def __init__(self, balance): """ :param balance: binance balance object :type balance: a dict contains: free, frozen, locked, symbol """ asset = Asset(BNBCHAIN, balance['symbol']) super().__init__(asset, balance['free'])
def parse_tx(tx: Transaction): """Parse tx :param tx: The transaction to be parsed :type tx: str :returns: The transaction parsed from the binance tx """ asset = Asset.from_str(f'{BITCOINCASH}.BCH') tx_from = [tx_types.TxFrom(i.address, i.value * 10**-8) for i in tx.inputs] tx_to = [tx_types.TxTo(i.address, i.value * 10**-8) for i in tx.outputs] tx_date = datetime.datetime.fromtimestamp(tx.time) tx_type = 'transfer' tx_hash = tx.txid tx = tx_types.TX(asset, tx_from, tx_to, tx_date, tx_type, tx_hash) return tx
def parse_tx(tx): """Parse tx :param tx: The transaction to be parsed :type tx: str :returns: The transaction parsed from the binance tx """ asset = Asset.from_str(f'{BTCCHAIN}.BTC') tx_from = [tx_types.TxFrom(i['address'], i['value']) for i in tx['inputs']] tx_to = [tx_types.TxTo(i['address'], i['value']) for i in tx['outputs']] tx_date = datetime.datetime.fromtimestamp(tx['time']) tx_type = 'transfer' tx_hash = tx['txid'] tx = tx_types.TX(asset, tx_from, tx_to, tx_date, tx_type, tx_hash) return tx
async def get_balance(self, address: str = None): """Get the LTC balance of a given address :param address: By default, it will return the balance of the current wallet. (optional) :type address: str :returns: The BTC balance of the address. """ try: amount = await sochain_api.get_balance( self.sochain_url, self.net, address or self.get_address()) if amount == None: raise Exception("Invalid Address") balance = Balance(Asset.from_str('LTC.LTC'), amount) return balance except Exception as err: raise Exception(str(err))
def parse_tx(tx): """Parse tx :param tx: The transaction to be parsed :type tx: str :returns: The transaction parsed from the binance tx """ asset = Asset.from_str(f'BNB.{tx["txAsset"]}') tx_from = [tx_types.TxFrom(tx['fromAddr'], tx['value'])] tx_to = [tx_types.TxTo(tx['toAddr'], tx['value'])] tx_date = datetime.datetime.strptime(tx['timeStamp'], "%Y-%m-%dT%H:%M:%S.%fz") tx_type = get_tx_type(tx['txType']) tx_hash = tx['txHash'] tx = tx_types.TX(asset, tx_from, tx_to, tx_date, tx_type, tx_hash) return tx
async def get_balance(self, address: str = ""): """Get the BCH balance of a given address :param address: By default, it will return the balance of the current wallet. (optional) :type address: str :returns: The BCH balance of the address :raises: "Invalid address" if the given address is an invalid address """ try: account = await haskoin_api.get_account( self.get_client_url(), address or self.get_address()) if not account: raise Exception("Invalid Address") balance = Balance(Asset.from_str("BCH.BCH"), account.confirmed * 10**-8) return balance except Exception as err: raise Exception(str(err))
class TestAsset: bnb_asset = Asset('BNB', 'BNB', 'BNB') def test_create_asset(self): asset = Asset('BNB', 'RUNE-67C') assert asset.chain == 'BNB' assert asset.symbol == 'RUNE-67C' assert asset.ticker == 'RUNE' def test_invalid_chain(self): with pytest.raises(Exception) as err: Asset('invalid chain', 'BNB', 'BNB') assert str(err.value) == "the chain is invalid" def test_asset_to_string(self): asset = Asset('BNB', 'RUNE-67C', 'RUNE') assert str(asset) == 'BNB.RUNE-67C' def test_asset_equal(self): asset = Asset('BNB', 'RUNE-67C', 'RUNE') asset2 = Asset('BNB', 'RUNE-67C', 'RUNE') assert asset == asset2
class TestClient: phrase = 'rural bright ball negative already grass good grant nation screen model pizza' mainnetaddress = 'thor19kacmmyuf2ysyvq3t9nrl9495l5cvktjs0yfws' testnetaddress = 'tthor19kacmmyuf2ysyvq3t9nrl9495l5cvktj5c4eh4' rune_asset = Asset('THOR', 'RUNE', 'RUNE') phraseForTX = 'history dice polar glad split follow tired invest lemon mask all industry' testnetaddressForTx = 'tthor103nyx8erew2tc5knfcj7se5hsvvmr4ew7fpn4t' testnetTransfer = 'tthor1pttyuys2muhj674xpr9vutsqcxj9hepy4ddueq' sampleTX = '8A2EC1EE711D1057594FAA9F7F82B6E0D726745F4E88372F6FFACC38C36D234B' transfer_amount = 0.01 single_tx_fee = 10000000 transfer_fee = {'average': single_tx_fee, 'fast': single_tx_fee, 'fastest': single_tx_fee } @pytest.fixture def client(self): self.client = Client(self.phrase, network='mainnet') yield self.client.purge_client() def test_empty_wallet_main(self): client = Client(self.phrase, network= 'mainnet') address_main = client.get_address() assert address_main == self.mainnetaddress def test_empty_wallet_test(self): client = Client(self.phrase, network= 'testnet') address_test = client.get_address() assert address_test == self.testnetaddress def test_invalid_phrase(self): with pytest.raises(Exception) as err: assert Client(phrase= 'invalid phrase') assert str(err.value) == "invalid phrase" def test_right_address(self, client): assert self.client.get_address() == self.mainnetaddress def test_update_net(self, client): self.client.set_network('testnet') assert self.client.get_network() == 'testnet' assert self.client.get_address() == self.testnetaddress def test_set_phrase_return_address(self, client): assert self.client.set_phrase(self.phrase) == self.mainnetaddress self.client.set_network('testnet') assert self.client.set_phrase(self.phrase) == self.testnetaddress @pytest.mark.asyncio async def test_has_no_balances(self, client): assert await self.client.get_balance() == [] @pytest.mark.asyncio async def test_has_balances(self, client): self.client.set_network('testnet') assert await self.client.get_balance() @pytest.mark.asyncio async def test_balance_has_correct_asset(self, client): self.client.set_network('testnet') balance = await self.client.get_balance(self.testnetaddress) assert 'THOR.' + str(balance[0]['asset']).upper() == str(self.rune_asset) assert balance[0]['amount'] == '0.9799' @pytest.mark.asyncio async def test_should_broadcast_transfer(self, client): self.client.set_network('testnet') self.client.set_phrase(self.phraseForTX) assert self.client.get_address() == self.testnetaddressForTx before_balance = await self.client.get_balance() assert len(before_balance) == 1 before_balance_amount = before_balance[0]['amount'] await self.client.transfer(amount=self.transfer_amount, recipient=self.testnetTransfer, asset=self.rune_asset) after_balance = await self.client.get_balance() after_balance_amount = after_balance[0]['amount'] assert round((float(before_balance_amount) - float(after_balance_amount)) * 10**8) == 3000000 @pytest.mark.asyncio async def test_should_raise_exception_if_input_amount_higher_than_balance(self , client): self.client.set_network('testnet') self.client.set_phrase(self.phraseForTX) before_balance = await self.client.get_balance() before_balance_amount = before_balance[0]['amount'] send_amount = float(before_balance_amount) + 1 with pytest.raises(Exception) as err: assert await self.client.transfer(amount=send_amount, recipient=self.testnetaddressForTx, asset=self.rune_asset) assert str(err.value) == "input asset amout is higher than current (asset balance - transfer fee)" @pytest.mark.asyncio async def test_get_transfer_fees(self, client): self.client.set_network('testnet') fee = await self.client.get_fees() assert fee['average'] == str(self.transfer_fee['average']) assert fee['fast'] == str(self.transfer_fee['fast']) assert fee['fastest'] == str(self.transfer_fee['fastest']) def test_validate_address(self, client): assert self.client.validate_address(self.testnetaddress, 'tthor') == True def test_validate_address_false_address(self, client): assert self.client.validate_address(self.testnetaddress + '1', 'tthor') == False def test_validate_address_false_prefix(self, client): assert self.client.validate_address(self.testnetaddress, 'thor') == False @pytest.mark.asyncio async def test_get_transaction_data(self, client): self.client.set_network('testnet') try: transaction = await self.client.get_transaction_data(self.sampleTX) assert transaction except Exception as err: assert str(err) == 'transaction not found' # no transaction found
class TestLiteCoinClient: phrase = 'atom green various power must another rent imitate gadget creek fat then' phrase_one = 'atom green various power must another rent imitate gadget creek fat then' testnetaddress = 'tltc1q2pkall6rf6v6j0cvpady05xhy37erndv05de7g' ltc_asset = Asset('LTC', 'LTC') memo = 'SWAP:THOR.RUNE' # phraseTwo = 'green atom various power must another rent imitate gadget creek fat then' address_two = 'tltc1ql68zjjdjx37499luueaw09avednqtge4u23q36' # Third ones is used only for balance verification phrase_three = 'quantum vehicle print stairs canvas kid erode grass baby orbit lake remove' address_three = 'tltc1q04y2lnt0ausy07vq9dg5w2rnn9yjl3rz364adu' @pytest.fixture def client(self): self.client = Client(self.phrase, network='testnet') yield self.client.purge_client() def test_right_address(self, client): assert self.client.get_address() == self.testnetaddress def test_invalid_phrase(self): with pytest.raises(Exception) as err: assert Client(phrase='Invalid Phrase') assert str(err.value) == "Invalid Phrase" def test_right_phrase(self, client): assert self.client.set_phrase(self.phrase) == self.testnetaddress def test_validate_address(self, client): assert self.client.validate_address(network=self.client.net, address=self.testnetaddress) @pytest.mark.asyncio async def test_has_balances(self, client): assert await self.client.get_balance() @pytest.mark.asyncio async def test_has_no_balances(self, client): self.client.set_network('mainnet') balance = await self.client.get_balance() assert balance.amount == 0 @pytest.mark.asyncio async def test_equal_balances_when_call_getbalance_twice(self, client): balance1 = await self.client.get_balance() balance2 = await self.client.get_balance() assert balance1.amount == balance2.amount @pytest.mark.asyncio async def test_transfer_with_memo_and_fee_rate(self, client): fee_rates = await self.client.get_fee_rates() fee_rate = fee_rates['fast'] balance = await self.client.get_balance() if balance.amount > 0: amount = 0.0000001 tx_id = await self.client.transfer(amount, self.address_two, self.memo, fee_rate) assert tx_id @pytest.mark.asyncio async def test_purge_client_should_purge_phrase_and_utxos(self): self.client = Client(self.phrase, network='testnet') self.client.purge_client() with pytest.raises(Exception) as err: self.client.get_address() assert str(err.value) == "Phrase must be provided" with pytest.raises(Exception) as err: await self.client.get_balance() assert str(err.value) == "Phrase must be provided" @pytest.mark.asyncio async def test_should_prevent_tx_when_fees_and_valueOut_exceed_balance( self, client): balance = await self.client.get_balance() if balance.amount > 0: amount = balance.amount + 1000 # LTC with pytest.raises(Exception) as err: await self.client.transfer(amount, self.address_two) assert str(err.value) == "Balance insufficient for transaction" @pytest.mark.asyncio async def test_fee_and_rates_normal_tx(self, client): fees_and_rates = await self.client.get_fees_with_rates() fees = fees_and_rates['fees'] rates = fees_and_rates['rates'] assert fees['fastest'] assert fees['fast'] assert fees['average'] assert rates['fastest'] assert rates['fast'] assert rates['average'] @pytest.mark.asyncio async def test_fee_and_rates_with_memo(self, client): fees_and_rates = await self.client.get_fees_with_rates(self.memo) fees = fees_and_rates['fees'] rates = fees_and_rates['rates'] assert fees['fastest'] assert fees['fast'] assert fees['average'] assert rates['fastest'] assert rates['fast'] assert rates['average'] @pytest.mark.asyncio async def test_estimated_fees_normal_tx(self, client): fees = await self.client.get_fees() assert fees['fastest'] assert fees['fast'] assert fees['average'] @pytest.mark.asyncio async def test_normal_tx_fees_and_vault_tx_fees(self, client): normal_tx = await self.client.get_fees() vault_tx = await self.client.get_fees_with_memo(self.memo) if vault_tx['average'] > MIN_TX_FEE: assert vault_tx['average'] > normal_tx['average'] else: assert vault_tx['average'] == MIN_TX_FEE @pytest.mark.asyncio async def test_has_balances_invalid_address(self, client): with pytest.raises(Exception) as err: await self.client.get_balance(address='invalid address') assert str(err.value) == "Invalid Address" @pytest.mark.asyncio async def test_transfer_invalid_address(self, client): balance = await self.client.get_balance() if balance.amount > 0: amount = 0.0000001 with pytest.raises(Exception) as err: await self.client.transfer(amount, 'invalid address') assert str(err.value) == "Invalid address" @pytest.mark.asyncio async def test_get_transactions(self, client): txs = await self.client.get_transactions({ 'address': self.address_three, 'limit': 4 }) assert txs if txs['total'] > 0: tx = txs['tx'][0] assert tx.asset == self.ltc_asset assert tx.tx_date assert tx.tx_hash assert tx.tx_type == 'transfer' assert len(tx.tx_to) assert len(tx.tx_from) @pytest.mark.asyncio async def test_get_transactions_limit_should_work(self, client): txs = await self.client.get_transactions({ 'address': self.address_three, 'limit': 1 }) assert len(txs['tx']) == 1 @pytest.mark.asyncio async def test_get_transaction_with_hash(self, client): tx_data = await self.client.get_transaction_data( 'b0422e9a4222f0f2b030088ee5ccd33ac0d3c59e7178bf3f4626de71b0e376d3') assert tx_data.tx_hash == 'b0422e9a4222f0f2b030088ee5ccd33ac0d3c59e7178bf3f4626de71b0e376d3' assert len(tx_data.tx_from) == 1 assert tx_data.tx_from[ 0].address == 'tltc1q2pkall6rf6v6j0cvpady05xhy37erndv05de7g' assert tx_data.tx_from[0].amount == '8.60368562' assert len(tx_data.tx_to) == 2 assert tx_data.tx_to[ 0].address == 'tltc1q04y2lnt0ausy07vq9dg5w2rnn9yjl3rz364adu' assert tx_data.tx_to[0].amount == '0.00002223' assert tx_data.tx_to[ 1].address == 'tltc1q2pkall6rf6v6j0cvpady05xhy37erndv05de7g' assert tx_data.tx_to[1].amount == '8.60365339'
def test_create_asset(self): asset = Asset('BNB', 'RUNE-67C') assert asset.chain == 'BNB' assert asset.symbol == 'RUNE-67C' assert asset.ticker == 'RUNE'
def test_asset_equal(self): asset = Asset('BNB', 'RUNE-67C', 'RUNE') asset2 = Asset('BNB', 'RUNE-67C', 'RUNE') assert asset == asset2
def test_invalid_chain(self): with pytest.raises(Exception) as err: Asset('invalid chain', 'BNB', 'BNB') assert str(err.value) == "the chain is invalid"
class TestBinanceClient: # Note: This phrase is created by https://iancoleman.io/bip39/ and will never been used in a real-world phrase = 'rural bright ball negative already grass good grant nation screen model pizza' mainnetaddress = 'bnb1zd87q9dywg3nu7z38mxdcxpw8hssrfp9e738vr' testnetaddress = 'tbnb1zd87q9dywg3nu7z38mxdcxpw8hssrfp9htcrvj' bnb_asset = Asset('BNB', 'BNB', 'BNB') phraseForTX = 'wheel leg dune emerge sudden badge rough shine convince poet doll kiwi sleep labor hello' testnetaddressForTx = 'tbnb1t95kjgmjc045l2a728z02textadd98yt339jk7' transfer_amount = 0.0001 single_tx_fee = 37500 multi_tx_fee = 30000 transfer_fee = { 'average': single_tx_fee, 'fast': single_tx_fee, 'fastest': single_tx_fee } multi_send_fee = { 'average': multi_tx_fee, 'fast': multi_tx_fee, 'fastest': multi_tx_fee } @pytest.fixture def client(self): self.client = Client(self.phrase, network='mainnet') yield self.client.purge_client() def test_empty_wallet_main(self): client = Client(self.phrase, network='mainnet') address_main = client.get_address() assert address_main == self.mainnetaddress def test_empty_wallet_test(self): client = Client(self.phrase, network='testnet') address_test = client.get_address() assert address_test == self.testnetaddress def test_invalid_phrase(self): with pytest.raises(Exception) as err: assert Client(phrase='invalid phrase') assert str(err.value) == "invalid phrase" def test_right_address(self, client): assert self.client.get_address() == self.mainnetaddress def test_update_net(self, client): self.client.set_network('testnet') assert self.client.get_network() == 'testnet' assert self.client.get_address() == self.testnetaddress def test_set_phrase_return_address(self, client): assert self.client.set_phrase(self.phrase) == self.mainnetaddress self.client.set_network('testnet') assert self.client.set_phrase(self.phrase) == self.testnetaddress @pytest.mark.asyncio async def test_has_no_balances(self, client): assert await self.client.get_balance() == [] @pytest.mark.asyncio async def test_has_balances(self, client): self.client.set_network('testnet') assert await self.client.get_balance() @pytest.mark.asyncio async def test_balance_has_correct_asset(self, client): self.client.set_network('testnet') balance = await self.client.get_balance(self.testnetaddress, self.bnb_asset) assert str(balance[0].asset) == str(self.bnb_asset) assert balance[0].amount == '12.92899000' @pytest.mark.asyncio async def test_should_broadcast_transfer(self, client): self.client.set_network('testnet') self.client.set_phrase(self.phraseForTX) assert self.client.get_address() == self.testnetaddressForTx before_balance = await self.client.get_balance() assert len(before_balance) == 1 before_balance_amount = before_balance[0].amount await self.client.transfer(asset=self.bnb_asset, amount=self.transfer_amount, recipient=self.testnetaddressForTx) after_balance = await self.client.get_balance() after_balance_amount = after_balance[0].amount assert round( (float(before_balance_amount) - float(after_balance_amount)) * 10**8) == self.single_tx_fee @pytest.mark.asyncio async def test_should_raise_exception_if_input_amount_higher_than_balance( self, client): self.client.set_network('testnet') self.client.set_phrase(self.phraseForTX) before_balance = await self.client.get_balance() before_balance_amount = before_balance[0].amount send_amount = float(before_balance_amount) + 1 with pytest.raises(Exception) as err: assert await self.client.transfer( asset=self.bnb_asset, amount=send_amount, recipient=self.testnetaddressForTx) assert str( err.value ) == "input asset amout is higher than current (asset balance - transfer fee)" @pytest.mark.asyncio async def test_get_transfer_fees(self, client): self.client.set_network('testnet') fee = await self.client.get_fees() assert fee['average'] == self.transfer_fee['average'] * 10**-8 assert fee['fast'] == self.transfer_fee['fast'] * 10**-8 assert fee['fastest'] == self.transfer_fee['fastest'] * 10**-8 def test_validate_address(self, client): assert self.client.validate_address(self.testnetaddress, 'tbnb') == True def test_validate_address_false_address(self, client): assert self.client.validate_address(self.testnetaddress + '1', 'tbnb') == False def test_validate_address_false_prefix(self, client): assert self.client.validate_address(self.testnetaddress, 'bnb') == False @pytest.mark.asyncio async def test_get_multi_send_fees(self, client): fee = await self.client.get_multi_send_fees() assert fee['average'] == round(self.multi_send_fee['average'] * 10**-8, 8) assert fee['fast'] == round(self.multi_send_fee['fast'] * 10**-8, 8) assert fee['fastest'] == round(self.multi_send_fee['fastest'] * 10**-8, 8) @pytest.mark.asyncio async def test_get_single_and_multi_fees(self, client): fee = await self.client.get_single_and_multi_fees() assert fee['multi']['average'] == round( self.multi_send_fee['average'] * 10**-8, 8) assert fee['multi']['fast'] == round( self.multi_send_fee['fast'] * 10**-8, 8) assert fee['multi']['fastest'] == round( self.multi_send_fee['fastest'] * 10**-8, 8) assert fee['single'][ 'average'] == self.transfer_fee['average'] * 10**-8 assert fee['single']['fast'] == self.transfer_fee['fast'] * 10**-8 assert fee['single'][ 'fastest'] == self.transfer_fee['fastest'] * 10**-8 @pytest.mark.asyncio async def test_search_transactions(self, client): self.client.set_network('testnet') transactions = await self.client.search_transactions( {'address': self.testnetaddress}) assert transactions if transactions['total'] > 0: assert isinstance(transactions['tx'][0], tx_types.TX) @pytest.mark.asyncio async def test_get_transactions(self, client): self.client.set_network('testnet') params = tx_types.TxHistoryParams(address=self.testnetaddressForTx, limit=1) transactions = await self.client.get_transactions(params) assert transactions assert len(transactions['tx']) == 1 or 0 if transactions['total'] > 0: assert isinstance(transactions['tx'][0], tx_types.TX) @pytest.mark.asyncio async def test_get_transaction_data(self, client): self.client.set_network('testnet') try: params = tx_types.TxHistoryParams(address=self.testnetaddressForTx, limit=1) transactions = await self.client.get_transactions(params) transaction = await self.client.get_transaction_data( transactions['tx'][0].tx_hash) assert transaction assert isinstance(transaction, tx_types.TX) except Exception as err: assert str( err ) == 'list index out of range' # there is not any transaction in the last 3 months for this address
class TestBitcoinClient: # please don't touch the tBTC in these phrase = 'atom green various power must another rent imitate gadget creek fat then' testnetaddress = 'tb1q2pkall6rf6v6j0cvpady05xhy37erndvku08wp' btc_asset = Asset('BTC', 'BTC') memo = 'SWAP:THOR.RUNE' phrase_for_tx1 = 'caution pear excite vicious exotic slow elite marble attend science strategy rude' testnetaddress_for_tx1 = 'tb1qxe0e8793v3z0v0h2l3nglzg85k2jdx04vx088z' phrase_for_tx2 = 'theme neither sun invite illness chat project enough answer spray visual zoo' testnetaddress_for_tx2 = 'tb1qymzatfxg22vg8adxlnxt3hkfmzl2rpuzpk8kcf' address_for_transactions = 'tb1q04y2lnt0ausy07vq9dg5w2rnn9yjl3rzgjhra4' @pytest.fixture def client(self): self.client = Client(self.phrase, network='testnet') yield self.client.purge_client() def test_right_address(self, client): assert self.client.get_address() == self.testnetaddress def test_invalid_phrase(self): with pytest.raises(Exception) as err: assert Client(phrase='Invalid Phrase') assert str(err.value) == "Invalid Phrase" def test_right_phrase(self, client): assert self.client.set_phrase(self.phrase) == self.testnetaddress def test_validate_address(self, client): assert self.client.validate_address(network=self.client.net, address=self.testnetaddress) @pytest.mark.asyncio async def test_has_balances(self, client): assert await self.client.get_balance() @pytest.mark.asyncio async def test_has_no_balances(self, client): self.client.set_network('mainnet') balance = await self.client.get_balance() assert balance.amount == 0 @pytest.mark.asyncio async def test_equal_balances_when_call_getbalance_twice(self, client): balance1 = await self.client.get_balance() balance2 = await self.client.get_balance() assert balance1.amount == balance2.amount @pytest.mark.asyncio async def test_transfer_with_memo_and_fee_rate(self): self.client = Client(self.phrase_for_tx1, network='testnet') fee_rates = await self.client.get_fee_rates() fee_rate = fee_rates['fast'] balance = await self.client.get_balance() if balance.amount > 0: amount = 0.0000001 tx_id = await self.client.transfer(amount, self.testnetaddress_for_tx2, self.memo, fee_rate) assert tx_id self.client.purge_client() @pytest.mark.asyncio async def test_purge_client_should_purge_phrase_and_utxos(self): self.client = Client(self.phrase, network='testnet') self.client.purge_client() with pytest.raises(Exception) as err: self.client.get_address() assert str(err.value) == "Phrase must be provided" with pytest.raises(Exception) as err: await self.client.get_balance() assert str(err.value) == "Phrase must be provided" @pytest.mark.asyncio async def test_should_prevent_tx_when_fees_and_valueOut_exceed_balance( self, client): balance = await self.client.get_balance() if balance.amount > 0: amount = balance.amount + 1000 # BTC with pytest.raises(Exception) as err: await self.client.transfer(amount, self.testnetaddress_for_tx2) assert str(err.value) == "Balance insufficient for transaction" @pytest.mark.asyncio async def test_fee_and_rates_normal_tx(self, client): fees_and_rates = await self.client.get_fees_with_rates() fees = fees_and_rates['fees'] rates = fees_and_rates['rates'] assert fees['fastest'] assert fees['fast'] assert fees['average'] assert rates['fastest'] assert rates['fast'] assert rates['average'] @pytest.mark.asyncio async def test_fee_and_rates_with_memo(self, client): fees_and_rates = await self.client.get_fees_with_rates(self.memo) fees = fees_and_rates['fees'] rates = fees_and_rates['rates'] assert fees['fastest'] assert fees['fast'] assert fees['average'] assert rates['fastest'] assert rates['fast'] assert rates['average'] @pytest.mark.asyncio async def test_estimated_fees_normal_tx(self, client): fees = await self.client.get_fees() assert fees['fastest'] assert fees['fast'] assert fees['average'] @pytest.mark.asyncio async def test_normal_tx_fees_and_vault_tx_fees(self, client): normal_tx = await self.client.get_fees() vault_tx = await self.client.get_fees_with_memo(self.memo) if vault_tx['average'] > MIN_TX_FEE: assert vault_tx['average'] > normal_tx['average'] else: assert vault_tx['average'] == MIN_TX_FEE @pytest.mark.asyncio async def test_different_fees_normal_tx(self, client): fees = await self.client.get_fees() assert fees['fastest'] > fees['fast'] assert fees['fast'] > fees['average'] @pytest.mark.asyncio async def test_has_balances_invalid_address(self, client): with pytest.raises(Exception) as err: await self.client.get_balance(address='invalid address') assert str(err.value) == "Invalid Address" @pytest.mark.asyncio async def test_transfer_invalid_address(self, client): balance = await self.client.get_balance() if balance.amount > 0: amount = 0.0000001 with pytest.raises(Exception) as err: await self.client.transfer(amount, 'invalid address') assert str(err.value) == "Invalid address" @pytest.mark.asyncio async def test_get_transactions(self, client): txs = await self.client.get_transactions({ 'address': self.address_for_transactions, 'limit': 4 }) assert txs if txs['total'] > 0: tx = txs['tx'][0] assert tx.asset == self.btc_asset assert tx.tx_date assert tx.tx_hash assert tx.tx_type == 'transfer' assert len(tx.tx_to) assert len(tx.tx_from) @pytest.mark.asyncio async def test_get_transactions_limit_should_work(self, client): txs = await self.client.get_transactions({ 'address': self.address_for_transactions, 'limit': 1 }) assert len(txs['tx']) == 1 @pytest.mark.asyncio async def test_get_transaction_with_hash(self, client): tx_data = await self.client.get_transaction_data( 'b660ee07167cfa32681e2623f3a29dc64a089cabd9a3a07dd17f9028ac956eb8') assert tx_data.tx_hash == 'b660ee07167cfa32681e2623f3a29dc64a089cabd9a3a07dd17f9028ac956eb8' assert len(tx_data.tx_from) == 1 assert tx_data.tx_from[ 0].address == '2N4nhhJpjauDekVUVgA1T51M5gVg4vzLzNC' assert tx_data.tx_from[0].amount == '0.08898697' assert len(tx_data.tx_to) == 2 assert tx_data.tx_to[ 0].address == 'tb1q3a00snh7erczk94k48fe9q5z0fldgnh4twsh29' assert tx_data.tx_to[0].amount == '0.00100000' assert tx_data.tx_to[ 1].address == 'tb1qxx4azx0lw4tc6ylurc55ak5hl7u2ws0w9kw9h3' assert tx_data.tx_to[1].amount == '0.08798533'
def test_asset_to_string(self): asset = Asset('BNB', 'RUNE-67C', 'RUNE') assert str(asset) == 'BNB.RUNE-67C'
class TestClient: # Note: This phrase is created by https://iancoleman.io/bip39/ and will never been used in a real-world phrase = 'rural bright ball negative already grass good grant nation screen model pizza' mainnetaddress = 'bnb1zd87q9dywg3nu7z38mxdcxpw8hssrfp9e738vr' testnetaddress = 'tbnb1zd87q9dywg3nu7z38mxdcxpw8hssrfp9htcrvj' bnb_asset = Asset('BNB', 'BNB', 'BNB') phraseForTX = 'wheel leg dune emerge sudden badge rough shine convince poet doll kiwi sleep labor hello' testnetaddressForTx = 'tbnb1t95kjgmjc045l2a728z02textadd98yt339jk7' transfer_amount = 0.001 single_tx_fee = 37500 transfer_fee = { 'average': single_tx_fee, 'fast': single_tx_fee, 'fastest': single_tx_fee } @pytest.fixture def client(self): return Client(self.phrase, network='mainnet') def test_empty_wallet_main(self): client = Client(self.phrase, network='mainnet') address_main = client.get_address() assert address_main == self.mainnetaddress def test_empty_wallet_test(self): client = Client(self.phrase, network='testnet') address_test = client.get_address() assert address_test == self.testnetaddress def test_invalid_phrase(self): with pytest.raises(Exception) as err: assert Client(phrase='invalid phrase') assert str(err.value) == "invalid phrase" def test_right_address(self, client): assert client.get_address() == self.mainnetaddress def test_update_net(self, client): client.set_network('testnet') assert client.get_network() == 'testnet' assert client.get_address() == self.testnetaddress def test_set_phrase_return_address(self, client): assert client.set_phrase(self.phrase) == self.mainnetaddress client.set_network('testnet') assert client.set_phrase(self.phrase) == self.testnetaddress @pytest.mark.asyncio async def test_has_no_balances(self, client): assert await client.get_balance() == [] @pytest.mark.asyncio async def test_has_balances(self, client): client.set_network('testnet') assert await client.get_balance() @pytest.mark.asyncio async def test_balance_has_correct_asset(self, client): client.set_network('testnet') balance = await client.get_balance(self.testnetaddress, self.bnb_asset) assert str(balance[0].asset) == str(self.bnb_asset) assert balance[0].amount == '12.92899000' @pytest.mark.asyncio async def test_should_broadcast_transfer(self, client): client.set_network('testnet') client.set_phrase(self.phraseForTX) assert client.get_address() == self.testnetaddressForTx before_balance = await client.get_balance() before_balance_amount = before_balance[0].amount assert len(before_balance) == 1 await client.transfer(asset=self.bnb_asset, amount=self.transfer_amount, recipient=self.testnetaddressForTx) after_balance = await client.get_balance() after_balance_amount = after_balance[0].amount assert round( (float(before_balance_amount) - float(after_balance_amount)) * 10**8) == self.single_tx_fee @pytest.mark.asyncio async def test_get_transfer_fees(self, client): client.set_network('testnet') fee = await client.get_fees() assert fee['average'] == self.transfer_fee['average'] * 10**-8 assert fee['fast'] == self.transfer_fee['fast'] * 10**-8 assert fee['fastest'] == self.transfer_fee['fastest'] * 10**-8
class TestBitcoincashClient: memo = 'SWAP:THOR.RUNE' phrase = 'atom green various power must another rent imitate gadget creek fat then' testnet_address = 'bchtest:qpd7jmj0hltgxux06v9d9u6933vq7zd0kyjlapya0g' mainnet_address = 'bitcoincash:qp4kjpk684c3d9qjk5a37vl2xn86wxl0f5j2ru0daj' bch_asset = Asset('BCH', 'BCH') @pytest.fixture def client(self): self.client = Client(phrase=self.phrase, network='testnet') yield self.client.purge_client() def test_set_phrase_should_return_correct_address(self, client): self.client.set_network('testnet') assert self.client.set_phrase(self.phrase) == self.testnet_address self.client.set_network('mainnet') assert self.client.set_phrase(self.phrase) == self.mainnet_address def test_invalid_phrase(self): with pytest.raises(Exception) as err: assert Client(phrase='Invalid Phrase') assert str(err.value) == "Invalid Phrase" def test_right_phrase(self, client): assert self.client.set_phrase(self.phrase) == self.testnet_address def test_validate_address(self, client): assert self.client.validate_address(address=self.mainnet_address) assert self.client.validate_address(address=self.testnet_address) @pytest.mark.asyncio async def test_has_balances(self, client): balance = await self.client.get_balance() assert balance.asset == self.bch_asset assert isinstance(balance.amount, float) @pytest.mark.asyncio async def test_get_transaction_with_hash(self, client): tx_data = await self.client.get_transaction_data('0d5764c89d3fbf8bea9b329ad5e0ddb6047e72313c0f7b54dcb14f4d242da64b') assert tx_data.tx_hash == '0d5764c89d3fbf8bea9b329ad5e0ddb6047e72313c0f7b54dcb14f4d242da64b' assert len(tx_data.tx_from) == 1 assert tx_data.tx_from[0].address == 'bchtest:qzyrvsm6z4ucrhaq4zza3wylre7mavvldgr67jrxt4' assert str(tx_data.tx_from[0].amount) == '0.04008203' assert len(tx_data.tx_to) == 2 assert tx_data.tx_to[0].address == 'bchtest:qq235k7k9y5cwf3s2vfpxwgu8c5497sxnsdnxv6upc' assert str(tx_data.tx_to[0].amount) == '0.04005704' @pytest.mark.asyncio async def test_transfer_with_memo_and_fee_rate(self, client): fee_rates = await self.client.get_fee_rates() fee_rate = fee_rates['fast'] balance = await self.client.get_balance() if balance.amount > 0: amount = 0.00000001 tx_id = await self.client.transfer(amount, 'bchtest:qzt6sz836wdwscld0pgq2prcpck2pssmwge9q87pe9', self.memo, fee_rate) assert tx_id @pytest.mark.asyncio async def test_fee_and_rates_normal_tx(self, client): fees_and_rates = await self.client.get_fees_with_rates() fees = fees_and_rates['fees'] rates = fees_and_rates['rates'] assert fees['fastest'] assert fees['fast'] assert fees['average'] assert rates['fastest'] assert rates['fast'] assert rates['average'] @pytest.mark.asyncio async def test_fee_and_rates_with_memo(self, client): fees_and_rates = await self.client.get_fees_with_rates(self.memo) fees = fees_and_rates['fees'] rates = fees_and_rates['rates'] assert fees['fastest'] assert fees['fast'] assert fees['average'] assert rates['fastest'] assert rates['fast'] assert rates['average'] @pytest.mark.asyncio async def test_estimated_fees_normal_tx(self, client): fees = await self.client.get_fees() assert fees['fastest'] assert fees['fast'] assert fees['average'] @pytest.mark.asyncio async def test_different_fees_normal_tx(self, client): fees = await self.client.get_fees() assert fees['fastest'] > fees['fast'] assert fees['fast'] > fees['average']