Interacting with daemon

The module offers an interface to interact with Monero daemon. For the time being, like with wallet, the only available backend is JSON RPC.

In [1]: from monero.daemon import Daemon

In [2]: from monero.backends.jsonrpc import JSONRPCDaemon

In [3]: daemon = Daemon(JSONRPCDaemon(port=28081))

In [4]: daemon.height()
Out[4]: 1099108

Also, the info() method will return a dictionary with details about the current daemon status.

Sending prepared transactions

The daemon connection may be used for two-step sending of transactions. For example, you may want to check the fee before broadcasting the transaction to the network.

To prepare a transaction, use transfer() or transfer_multiple() method of the wallet or account, as described in the section about sending payments. The only difference is that now you want to add the relay=False argument.

In [5]: from monero.wallet import Wallet

In [6]: from monero.backends.jsonrpc import JSONRPCWallet

In [7]: wallet = Wallet(JSONRPCWallet(port=28088))

In [8]: wallet.balance()
Out[8]: Decimal('17.642325205670')

In [9]: txs = wallet.transfer('Bg1nUjsEx6UUByxr68o6gXcQRF58BpQyKauoZSo2HwubGErEnz9x6AS9o5ybmk3QmgeUpX3Msgm74QkwZKx2CeVWFrrZZqt', 10, relay=False)

Now the return value is a list of resulting transactions (usually just one) which may be inspected and validated.

In [10]: txs
Out[10]: [38964a0c8c3be041051464b413996ad8d696223dc34925d98156848ed76a3ae3]

In [11]: txs[0].fee
Out[11]: Decimal('0.003766080000')

If anything is not OK, just discard the transaction and create a new one. There’s no need to clean up anything in the wallet.

Once you have the transaction accepted, it’s time to post it to the daemon:

In [12]: result = daemon.send_transaction(txs[0])

In [13]: result
{'double_spend': False,
 'fee_too_low': False,
 'invalid_input': False,
 'invalid_output': False,
 'low_mixin': False,
 'not_rct': False,
 'not_relayed': False,
 'overspend': False,
 'reason': '',
 'status': 'OK',
 'too_big': False}

No batching due to double spends


The workflow described above should not be used for preparing a batch of transactions to be sent later. The wallet doesn’t remember which inputs have been spent and will very likely use the same in the next transaction, resulting in a double spend and broadcast failure.

The following example shows such behavior:

In [14]: txs1 = wallet.transfer('BYSXsmmK44xdjNVMGprUW5Yau9tsc9SAMJrQsANjGgpk2RB83cvVhWjZAgYNwLgmhdPawATh5q1CTEoLGKZSeZqtThefV7D', 1, relay=False)

In [15]: txs2 = wallet.transfer('Bd5m5wTjWdYSaLBKe4i2avJjuFLYMEUKpiiE86F83NFiDXKE7QseSRvS7efTtJu5xHiHm5XmxgB2mfLu7NFrG7e3UTYRzEf', 2, relay=False)

In [16]: txs1, txs2

In [17]: daemon.send_transaction(txs1[0])
{'double_spend': False,
 'fee_too_low': False,
 'invalid_input': False,
 'invalid_output': False,
 'low_mixin': False,
 'not_rct': False,
 'not_relayed': False,
 'overspend': False,
 'reason': '',
 'status': 'OK',
 'too_big': False}

In [18]: daemon.send_transaction(txs2[0])
TransactionBroadcastError                 Traceback (most recent call last)
<ipython-input-22-f24dc5d51c78> in <module>()
----> 1 daemon.send_transaction(txs2[0])

~/devel/monero-python/monero/ in send_transaction(self, tx, relay)
     11     def send_transaction(self, tx, relay=True):
---> 12         return self._backend.send_transaction(tx.blob, relay=relay)
     14     def mempool(self):

~/devel/monero-python/monero/backends/ in send_transaction(self, blob, relay)
     36         raise exceptions.TransactionBroadcastError(
     37                 "{status}: {reason}".format(**res),
---> 38                 details=res)
     40     def mempool(self):

TransactionBroadcastError: Failed: double spend

The second transaction failed because it used the same inputs as the previous one. The daemon checks all incoming transactions for possible double-spends and rejects them if such conflict is discovered.

API reference

class monero.daemon.Daemon(backend)

Monero daemon.

Provides interface do a daemon instance.

Parameters:backend – a daemon backend
headers(start_height, end_height=None)

Returns block headers for given height range. If no :param end_height: is given, it’s assumed to be equal to :param start_height:

Return type:list of dict

Return daemon’s chain height.

Return type:int

Returns basic information about the daemon.

Return type:dict

Returns current mempool contents.

Return type:list of Transaction
send_transaction(tx, relay=True)

Sends a transaction generated by a Wallet.

  • txTransaction
  • relay – whether to relay the transaction to peers. If False, the daemon will have to mine the transaction itself in order to have it included in the blockchain.