privex.rpcemulator.bitcoin

Bitcoin RPC emulator - emulates a limited bitcoind JsonRPC API

While the emulation isn’t complete (at the time of writing), nor does it perfectly emulate bitcoind, it’s still very close, and implements methods such as sendtoaddress() with balance checking, address “validation”, and automatically stores the send transaction (and receive TX if internal address).

To allow the RPC to be usable immediately, three receive transactions are included by default inside of internal - allowing you to send from these addresses with no additional configuration.

  • 1PNgW6AgPZMys844kFS2dK4tt7F36MzLC8 has 0.10 BTC

  • 1CGzMWXH6JhSKrkrbcGhRtEJxrU1za23LW has 0.05 BTC

  • 13LWnGV7fGCUA2a9QiByGFKXL27H1HDuYp has 0.03 BTC

Basic Usage:

>>> from privex.rpcemulator.bitcoin import BitcoinEmulator
>>> btc_rpc = BitcoinEmulator()
>>> # make some queries to the RPC at https://127.0.0.1:8332
>>> from privex.jsonrpc import BitcoinRPC
>>> jr = BitcoinRPC()
>>> print('Balance is:', jr.getbalance())
>>> # once you're done, terminate the process
>>> btc_rpc.terminate()
class privex.rpcemulator.bitcoin.BitcoinEmulator(host='', port: int = 8332, background=True)[source]

Process manager class for the bitcoind emulator web server.

Without any constructor arguments, will fork into background at http://127.0.0.1:8332

By default, background is set to True, meaning it will launch as a sub-process, instead of blocking your application.

Using with a Context Manager:

By using BitcoinEmulator as a context manager, the JsonRPC server will be started before the first line inside of the with statement, and will automatically shutdown at the end of the with statement.

>>> from privex.rpcemulator.bitcoin import BitcoinEmulator
>>>
>>> with BitcoinEmulator():
...     # make some queries to the RPC at https://127.0.0.1:8332
...
>>> # Once the `with` statement is over, the JsonRPC server automatically shuts down

Alternative

You can create an instance of BitcoinEmulator normally, but you should make sure to call terminate() when you’re done with using the emulator.

This may be preferable when using inside of a unit test which has a setUpClass and tearDownClass method:

>>> from privex.rpcemulator.bitcoin import BitcoinEmulator
>>> btc_rpc = BitcoinEmulator()
>>> # make some queries to the RPC at https://127.0.0.1:8332
>>> # once you're done, terminate the process
>>> btc_rpc.terminate()
privex.rpcemulator.bitcoin.fake = <faker.generator.Generator object>

An instance of faker.Faker for generating fake data in functions such as j_gen_tx()

privex.rpcemulator.bitcoin.getbalance(account='*', confirmations: int = 0, watch_only=False)[source]

Get the balance of the RPC node, or an individual account.

Parameters
  • account (str) – Only get the balance for this account. "*" or "" will sum all accounts.

  • confirmations (str) – Only include transactions with at least this many confirmations

  • watch_only – NOT IMPLEMENTED

Return float balance

The total balance as a float

privex.rpcemulator.bitcoin.getblockchaininfo()[source]

Return bitcoind blockchain information, e.g. current block height

privex.rpcemulator.bitcoin.getnetworkinfo()[source]

Return bitcoind network information, e.g. coin daemon version

privex.rpcemulator.bitcoin.getnewaddress(account='', address_type=None)[source]

Generate a Bitcoin address. Note: this is simulated, it just pulls a random address from internal['addresses']

privex.rpcemulator.bitcoin.getreceivedbyaddress(address, confirmations: int = 0)[source]

Returns the total amount of coins received by address (excludes send transactions!)

privex.rpcemulator.bitcoin.internal = {'addresses': ['13LWnGV7fGCUA2a9QiByGFKXL27H1HDuYp', '12Q3qTYGfgYwFC8Df2bgR7SqrQ5LcvkmhV', '1CGzMWXH6JhSKrkrbcGhRtEJxrU1za23LW', '18VstwHr1CWYPremjpJWTDNQvJmrPbdoef', '1GrZfggs26g3MMfATeRZCt2nEMmMSpJtVb', '1Br7KPLQJFuS2naqidyzdciWUYhnMZAzKA', '1ni4jkof1JAiuG7r3cnnDaCh9pk1gXZCG', '1Zr95UjPJBrUM8yXojNCYEjiX7uvbg6vM', '12AAGLe6BCoTfH1sKBXyUkzhSADoNgreAY', '1eS2hvVhiiA56hKd5JVMu9GrYvyLqfZ6q', '1PiXyqVnqv3TjEmBNESU3ZcTktZUZyZqnz', '1ASCd3gLBkMUtXXgLSMESUjAakth5iqvHM', '18iHXvsy57NiNmC7rWRm5X6rW6DSzWPAhP', '1BNqgLyNTFbFjGLR4sQMDX8E1F3rM8KBzT', '1ALEM4xrGPjSfcmLGica1Ygf3gsy9oPJgP', '1PNgW6AgPZMys844kFS2dK4tt7F36MzLC8', '1JBLYpceHDrPkhzWvP4o5bPo7tFMHPEYJ3', '1GWh8RfFDZrD9ooSAUpNQhUsFyyHaRfUye', '1J2VishkhGviaEZA5dYgrqW1bjV8JGKFj', '1MuncCP7uUicoL7bouyemZ3XqL5fC33J5V'], 'external_addresses': ['13J8HRihYqEDYHAxLciryQYTjpxXcjYMmR', '165GagcJtj4LtvM94BDrM2nfBfnfX1gQxc', '17EZkTedEnhEHe6yyy48YX1goAuP92DMUy', '1L5mrvowocD5rZdHWSBeacBZzMxAeGY6Rj'], 'getblockchaininfo': {'bestblockhash': '00000000000000000000d6e50e9a20b98936b7833069a30e1e86c3d722d8a176', 'bip9_softforks': {}, 'blocks': 601440, 'chain': 'main', 'chainwork': '000000000000000000000000000000000000000009a65702bd04b8615352b4f7', 'difficulty': 13691480038694.45, 'headers': 601440, 'initialblockdownload': False, 'mediantime': 1572303763, 'pruned': False, 'size_on_disk': 279953979777, 'softforks': [], 'verificationprogress': 0.9999950714588575, 'warnings': ''}, 'getnetworkinfo': {'connections': 8, 'incrementalfee': 1e-05, 'localaddresses': [{'address': '127.0.0.1', 'port': 8333, 'score': 1}, {'address': '::1', 'port': 8333, 'score': 1}], 'localrelay': True, 'localservices': '000000000000040d', 'networkactive': True, 'networks': [{'name': 'ipv4', 'limited': False, 'reachable': True, 'proxy': '', 'proxy_randomize_credentials': False}, {'name': 'ipv6', 'limited': False, 'reachable': True, 'proxy': '', 'proxy_randomize_credentials': False}, {'name': 'onion', 'limited': True, 'reachable': False, 'proxy': '', 'proxy_randomize_credentials': False}], 'protocolversion': 70015, 'relayfee': 1e-05, 'subversion': '/Satoshi:0.17.1/', 'timeoffset': 0, 'version': 170100, 'warnings': ''}, 'transactions': [{'account': '', 'address': '1PNgW6AgPZMys844kFS2dK4tt7F36MzLC8', 'amount': Decimal('0.1'), 'category': 'receive', 'txid': 'db3f9b83bc7c53483e98a8714b61fc667772e1856333f290e2543186947ee939', 'confirmations': 5, 'time': 1572020407, 'label': '', 'vout': 0, 'generated': False}, {'account': '', 'address': '13LWnGV7fGCUA2a9QiByGFKXL27H1HDuYp', 'amount': Decimal('0.03'), 'category': 'receive', 'txid': 'fccacaffcb0a0a104274f1caa0b710e5a58b78f774629bfdcae99d544750e655', 'confirmations': 26, 'time': 1572279928, 'label': '', 'vout': 0, 'generated': False}, {'account': '', 'address': '1CGzMWXH6JhSKrkrbcGhRtEJxrU1za23LW', 'amount': Decimal('0.05'), 'category': 'receive', 'txid': 'e20ec2d1d56c7a2cc286a323ab4af4a990d9d23ca779ef1b0c0ad8e337e76d87', 'confirmations': 28, 'time': 1571928625, 'label': '', 'vout': 0, 'generated': False}]}

This module attribute is used as in-memory storage for various data, such as:

  • transactions - A list of incoming and outgoing wallet transactions. Some are pre-defined to ensure some addresses have a balance for immediate usage of the emulator.

  • addresses - Addresses in the emulated “wallet” that are owned by the emulated daemon

  • external_addresses - External/foreign addresses (i.e. not controlled by this wallet). Used for very basic address validation.

  • getblockchaininfo - Stores the dictionary that would be returned by a getblockchaininfo() call

  • getnetworkinfo - Stores the dictionary that would be returned by a getnetworkinfo() call

privex.rpcemulator.bitcoin.j_add_tx(account='', address=None, amount: Union[float, str, decimal.Decimal] = None, category: str = None, **kwargs)[source]

Generate a transaction using j_gen_tx() using the passed arguments, then store it into the transaction list.

Parameters
  • account – Wallet account to label the transaction under

  • addressOur address, that we’re sending from or receiving into.

  • amount – The amount of BTC transferred

  • category – Either 'receive' or 'send'

  • kwargs – Any additional dict keys to put into the TX data

Return dict tx

The generated TX

privex.rpcemulator.bitcoin.j_gen_tx(account='', address=None, amount=None, category=None, **kwargs)[source]

Generate a Bitcoin transaction and return it as a dict.

If any transaction attributes aren’t specified, fake data will be automatically generated using random or faker to fill the attributes.

Parameters
  • account – Wallet account to label the transaction under

  • addressOur address, that we’re sending from or receiving into.

  • amount – The amount of BTC transferred

  • category – Either 'receive' or 'send'

  • kwargs – Any additional dict keys to put into the TX data

Return dict tx

The generated TX

privex.rpcemulator.bitcoin.j_transactions(cast_decimal=<class 'float'>) → List[dict][source]

Returns internal['transactions'] with unserializable types such as Decimal casted appropriately.

This should be used instead of internal['transactions'] if returning TXs from the RPC.

Parameters

cast_decimal – A casting function to use to convert Decimal’s, e.g. float or str

Return List[dict] txs

A list of dict transactions, with values converted to allow JSON serialisation.

privex.rpcemulator.bitcoin.j_update_blockchaininfo(**kwargs)[source]

Update keys in the blockchaininfo using the kwargs

privex.rpcemulator.bitcoin.j_update_networkinfo(**kwargs)[source]

Update keys in the networkinfo using the kwargs

privex.rpcemulator.bitcoin.listtransactions(account='*', count: int = 10, skip: int = 0, watch_only=False)[source]

Simulates a Bitcoin RPC listtransactions call - returns a list of dictionary transactions from internal ['transactions']

Parameters
  • account – Account to list TXs for

  • count – Load this many recent TXs

  • skip – Skip this many recent TXs (for pagination)

  • watch_only – (NOT IMPLEMENTED)

Returns

[ {account, address, category, amount, label, vout, fee, confirmations, trusted, generated, txid, time, comment, to}, … ]

privex.rpcemulator.bitcoin.sendtoaddress(address, amount: Union[float, str, decimal.Decimal], comment='', comment_to='', subtractfee: bool = False)[source]

Sends amount BTC to address - generates a fake TX in internal transaction storage.

Example:

$ curl -v -s --data '{"method": "sendtoaddress",
    "params": ["1J2VishkhGviaEZA5dYgrqW1bjV8JGKFj", "0.001", "", "", false],
    "jsonrpc": "2.0", "id": 1}' http://127.0.0.1:5000

{"jsonrpc": "2.0", "result": "a4415c4013d2ba58106795ecb36a8694a3e93a4056e39ace4adde80d083c9641", "id": 1}
Parameters
  • address – The destination Bitcoin address

  • amount – The amount to send to address

  • comment (str) – A comment used to store what the transaction is for.

  • comment_to (str) – A comment, representing the name of the person or organization you’re sending to.

  • subtractfee (bool) – (Default False) If set to True, reduce the sending amount to cover the TX fee.

Returns

Attributes

Attributes

fake

An instance of faker.Faker for generating fake data in functions such as j_gen_tx()

internal

This module attribute is used as in-memory storage for various data, such as:

Classes

Classes

BitcoinEmulator([host, port, background])

Process manager class for the bitcoind emulator web server.

Functions

Functions

getbalance([account, confirmations, watch_only])

Get the balance of the RPC node, or an individual account.

getblockchaininfo()

Return bitcoind blockchain information, e.g.

getnetworkinfo()

Return bitcoind network information, e.g.

getnewaddress([account, address_type])

Generate a Bitcoin address.

getreceivedbyaddress(address[, confirmations])

Returns the total amount of coins received by address (excludes send transactions!)

j_add_tx([account, address, amount, category])

Generate a transaction using j_gen_tx() using the passed arguments, then store it into the transaction list.

j_gen_tx([account, address, amount, category])

Generate a Bitcoin transaction and return it as a dict.

j_transactions([cast_decimal])

Returns internal['transactions'] with unserializable types such as Decimal casted appropriately.

j_update_blockchaininfo(**kwargs)

Update keys in the blockchaininfo using the kwargs

j_update_networkinfo(**kwargs)

Update keys in the networkinfo using the kwargs

listtransactions([account, count, skip, …])

Simulates a Bitcoin RPC listtransactions call - returns a list of dictionary transactions from internal ['transactions']

sendtoaddress(address, amount[, comment, …])

Sends amount BTC to address - generates a fake TX in internal transaction storage.