import asyncio
from test_framework.util import (
assert_equal,
assert_raises_async,
wait_for,
)
from test_framework.electrumutil import (
ElectrumTestFramework,
)
from test_framework.constants import COIN
from test_framework.environment import on_bch, on_nex
from test_framework.serialize import to_hex
from test_framework.connectrum.exc import ElectrumErrorResponse
from test_framework.electrumconnection import ElectrumConnection
if on_bch():
from test_framework.bch.nodemessages import CTransaction, CTxIn, COutPoint
elif on_nex():
from test_framework.nex.nodemessages import CTransaction, CTxIn, COutPoint
else:
raise NotImplementedError()
class ElectrumBasicTests(ElectrumTestFramework):
async def run_test(self):
n = self.nodes[0]
self.info("Checking that blocks are indexed")
n.generate(200)
electrum_client = ElectrumConnection()
try:
await electrum_client.connect()
await self.test_mempoolsync(n, electrum_client)
await self.test_unknown_method(electrum_client)
await self.test_invalid_args(electrum_client)
await self.test_address_balance(n, electrum_client)
finally:
electrum_client.disconnect()
async def test_mempoolsync(self, n, cli):
await self.sync_all(cli, n)
self.info("Check that mempool is communicated")
n.sendtoaddress(n.getnewaddress(), 10)
assert_equal(1, len(n.getrawtxpool()))
await self.wait_for_mempool_count(cli, count=1)
n.generate(1)
await self.sync_height(cli)
assert_equal(0, len(n.getrawtxpool()))
await self.wait_for_mempool_count(cli, count=0)
async def test_unknown_method(self, electrum_client):
await assert_raises_async(
ElectrumErrorResponse,
electrum_client.call,
"method.that.does.not.exist",
42,
)
try:
await electrum_client.call("method.that.does.not.exist")
except ElectrumErrorResponse as e:
error_code = "-32601"
assert error_code in str(e)
async def test_invalid_args(self, electrum_client):
error_code = "-32602"
hash_param_methods = (
"blockchain.scripthash.get_balance",
"blockchain.scripthash.get_history",
"blockchain.scripthash.listunspent",
)
for method in hash_param_methods:
await assert_raises_async(
ElectrumErrorResponse, electrum_client.call, method, "invalidhash"
)
try:
await electrum_client.call(method, "invalidhash")
except ElectrumErrorResponse as e:
print("ERROR:" + str(e))
assert error_code in str(e)
try:
tx = CTransaction()
if on_nex():
tx.vin = [CTxIn(COutPoint().from_idem_and_idx(0xF00D, 0))]
else:
tx.vin = [CTxIn(COutPoint(0xF00D, 0))]
tx.rehash()
await electrum_client.call("blockchain.transaction.broadcast", to_hex(tx))
except Exception as e:
assert error_code in str(e), e
async def test_address_balance(self, n, electrum_client):
addr = n.getnewaddress()
n.sendtoaddress(addr, 10)
async def check_address(address, unconfirmed=0, confirmed=0):
res = await electrum_client.call("blockchain.address.get_balance", address)
print(res, "vs", unconfirmed * COIN)
return (
res["unconfirmed"] == unconfirmed * COIN
and res["confirmed"] == confirmed * COIN
)
async def check_unconfirmed_balance():
return await check_address(addr, unconfirmed=10)
async def check_confirmed_balance():
return await check_address(addr, confirmed=10)
await wait_for(10, check_unconfirmed_balance)
n.generate(1)
await wait_for(10, check_confirmed_balance)
if __name__ == "__main__":
asyncio.run(ElectrumBasicTests().main())