def test_get_deploy_transaction_cosmwasm(): """Test the get deploy transaction method.""" cc2 = FetchAICrypto() cosmos_api = FetchAIApi(**FETCHAI_TESTNET_CONFIG) contract_interface = {"wasm_byte_code": b""} deployer_address = cc2.address deploy_transaction = cosmos_api.get_deploy_transaction( contract_interface, deployer_address) assert type(deploy_transaction) == dict and len(deploy_transaction) == 6 assert "account_number" in deploy_transaction assert "chain_id" in deploy_transaction assert "fee" in deploy_transaction and deploy_transaction["fee"] == { "amount": [{ "amount": "0", "denom": "atestfet" }], "gas": "80000", } assert "memo" in deploy_transaction assert "msgs" in deploy_transaction and len( deploy_transaction["msgs"]) == 1 msg = deploy_transaction["msgs"][0] assert "type" in msg and msg["type"] == "wasm/store-code" assert ("value" in msg and msg["value"]["sender"] == deployer_address and msg["value"]["wasm_byte_code"] == contract_interface["wasm_byte_code"]) assert "sequence" in deploy_transaction
def test_format_default(): """Test if default CosmosSDK transaction is correctly formated.""" account = FetchAICrypto() cc2 = FetchAICrypto() cosmos_api = FetchAIApi(**FETCHAI_TESTNET_CONFIG) amount = 10000 transfer_transaction = cosmos_api.get_transfer_transaction( sender_address=account.address, destination_address=cc2.address, amount=amount, tx_fee=1000, tx_nonce="something", ) signed_transaction = cc2.sign_transaction(transfer_transaction) assert "tx" in signed_transaction assert "signatures" in signed_transaction["tx"] assert len(signed_transaction["tx"]["signatures"]) == 1 assert "pub_key" in signed_transaction["tx"]["signatures"][0] assert "value" in signed_transaction["tx"]["signatures"][0]["pub_key"] base64_pbk = signed_transaction["tx"]["signatures"][0]["pub_key"]["value"] assert "signature" in signed_transaction["tx"]["signatures"][0] signature = signed_transaction["tx"]["signatures"][0]["signature"] default_formated_transaction = cc2.format_default_transaction( transfer_transaction, signature, base64_pbk) # Compare default formatted transaction with signed transaction assert signed_transaction == default_formated_transaction
def test_get_handle_transaction_cosmwasm(): """Test the get deploy transaction method.""" cc2 = FetchAICrypto() cosmos_api = FetchAIApi(**FETCHAI_TESTNET_CONFIG) handle_msg = "handle_msg" sender_address = cc2.address contract_address = "contract_address" tx_fee = 1 amount = 10 handle_transaction = cosmos_api.get_handle_transaction( sender_address, contract_address, handle_msg, amount, tx_fee) assert type(handle_transaction) == dict and len(handle_transaction) == 6 assert "account_number" in handle_transaction assert "chain_id" in handle_transaction assert "fee" in handle_transaction and handle_transaction["fee"] == { "amount": [{ "denom": "atestfet", "amount": "{}".format(tx_fee) }], "gas": "80000", } assert "memo" in handle_transaction assert "msgs" in handle_transaction and len( handle_transaction["msgs"]) == 1 msg = handle_transaction["msgs"][0] assert "type" in msg and msg["type"] == "wasm/execute" assert ("value" in msg and msg["value"]["sender"] == sender_address and msg["value"]["contract"] == contract_address and msg["value"]["msg"] == handle_msg and msg["value"]["sent_funds"] == [{ "denom": "atestfet", "amount": str(amount) }]) assert "sequence" in handle_transaction
def test_get_balance(): """Test the balance is zero for a new account.""" fetchai_api = FetchAIApi(**FETCHAI_TESTNET_CONFIG) fc = FetchAICrypto() balance = fetchai_api.get_balance(fc.address) assert balance == 0, "New account has a positive balance." balance = get_wealth(fc.address) assert balance > 0, "Existing account has no balance."
def test_get_balance(): """Test the balance is zero for a new account.""" fetch_api = FetchAIApi(**FETCHAI_TESTNET_CONFIG) fc = FetchAICrypto() balance = fetch_api.get_balance(fc.address) assert balance == 0, "New account has a positive balance." fc = FetchAICrypto(private_key_path=FETCHAI_PRIVATE_KEY_PATH) balance = fetch_api.get_balance(fc.address)
def test_send_signed_transaction_wasm_transaction(): """Test the send_signed_transaction method for a wasm transaction.""" cosmos_api = FetchAIApi(**FETCHAI_TESTNET_CONFIG) tx_signed = {"value": {"msg": [{"type": "wasm/store-code"}]}} with mock.patch.object(cosmos_api, "try_execute_wasm_transaction", return_value="digest"): result = cosmos_api.send_signed_transaction(tx_signed=tx_signed) assert result == "digest"
def test_get_state(): """Test that get_state() with 'blocks' function returns something containing the block height.""" fetchai_api = FetchAIApi(**FETCHAI_TESTNET_CONFIG) callable_name = "blocks" args = ("latest",) block = fetchai_api.get_state(callable_name, *args) assert block is not None, "No response to 'blocks/latest' query." assert ( block["block"]["header"]["height"] is not None ), "Block height not found in response."
def test_try_execute_wasm_transaction(): """Test the execute wasm query method.""" cosmos_api = FetchAIApi(**FETCHAI_TESTNET_CONFIG) process_mock = mock.Mock() output = "output".encode("ascii") attrs = {"communicate.return_value": (output, "error")} process_mock.configure_mock(**attrs) with mock.patch("subprocess.Popen", return_value=process_mock): result = cosmos_api.try_execute_wasm_transaction( tx_signed="signed_transaction") assert result == output.decode("ascii")
def test_execute_shell_command(mock_api_call): """Test the helper _execute_shell_command method""" mock_res = b'{"SOME": "RESULT"}', "ERROR" mock_api_call.return_value = mock_res cosmos_api = FetchAIApi(**FETCHAI_TESTNET_CONFIG) res = cosmos_api._execute_shell_command(["test", "command"]) assert res == {"SOME": "RESULT"}
def get_wealth(address: str): """Get wealth for test.""" fetchai_api = FetchAIApi(**FETCHAI_TESTNET_CONFIG) FetchAIFaucetApi().get_wealth(address) balance = 0 timeout = 0 while timeout < 40 and balance == 0: time.sleep(1) timeout += 1 _balance = fetchai_api.get_balance(address) balance = _balance if _balance is not None else 0 return balance
def test_try_execute_wasm_query(): """Test the execute wasm query method.""" cosmos_api = FetchAIApi(**FETCHAI_TESTNET_CONFIG) process_mock = mock.Mock() output_raw = {"output": 1} output = json.dumps(output_raw).encode("ascii") attrs = {"communicate.return_value": (output, "error")} process_mock.configure_mock(**attrs) with mock.patch("subprocess.Popen", return_value=process_mock): result = cosmos_api.execute_contract_query( contract_address="contract_address", query_msg={} ) assert result == output_raw
def test_transfer(): """Test transfer of wealth.""" fetchai_api = FetchAIApi(**FETCHAI_TESTNET_CONFIG) fc1 = FetchAICrypto(private_key_path=FETCHAI_PRIVATE_KEY_PATH) fc2 = FetchAICrypto() amount = 40000 fee = 30000 tx_nonce = fetchai_api.generate_tx_nonce(fc2.address, fc1.address) tx_digest = fetchai_api.transfer(fc1, fc2.address, amount, fee, tx_nonce, chain_id=3) assert tx_digest is not None, "Failed to submit transfer!"
def test_get_contract_address(mock_api_call): """Test the get_contract_address method used for interaction with CosmWasm contracts.""" mock_res = [{ "code_id": 999, "creator": "cosmos_creator_address", "label": "SOME_LABEL", "address": "cosmos_contract_address", }] mock_api_call.return_value = mock_res cosmos_api = FetchAIApi(**FETCHAI_TESTNET_CONFIG) res = cosmos_api.get_contract_address(code_id=999) assert res == mock_res[-1]["address"]
def test_generate_nonce(): """Test generate nonce.""" nonce = FetchAIApi.generate_tx_nonce( seller="some_seller_addr", client="some_buyer_addr" ) assert len(nonce) > 0 and int( nonce, 16 ), "The len(nonce) must not be 0 and must be hex"
def test_get_last_code_id(mock_api_call): """Test the get_last_code_id method used for interaction with CosmWasm contracts.""" mock_res = [{ "id": 1, "creator": "cosmos14xjnl2mwwfz6pztpwzj6s89npxr0e3lhxl52nv", "data_hash": "59D6DD8D6034C9E97015DD9E12DAFCE404FA5C413FA81CFBE0EF3E427F0A9BA3", "source": "", "builder": "", }] mock_api_call.return_value = mock_res cosmos_api = FetchAIApi(**FETCHAI_TESTNET_CONFIG) res = cosmos_api.get_last_code_id() assert res == mock_res[-1]["id"]
def test_sign_and_recover_message(): """Test the signing and the recovery of a message.""" account = FetchAICrypto(FETCHAI_PRIVATE_KEY_PATH) sign_bytes = account.sign_message(message=b"hello") assert len(sign_bytes) > 0, "The len(signature) must not be 0" recovered_addresses = FetchAIApi.recover_message(message=b"hello", signature=sign_bytes) assert (account.address in recovered_addresses), "Failed to recover the correct address."
def test_handle_tx_signing_fetchai(self): """Test tx signing for fetchai.""" fetchai_api = FetchAIApi(**FETCHAI_TESTNET_CONFIG) account = FetchAICrypto() fc2 = FetchAICrypto() amount = 10000 transfer_transaction = fetchai_api.get_transfer_transaction( sender_address=account.address, destination_address=fc2.address, amount=amount, tx_fee=1000, tx_nonce="something", ) signing_dialogues = SigningDialogues( str(PublicId("author", "a_skill", "0.1.0"))) signing_msg = SigningMessage( performative=SigningMessage.Performative.SIGN_TRANSACTION, dialogue_reference=signing_dialogues. new_self_initiated_dialogue_reference(), terms=Terms( ledger_id=FETCHAI, sender_address="pk1", counterparty_address="pk2", amount_by_currency_id={"FET": -1}, is_sender_payable_tx_fee=True, quantities_by_good_id={"good_id": 10}, nonce="transaction nonce", ), raw_transaction=RawTransaction(FETCHAI, transfer_transaction), ) signing_dialogue = signing_dialogues.create_with_message( "decision_maker", signing_msg) assert signing_dialogue is not None self.decision_maker.message_in_queue.put_nowait(signing_msg) signing_msg_response = self.decision_maker.message_out_queue.get( timeout=2) recovered_dialogue = signing_dialogues.update(signing_msg_response) assert recovered_dialogue is not None and recovered_dialogue == signing_dialogue assert (signing_msg_response.performative == SigningMessage.Performative.SIGNED_TRANSACTION) assert type(signing_msg_response.signed_transaction.body) == dict
def test_construct_sign_and_submit_transfer_transaction(): """Test the construction, signing and submitting of a transfer transaction.""" account = FetchAICrypto() balance = get_wealth(account.address) assert balance > 0, "Failed to fund account." fc2 = FetchAICrypto() fetchai_api = FetchAIApi(**FETCHAI_TESTNET_CONFIG) amount = 10000 assert amount < balance, "Not enough funds." transfer_transaction = fetchai_api.get_transfer_transaction( sender_address=account.address, destination_address=fc2.address, amount=amount, tx_fee=1000, tx_nonce="", ) assert isinstance( transfer_transaction, Transaction), "Incorrect transfer_transaction constructed." signed_transaction = account.sign_transaction(transfer_transaction) assert (isinstance(signed_transaction, Transaction) and len(signed_transaction.signatures) == 1), "Incorrect signed_transaction constructed." transaction_digest = fetchai_api.send_signed_transaction( signed_transaction) assert transaction_digest is not None, "Failed to submit transfer transaction!" not_settled = True elapsed_time = 0 while not_settled and elapsed_time < 20: elapsed_time += 1 time.sleep(2) transaction_receipt = fetchai_api.get_transaction_receipt( transaction_digest) if transaction_receipt is None: continue is_settled = fetchai_api.is_transaction_settled(transaction_receipt) if is_settled is None: continue not_settled = not is_settled assert transaction_receipt is not None, "Failed to retrieve transaction receipt." assert is_settled, "Failed to verify tx!" tx = fetchai_api.get_transaction(transaction_digest) assert tx != transaction_receipt, "Should be same!" is_valid = fetchai_api.is_transaction_valid(tx, fc2.address, account.address, "", amount) assert is_valid, "Failed to settle tx correctly!"
def test_get_init_transaction_cosmwasm(): """Test the get deploy transaction method.""" cc2 = FetchAICrypto() cosmos_api = FetchAIApi(**FETCHAI_TESTNET_CONFIG) init_msg = "init_msg" code_id = 1 deployer_address = cc2.address tx_fee = 1 amount = 10 contract_interface = {"wasm_byte_code": b""} deploy_transaction = cosmos_api.get_deploy_transaction( contract_interface, deployer_address, code_id=code_id, init_msg=init_msg, amount=amount, tx_fee=tx_fee, label="", ) assert type(deploy_transaction) == dict and len(deploy_transaction) == 6 assert "account_number" in deploy_transaction assert "chain_id" in deploy_transaction assert "fee" in deploy_transaction and deploy_transaction["fee"] == { "amount": [{"denom": "atestfet", "amount": "{}".format(tx_fee)}], "gas": "0", } assert "memo" in deploy_transaction assert "msgs" in deploy_transaction and len(deploy_transaction["msgs"]) == 1 msg = deploy_transaction["msgs"][0] assert "type" in msg and msg["type"] == "wasm/instantiate" assert ( "value" in msg and msg["value"]["sender"] == deployer_address and msg["value"]["code_id"] == str(code_id) and msg["value"]["label"] == "" and msg["value"]["init_msg"] == init_msg and msg["value"]["init_funds"] == [{"denom": "atestfet", "amount": str(amount)}] ) assert "sequence" in deploy_transaction
def _instantiate_api(identifier: str, config: Dict[str, Union[str, int]]) -> LedgerApi: """ Instantiate a ledger api. :param identifier: the ledger identifier :param config: the config of the api :return: the ledger api """ retry = 0 is_connected = False while retry < MAX_CONNECTION_RETRY: if identifier not in SUPPORTED_LEDGER_APIS: raise ValueError( "Unsupported identifier {} in ledger apis.".format(identifier) ) try: if identifier == FetchAIApi.identifier: api = FetchAIApi(**config) # type: LedgerApi elif identifier == EthereumApi.identifier: api = EthereumApi( cast(str, config["address"]), cast(str, config["gas_price"]) ) elif identifier == CosmosApi.identifier: api = CosmosApi(**config) is_connected = True break except Exception: # pragma: no cover retry += 1 logger.debug( "Connection attempt {} to {} ledger with provided config {} failed.".format( retry, identifier, config ) ) time.sleep(0.5) if not is_connected: # pragma: no cover logger.error( "Cannot connect to {} ledger with provided config {} after {} attemps. Giving up!".format( identifier, config, MAX_CONNECTION_RETRY ) ) sys.exit(1) return api
def __init__( self, ledger_api_configs: Dict[str, Dict[str, Union[str, int]]], default_ledger_id: str, ): """ Instantiate a wallet object. :param ledger_api_configs: the ledger api configs. :param default_ledger_id: the default ledger id. """ apis = {} # type: Dict[str, LedgerApi] configs = {} # type: Dict[str, Dict[str, Union[str, int]]] self._last_tx_statuses = {} # type: Dict[str, str] for identifier, config in ledger_api_configs.items(): self._last_tx_statuses[identifier] = UNKNOWN if identifier == FETCHAI: try: api = FetchAIApi(**config) # type: LedgerApi except Exception: logger.error( "Cannot connect to fetchai ledger with provided config." ) sys.exit(1) elif identifier == ETHEREUM: try: api = EthereumApi(cast(str, config["address"]), cast(str, config["gas_price"])) except Exception: logger.error( "Cannot connect to ethereum ledger with provided config." ) sys.exit(1) else: raise ValueError("Unsupported identifier in ledger apis.") apis[identifier] = api configs[identifier] = config self._apis = apis self._configs = configs self._default_ledger_id = default_ledger_id
def test_api_none(): """Test the "api" of the cryptoApi is none.""" fetchai_api = FetchAIApi(**FETCHAI_TESTNET_CONFIG) assert fetchai_api.api is not None, "The api property is None."
def test_api_creation(): """Test api instantiation.""" assert FetchAIApi(**FETCHAI_TESTNET_CONFIG), "Failed to initialise the api"
def test_get_address_from_public_key(): """Test the address from public key.""" fet_crypto = FetchAICrypto() address = FetchAIApi.get_address_from_public_key(fet_crypto.public_key) assert address == fet_crypto.address, "The address must be the same."
def test_get_hash(): """Test the get hash functionality.""" expected_hash = "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824" hash_ = FetchAIApi.get_hash(message=b"hello") assert expected_hash == hash_
def test_get_contract_instance(): """Test the get contract instance method.""" cosmos_api = FetchAIApi(**FETCHAI_TESTNET_CONFIG) assert cosmos_api.get_contract_instance("interface") is None
def test_get_contract_instance(): """Test the get contract instance method.""" fetchai_api = FetchAIApi(**FETCHAI_TESTNET_CONFIG) with pytest.raises(NotImplementedError): fetchai_api.get_contract_instance("interface")
def test_get_deploy_transaction(): """Test the get deploy transaction method.""" fetchai_api = FetchAIApi(**FETCHAI_TESTNET_CONFIG) with pytest.raises(NotImplementedError): fetchai_api.get_deploy_transaction("interface", "deployer")
def test_validate_address(): """Test the is_valid_address functionality.""" account = FetchAICrypto() assert FetchAIApi.is_valid_address(account.address) assert not FetchAIApi.is_valid_address(account.address + "wrong")