Exemplo n.º 1
0
    async def sendfrom(self,
                       fromaccount,
                       toaddress,
                       amount,
                       minconf=1,
                       comment="",
                       comment_to=""):
        """sendfrom "fromaccount" "toaddress" amount ( minconf "comment" "comment_to" )

DEPRECATED (use sendtoaddress). Sent an amount from an account to a ethereum address.
Requires wallet passphrase to be set with walletpassphrase call.

Arguments:
1. "fromaccount"       (string, required) The name of the account to send funds from. May be the default account using "".
                       Specifying an account does not influence coin selection, but it does associate the newly created
                       transaction with the account, so the account's balance computation and transaction history can reflect
                       the spend.
2. "toaddress"         (string, required) The ethereum address to send funds to.
3. amount                (numeric or string, required) The amount in BTC (transaction fee is added on top).
4. minconf               (numeric, optional, default=1) Only use funds with at least this many confirmations.
5. "comment"           (string, optional) A comment used to store what the transaction is for. 
                                     This is not part of the transaction, just kept in your wallet.
6. "comment_to"        (string, optional) An optional comment to store the name of the person or organization 
                                     to which you're sending the transaction. This is not part of the transaction, 
                                     it is just kept in your wallet.

Result:
"txid"                 (string) The transaction id.

Examples:

Send 0.01 ETH from the coinbase account to the address, must have at least 1 confirmation
> ethereum-cli sendfrom "" "0xc729d1e61e94e0029865d759327667a6abf0cdc5" 0.01

Send 0.01 from the tabby account to the given address, funds must have at least 6 confirmations
> ethereum-cli sendfrom "tabby" "0xc729d1e61e94e0029865d759327667a6abf0cdc5" 0.01 6 "donation" "seans outpost"

As a json rpc call
> curl -X POST -H 'Content-Type: application/json' -d '{"jsonrpc": "1.0", "id":"curltest", "method": "sendfrom", "params": ["0xc729d1e61e94e0029865d759327667a6abf0cdc5", 0.01, 6, "donation", "seans outpost"] }'  http://127.0.0.01:9500/
        """
        # TODO: add default fromaccount if empty as coinbase
        # TODO: Add amount and address validation
        # TODO: Add minconf logic
        gas = await self._paytxfee_to_etherfee()
        try:
            return await self._rpc.eth_sendTransaction(
                fromaccount,  # from ???
                toaddress,  # to
                gas['gas_amount'],  # gas amount
                gas['gas_price'],  # gas price
                ether_to_wei(float(amount)),  # value
            )
        except BadResponseError as e:
            if (e.code == -32000 and 'gas * price + value' in e.msg):
                raise BadResponseError('Insufficient funds', code=-6)
            raise
Exemplo n.º 2
0
    async def test_method__poll_with_reconnect_when_droped(self):
        with patch('ethereumd.poller.Poller.poll'):
            poller = Poller(self.rpc_proxy)

        with patch.object(AsyncIOHTTPClient,
                          '_call',
                          side_effect=return_once(
                              lambda: BadResponseError('test', code=-99999999),
                              then=fake_call())):
            poller._pending = '0x6f4111062b3db311e6521781f4ef0046'
            await poller._poll_with_reconnect('pending')
Exemplo n.º 3
0
    async def getblockhash(self, height):
        """getblockhash height

Returns hash of block in best-block-chain at height provided.

Arguments:
1. height         (numeric, required) The height index

Result:
"hash"         (string) The block hash

Examples:
> ethereum-cli getblockhash 1000
> curl -X POST -H 'Content-Type: application/json' -d '{"jsonrpc": "1.0", "id":"curltest", "method": "getblockhash", "params": [1000] }'  http://127.0.0.01:9500/
        """
        if height < 0:
            raise BadResponseError('Block height out of range', code=-8)

        block = await self._rpc.eth_getBlockByNumber(height)
        if block is None:
            raise BadResponseError('Block height out of range', code=-8)

        return block['hash']
Exemplo n.º 4
0
    async def getbestblockhash(self):
        """getbestblockhash

Returns the hash of the best (tip) block in the longest blockchain.

Result:
"hex"      (string) the block hash hex encoded

Examples:
> ethereum-cli getbestblockhash 
> curl -X POST -H 'Content-Type: application/json' -d '{"jsonrpc": "1.0", "id":"curltest", "method": "getbestblockhash", "params": [] }'  http://127.0.0.01:9500/
        """
        # TODO: What happen when no blocks in db?
        block = await self._rpc.eth_getBlockByNumber(tx_objects=False)
        if block is None:
            raise BadResponseError('Block not found', code=-5)

        return block['hash']
Exemplo n.º 5
0
    async def settxfee(self, amount):
        """settxfee amount

Set the transaction fee for transactions only. Overwrites the paytxfee parameter.

Arguments:
1. amount         (numeric or string, required) The transaction fee in ether

Result
true|false        (boolean) Returns true if successful

Examples:
> ethereum-cli settxfee 0.00042
> curl -X POST -H 'Content-Type: application/json' -d '{"jsonrpc": "1.0", "id":"curltest", "method": "settxfee", "params": [0.00042] }'  http://127.0.0.01:9500/
        """
        if isinstance(amount, (int, float)) and amount <= 0:
            raise BadResponseError('Amount out of range', code=-3)

        try:
            self._paytxfee = float(amount)
        except Exception:
            return False
        else:
            return True
Exemplo n.º 6
0
    def _wrapper(method, params=None, _id=None):
        params = params or []
        if method == 'eth_accounts':
            return (["0xf5041fe398062cd63b62bd9b5df9942d30c9b8ca"]
                    if _allowed_method(method) else [])
        elif method == 'eth_getTransactionByHash':
            if len(params) < 1:
                raise BadResponseError(
                    'missing value for required argument %s' % len(params),
                    code=-32602)
            return {
                'blockHash': '0x6d18d84c577f99f8073c80ad5200c3da0e5a64de98b4c07cb2d84a8786682360',
                'blockNumber': '0x63a',
                'from': '0xf5041fe398062cd63b62bd9b5df9942d30c9b8ca',
                'gas': '0x15f90',
                'gasPrice': '0x0',
                'hash': params[0],
                'input': '0x',
                'nonce': '0x39',
                'r': '0x1b1316134fca8c9c0a82e884b9c96a8746a6b636c93d31abeab7dab290ba3bcb',
                's': '0x64f4f8b5e19b3a7dedc92c16e0c5b1a5b49240cb42960001e69ab70e7d3005e4',
                'to': '0x85521e2663efd02fef594a9b90b0dbe3aec590ac',
                'transactionIndex': '0x0',
                'v': '0xa95',
                'value': '0xde0b6b3a7640000'
            } if _allowed_method(method) else None
        elif method == 'eth_getBlockByHash':
            if len(params) < 2:
                raise BadResponseError(
                    'missing value for required argument %s' % len(params),
                    code=-32602)
            return {
                'difficulty': '0x3cd85',
                'extraData': '0xd783010606846765746887676f312e382e31856c696e7578',
                'gasLimit': '0x47e7c4',
                'gasUsed': '0x5208',
                'hash': params[0],
                'logsBloom': '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
                'miner': '0xf5041fe398062cd63b62bd9b5df9942d30c9b8ca',
                'mixHash': '0x048ee8d2ad79623956c5fe5f11056e92693fc89bbbce90dc67d80010e7daebd0',
                'nonce': '0x64ace968fdc0f3a4',
                'number': '0x63a',
                'parentHash': '0x01dd4dd0522d5f526c62d5fded6db9ff99583ae6b3acf5f7fafd9fa66446be1a',
                'receiptsRoot': '0x42bc6d46087014a68b0d8a0db658e00ed254f752e27afb5091b28e4466177b4e',
                'sha3Uncles': '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
                'size': '0x288',
                'stateRoot': '0xd8563b7fab1224c1606edbccc807aef3a6578e6ace89c1d72b6ab3d44208edde',
                'timestamp': '0x5981bf5e',
                'totalDifficulty': '0x11f5bb1f',
                'transactions': [],
                'transactionsRoot': '0x95bc25f9816a11ccc1b136d5655fc24824dce14c06a4aa0602f02441085347f4',
                'uncles': []
            } if _allowed_method(method) else None
        elif method == 'eth_newBlockFilter':
            return ('0x6f4111062b3db311e6521781f4ef0046'
                    if _allowed_method(method) else None)
        elif method == 'eth_newPendingTransactionFilter':
            return ('0x967e6ebd52c48adce994057695090fe'
                    if _allowed_method(method) else None)
        elif method == 'eth_getFilterChanges':
            if len(params) < 1:
                raise BadResponseError(
                    'missing value for required argument %s' % len(params),
                    code=-32602)

            return (['0x9c864dd0e7fdcfb3bd7197020ac311cbacef1aa29b49791223427bbedb6d36ad']
                    if _allowed_method(method) else [])
        else:
            raise BadResponseError(
                'The method %s does not exist/is not available' % method,
                code=-32601)
Exemplo n.º 7
0
    async def getblock(self, blockhash, verbose=True):
        """getblock "blockhash" ( verbose )

If verbose is false, returns a string that is serialized, hex-encoded data for block 'hash'.
If verbose is true, returns an Object with information about block <hash>.

Arguments:
1. "blockhash"          (string, required) The block hash
2. verbose                (boolean, optional, default=true) true for a json object, false for the hex encoded data

Result (for verbose = true):
{
  "hash" : "hash",     (string) the block hash (same as provided)
  "confirmations" : n,   (numeric) The number of confirmations, or -1 if the block is not on the main chain
  "size" : n,            (numeric) The block size
  "strippedsize" : n,    (numeric) The block size excluding witness data
  "weight" : n           (numeric) The block weight
  "height" : n,          (numeric) The block height or index
  "version" : n,         (numeric) The block version
  "versionHex" : "00000000", (string) The block version formatted in hexadecimal
  "merkleroot" : "xxxx", (string) The merkle root
  "tx" : [               (array of string) The transaction ids
     "transactionid"     (string) The transaction id
     ,...
  ],
  "time" : ttt,          (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)
  "mediantime" : ttt,    (numeric) The median block time in seconds since epoch (Jan 1 1970 GMT)
  "nonce" : n,           (numeric) The nonce
  "bits" : "1d00ffff", (string) The bits
  "difficulty" : x.xxx,  (numeric) The difficulty
  "chainwork" : "xxxx",  (string) Expected number of hashes required to produce the chain up to this block (in hex)
  "previousblockhash" : "hash",  (string) The hash of the previous block
  "nextblockhash" : "hash"       (string) The hash of the next block
}

Result (for verbose=false):
"data"             (string) A string that is serialized, hex-encoded data for block 'hash'.

Examples:
> ethereum-cli getblock "0x8b22f9aa6c27231fb4acc587300abadd259f501ba99ef18d11e9e4dfa741eb39"
> curl -X POST -H 'Content-Type: application/json' -d '{"jsonrpc": "1.0", "id":"curltest", "method": "getblock", "params": ["0x8b22f9aa6c27231fb4acc587300abadd259f501ba99ef18d11e9e4dfa741eb39"] }'  http://127.0.0.01:9500/
        """
        block = await self._rpc.eth_getBlockByHash(blockhash, False)
        if block is None:
            raise BadResponseError('Block not found', code=-5)

        if not verbose:
            return block['hash']

        next_block, confirmations = await asyncio.gather(
            self._rpc.eth_getBlockByNumber(
                hex_to_dec(block['number']) + 1, False),
            self._get_confirmations(block),
        )

        data = {
            'hash': block['hash'],
            'confirmations': (await self._get_confirmations(block)),
            'strippedsize': None,
            'size': None,
            'weight': None,
            'height': None,
            'version': None,
            'versionHex': None,
            'merkleroot': None,
            'tx': block['transactions'],
            'time': hex_to_dec(block['timestamp']),
            'mediantime': None,
            'nonce': hex_to_dec(block['nonce']),
            'bits': None,
            'difficulty': hex_to_dec(block['totalDifficulty']),
            'chainwork': None,
            'previousblockhash': block['parentHash']
        }
        if next_block:
            data['nextblockhash'] = next_block['hash']
        return data
Exemplo n.º 8
0
    async def gettransaction(self, txid, include_watchonly=False):
        """gettransaction "txid" ( include_watchonly )

Get detailed information about in-wallet transaction <txid>

Arguments:
1. "txid"                  (string, required) The transaction id
2. "include_watchonly"     (bool, optional, default=false) DEPRECATED. Whether to include watch-only addresses in balance calculation and details[]

Result:
{
  "amount" : x.xxx,        (numeric) The transaction amount in BTC
  "fee": x.xxx,            (numeric) The amount of the fee in BTC. This is negative and only available for the
                              'send' category of transactions.
  "confirmations" : n,     (numeric) The number of confirmations
  "blockhash" : "hash",  (string) The block hash
  "blockindex" : xx,       (numeric) The index of the transaction in the block that includes it
  "blocktime" : ttt,       (numeric) The time in seconds since epoch (1 Jan 1970 GMT)
  "txid" : "transactionid",   (string) The transaction id.
  "time" : ttt,            (numeric) The transaction time in seconds since epoch (1 Jan 1970 GMT)
  "timereceived" : ttt,    (numeric) The time received in seconds since epoch (1 Jan 1970 GMT)
  "details" : [
    {
      "address" : "address",          (string) The ethereum address involved in the transaction
      "category" : "send|receive",    (string) The category, either 'send' or 'receive'
      "amount" : x.xxx,                 (numeric) The amount in BTC
      "label" : "label",              (string) A comment for the address/transaction, if any
      "vout" : n,                       (numeric) the vout value
      "fee": x.xxx,                     (numeric) The amount of the fee in BTC. This is negative and only available for the
                                           'send' category of transactions.
      "abandoned": xxx                  (bool) 'true' if the transaction has been abandoned (inputs are respendable). Only available for the
                                           'send' category of transactions.
    }
    ,...
  ],
  "hex" : "data"         (string) Raw data for transaction
}

Examples:
> ethereum-cli gettransaction "0xa4cb352eaff243fc962db84c1ab9e180bf97857adda51e2a417bf8015f05def3"
> ethereum-cli gettransaction "0xa4cb352eaff243fc962db84c1ab9e180bf97857adda51e2a417bf8015f05def3" true
> curl -X POST -H 'Content-Type: application/json' -d '{"jsonrpc": "1.0", "id":"curltest", "method": "gettransaction", "params": ["0xa4cb352eaff243fc962db84c1ab9e180bf97857adda51e2a417bf8015f05def3"] }'  http://127.0.0.01:9500/
        """
        # TODO: Make workable include_watchonly flag
        transaction, addresses = await asyncio.gather(
            self._rpc.eth_getTransactionByHash(txid), self._rpc.eth_accounts())
        if transaction is None:
            raise BadResponseError('Invalid or non-wallet transaction id',
                                   code=-5)

        trans_info = {
            'amount': wei_to_ether(hex_to_dec(transaction['value'])),
            'blockhash': transaction['blockHash'],
            'blockindex': None,
            'blocktime': None,
            'confirmations': 0,
            'trusted': None,
            'walletconflicts': [],
            'txid': transaction['hash'],
            'time': None,
            'timereceived': None,
            'details': [],
            'hex': transaction['input'],
            'fee': DEFAUT_FEE,
        }
        if hex_to_dec(transaction['blockHash']) != 0:
            block = await self.getblock(transaction['blockHash'])
            trans_info['confirmations'] = block['confirmations']
        else:
            trans_info['confirmations'] = 0
        if transaction['to'] in addresses:
            trans_info['details'].append({
                'address': transaction['to'],
                'category': 'receive',
                'amount': trans_info['amount'],
                'label': '',
                'vout': 1
            })
        if transaction['from'] in addresses:
            from_ = {
                'address': transaction['to'],
                'category': 'send',
                'amount': operator.neg(trans_info['amount']),
                'vout': 1,
                'abandoned': False,
                'fee': DEFAUT_FEE,
            }
            if hex_to_dec(transaction['blockHash']):
                tr_hash, tr_receipt = await asyncio.gather(
                    self._rpc.eth_getTransactionByHash(transaction['hash']),
                    self._rpc.eth_getTransactionReceipt(transaction['hash']))
                from_['fee'] = (
                    hex_to_dec(tr_hash['gasPrice']) *
                    wei_to_ether(hex_to_dec(tr_receipt['gasUsed'])))
            trans_info['details'].append(from_)
        return trans_info
Exemplo n.º 9
0
    async def listsinceblock(self,
                             blockhash,
                             target_confirmations=1,
                             include_watchonly=False):
        """listsinceblock ( "blockhash" target_confirmations include_watchonly)

Get all transactions in blocks since block [blockhash]

Arguments:
1. "blockhash"            (string, required) The block hash to list transactions since
2. target_confirmations:    (numeric, optional) The confirmations required, must be 1 or more
3. include_watchonly:       (bool, optional, default=false) Include transactions to watch-only addresses (see 'importaddress')
Result:
{
  "transactions": [
    "address":"address",    (string) The ethereum address of the transaction. Not present for move transactions (category = move).
    "category":"send|receive",     (string) The transaction category. 'send' has negative amounts, 'receive' has positive amounts.
    "amount": x.xxx,          (numeric) The amount in BTC. This is negative for the 'send' category, and for the 'move' category for moves
                                          outbound. It is positive for the 'receive' category, and for the 'move' category for inbound funds.
    "vout" : n,               (numeric) the vout value
    "fee": x.xxx,             (numeric) The amount of the fee in BTC. This is negative and only available for the 'send' category of transactions.
    "confirmations": n,       (numeric) The number of confirmations for the transaction. Available for 'send' and 'receive' category of transactions.
                                          When it's < 0, it means the transaction conflicted that many blocks ago.
    "blockhash": "hashvalue",     (string) The block hash containing the transaction. Available for 'send' and 'receive' category of transactions.
    "blockindex": n,          (numeric) The index of the transaction in the block that includes it. Available for 'send' and 'receive' category of transactions.
    "blocktime": xxx,         (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).
    "txid": "transactionid",  (string) The transaction id. Available for 'send' and 'receive' category of transactions.
    "time": xxx,              (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT).
    "timereceived": xxx,      (numeric) The time received in seconds since epoch (Jan 1 1970 GMT). Available for 'send' and 'receive' category of transactions.
    "abandoned": xxx,         (bool) 'true' if the transaction has been abandoned (inputs are respendable). Only available for the 'send' category of transactions.
    "comment": "...",       (string) If a comment is associated with the transaction.
    "label" : "label"       (string) A comment for the address/transaction, if any
    "to": "...",            (string) If a comment to is associated with the transaction.
  ],
  "lastblock": "lastblockhash"     (string) The hash of the last block
}

Examples:
> ethereum-cli listsinceblock
> ethereum-cli listsinceblock "0x2a7f92d11cf8194f2bc8976e0532a9d7735e60e99e3339cb2316bd4c5b4137ce"
> curl -X POST -H 'Content-Type: application/json' -d '{"jsonrpc": "1.0", "id":"curltest", "method": "listsinceblock", "params": ["0x2a7f92d11cf8194f2bc8976e0532a9d7735e60e99e3339cb2316bd4c5b4137ce"] }'  http://127.0.0.01:9500/
        """
        # TODO: Optimization??
        # TODO: Correct return data
        if target_confirmations < 1:
            raise BadResponseError('Invalid parameter', code=-8)
        transactions = []

        latest_block, from_block, addresses = await asyncio.gather(
            self._rpc.eth_getBlockByNumber(),
            self._rpc.eth_getBlockByHash(blockhash), self._rpc.eth_accounts())
        if target_confirmations == 1:
            lst_hash = await self.getbestblockhash()
        else:
            need_height = hex_to_dec(latest_block['number']) + 1 - \
                target_confirmations
            lst_hash = (await
                        self._rpc.eth_getBlockByNumber(need_height))['hash']
        if not from_block:
            return {
                'transactions': transactions,
                'lastblock': lst_hash,
            }

        start_height = hex_to_dec(from_block['number']) + 1
        end_height = hex_to_dec(latest_block['number'])

        def _fetch_block_transacs(addresses, block, tr):
            category = None
            if tr['from'] in addresses:
                address = tr['to']
                category = 'send'
            elif tr['to'] in addresses:
                address = tr['to']
                category = 'receive'

            if category:
                return {
                    'address':
                    address,
                    'category':
                    category,
                    'amount':
                    wei_to_ether(hex_to_dec(tr['value'])),
                    'vout':
                    1,
                    'fee': (hex_to_dec(tr['gasPrice']) *
                            wei_to_ether(hex_to_dec(tr['gas']))),
                    'confirmations':
                    (end_height + 1 - hex_to_dec(tr['blockNumber'])),
                    'blockhash':
                    tr['blockHash'],
                    'blockindex':
                    None,  # TODO
                    'blocktime':
                    hex_to_dec(block['timestamp']),
                    'txid':
                    tr['hash'],
                    'time':
                    hex_to_dec(block['timestamp']),
                    'timereceived':
                    None,  # TODO
                    'abandoned':
                    False,  # TODO
                    'comment':
                    None,  # TODO
                    'label':
                    None,  # TODO
                    'to':
                    None,  # TODO
                }

        blocks = [from_block]
        blocks.extend(
            filter(
                lambda b: b is not None, await
                asyncio.gather(*(self._rpc.eth_getBlockByNumber(height)
                                 for height in range(start_height, end_height))
                               )))
        blocks.append(latest_block)
        for block in blocks:
            for tr in block['transactions']:
                if not (tr['to'] in addresses and tr['from'] in addresses):
                    fetched_tr = _fetch_block_transacs(addresses, block, tr)
                    if fetched_tr:
                        transactions.append(fetched_tr)

        return {
            'transactions': transactions,
            'lastblock': lst_hash,
        }
Exemplo n.º 10
0
 def _raise_error():
     raise BadResponseError('test', code=-99999999)