def test_utils_amount_to_aettos(): args = [ ("1.2AE", 1200000000000000000), ("1.2ae", 1200000000000000000), (" 1.2ae ", 1200000000000000000), ("1.25ae", 1250000000000000000), (1.3, 1300000000000000000), (10, 10), (-1, TypeError()), ("10", 10), (" 1000 ", 1000), ("1001 ", 1001), (" 1002", 1002), ("1,25ae", TypeError()), ("1ae", 1000000000000000000), ("0.000000005", 5000000000), ("0", 0), (0, 0), ] # TODO: test more float for i in range(10000): val = random.randint(0, 1000000000000000000000000) args.append((utils.format_amount(val), val)) for i in range(10000): val = random.randint(0, 1000000) args.append((utils.format_amount(val), val)) # the default context has 28 for max prcision # therefore anything greater than 1e28 will fail for i in range(10000): val = random.randint(1000000000000000000, 10000000000000000000000000000) args.append((utils.format_amount(val), val)) for a in args: expected = a[1] if issubclass(type(expected), Exception): with pytest.raises(type(expected)): utils.amount_to_aettos(a[0]) else: got = utils.amount_to_aettos(a[0]) assert got == expected
def test_node_contract_signature_delegation(compiler_fixture, chain_fixture): compiler = compiler_fixture.COMPILER account = chain_fixture.ALICE bob = chain_fixture.BOB contract_native = ContractNative(client=chain_fixture.NODE_CLI, source=contractAens, compiler=compiler, account=account) contract_native.deploy() assert (contract_native.address is not None) # the contract_id contract_id = contract_native.address # node client ae_cli = contract_native.client # example name name = random_domain(length=15) c_id, salt = hashing.commitment_id(name, 9876) name_ttl = 500000 client_ttl = 36000 name_fee = utils.amount_to_aettos("20AE") print(f"name is {name}, commitment_id: {c_id}") # aens calls signature = ae_cli.delegate_name_preclaim_signature(account, contract_id) call, r = contract_native.signedPreclaim(account.get_address(), c_id, signature) assert (call.return_type == 'ok') ae_cli.wait_for_confirmation(call.tx_hash) signature = ae_cli.delegate_name_claim_signature(account, contract_id, name) call, _ = contract_native.signedClaim(account.get_address(), name, salt, name_fee, signature) assert (call.return_type == 'ok') signature = ae_cli.delegate_name_transfer_signature( account, contract_id, name) call, _ = contract_native.signedTransfer(account.get_address(), bob.get_address(), name, signature) assert (call.return_type == 'ok') signature = ae_cli.delegate_name_revoke_signature(bob, contract_id, name) call, _ = contract_native.signedRevoke(bob.get_address(), name, signature) assert (call.return_type == 'ok')
def update(self, account, *targets, name_ttl=defaults.NAME_MAX_TTL, client_ttl=defaults.NAME_MAX_CLIENT_TTL, fee=defaults.FEE, tx_ttl=defaults.TX_TTL): """ Update a claimed name, an update may update the name_ttl and/or set name pointers for it. A name pointer can be specified as an address for accounts, oracles or contracts or using a custom tuple containing the (key, value) for the pointer. :param account: the account singing the update transaction :param targets: the list of pointers targets :param name_ttl: the number of blocks before the name enters in the revoked state :param client_ttl: the ttl for client to cache the name in seconds :param fee: the fee for the transaction, [optional, calculated automatically] :param tx_ttl: relative number of blocks for the validity of the transaction :return: the TxObject of the update transaction :raises NameUpdateError: if the name is not claimed """ if not self.check_claimed(): raise NameUpdateError( f"the name {self.domain} must be claimed for an update transaction to be successful" ) # parse amounts fee = utils.amount_to_aettos(fee) # check that there are at least one target pointers = self._get_pointers(targets) # get the transaction builder txb = self.client.tx_builder # get the account nonce and ttl nonce, ttl = self.client._get_nonce_ttl(account.get_address(), tx_ttl) # create transaction tx = txb.tx_name_update(account.get_address(), self.name_id, pointers, name_ttl, client_ttl, fee, ttl, nonce) # sign the transaction tx_signed = self.client.sign_transaction(account, tx) # post the transaction to the chain self.client.broadcast_transaction(tx_signed) return tx_signed
def test_node_spend_burst(chain_fixture): sender_account = chain_fixture.ALICE # make a new non blocking client ae_cli = chain_fixture.NODE_CLI ae_cli.config.blocking_mode = False # recipient account recipient_account = Account.generate().get_address() # send 50 consecutive spend ths = [] print(">>" * 20, "spend burst start") for i in range(50): tx = ae_cli.spend(sender_account, recipient_account, "1AE") ths.append(tx.hash) print("<<" * 20, "spend burst end") for th in ths: ae_cli.wait_for_transaction(th) assert (ae_cli.get_balance(recipient_account) == utils.amount_to_aettos( "50ae"))
def transfer_funds(self, account: Account, recipient_id: str, percentage: float, payload: str = "", tx_ttl: int = defaults.TX_TTL, fee: int = defaults.FEE, include_fee=True): """ Create and execute a spend transaction """ if utils.is_valid_aens_name(recipient_id): recipient_id = hashing.name_id(recipient_id) elif not utils.is_valid_hash(recipient_id, prefix="ak"): raise TypeError("Invalid recipient_id. Please provide a valid AENS name or account pub_key.") if percentage < 0 or percentage > 1: raise ValueError(f"Percentage should be a number between 0 and 1, got {percentage}") # parse amounts fee = utils.amount_to_aettos(fee) # retrieve the balance account_on_chain = self.get_account_by_pubkey(pubkey=account.get_address()) request_transfer_amount = int(account_on_chain.balance * percentage) # retrieve the nonce account.nonce = account_on_chain.nonce + 1 # retrieve ttl tx_ttl = self.compute_absolute_ttl(tx_ttl) # build the transaction tx = self.tx_builder.tx_spend(account.get_address(), recipient_id, request_transfer_amount, payload, fee, tx_ttl.absolute_ttl, account.nonce) # if the request_transfer_amount should include the fee keep calculating the fee if include_fee: amount = request_transfer_amount while (amount + tx.data.fee) > request_transfer_amount: amount = request_transfer_amount - tx.data.fee tx = self.tx_builder.tx_spend(account.get_address(), recipient_id, amount, payload, fee, tx_ttl.absolute_ttl, account.nonce) # execute the transaction tx = self.sign_transaction(account, tx) # post the transaction self.broadcast_transaction(tx) return tx
def transfer_ownership(self, account, recipient_id, fee=defaults.FEE, tx_ttl=defaults.TX_TTL): """ Transfer ownership of a name to another account :param account: the account singing the transfer transaction and owner of the name :param recipient_id: the recipient of the name transfer that will become the new owner :param fee: the fee for the transaction, [optional, calculated automatically] :param tx_ttl: relative number of blocks for the validity of the transaction :return: the TxObject of the transfer transaction :raises NameUpdateError: if the name is not claimed """ if not self.check_claimed(): raise NameUpdateError( f"the name {self.domain} must be claimed for an update transaction to be successful" ) # get the transaction builder txb = self.client.tx_builder # parse amounts fee = utils.amount_to_aettos(fee) # get the account nonce and ttl nonce, ttl = self.client._get_nonce_ttl(account.get_address(), tx_ttl) # create transaction tx = txb.tx_name_transfer(account.get_address(), self.name_id, recipient_id, fee, ttl, nonce) # sign the transaction tx_signed = self.client.sign_transaction(account, tx) # post the transaction to the chain self.client.broadcast_transaction(tx_signed) # update the status self.status = NameStatus.TRANSFERRED return tx_signed
def preclaim(self, account, fee=defaults.FEE, tx_ttl=defaults.TX_TTL) -> transactions.TxObject: """ Execute a name pre-claim transaction :param account: the account performing the pre-claim :param fee: the fee for the transaction, [optional, calculated automatically] :param tx_ttl: relative number of blocks for the validity of the transaction :return: the TxObject of the pre-claim transaction including the parameters to calculate the commitment_id in the meta-data """ # parse the fee fee = utils.amount_to_aettos(fee) # check which block we used to create the pre-claim self.preclaimed_block_height = self.client.get_current_key_block_height( ) # calculate the commitment id commitment_id, self.preclaim_salt = hashing.commitment_id(self.domain) # get the transaction builder txb = self.client.tx_builder # get the account nonce and ttl nonce, ttl = self.client._get_nonce_ttl(account.get_address(), tx_ttl) # create spend_tx tx = txb.tx_name_preclaim(account.get_address(), commitment_id, fee, ttl, nonce) # sign the transaction tx_signed = self.client.sign_transaction( account, tx, metadata={"salt": self.preclaim_salt}) # post the transaction to the chain self.client.broadcast_transaction(tx_signed) # update local status self.status = AEName.Status.PRECLAIMED self.preclaim_tx_hash = tx_signed.hash return tx_signed
def test_tutorial_offline_tx(chain_fixture): # Accounts addresses account = Account.generate() # --- hide --- override the account for tests account = chain_fixture.ALICE # /--- hide --- # instantiate the transactions builder build = TxBuilder() # we will be creating 5 transactions for later broadcast TODO: warn about the nonce limit txs = [] # each transaction is going to be a spend amount = utils.amount_to_aettos("0.05AE") payload = b'' for i in range(5): # increase the account nonce account.nonce = account.nonce + 1 # build the transaction tx = build.tx_spend( account.get_address(), # sender Account.generate().get_address(), # random generated recipient amount, payload, defaults.FEE, defaults.TX_TTL, account.nonce) # save the transaction txs.append(tx) # Sign the transactions # define the network_id network_id = identifiers.NETWORK_ID_TESTNET # --- hide --- override the network_id for tests network_id = chain_fixture.NODE_CLI.config.network_id # /--- hide --- # instantiate a transaction signer signer = TxSigner(account, network_id) # collect the signed tx for broadcast signed_txs = [] # sign all transactions for tx in txs: signature = signer.sign_transaction(tx) signed_tx = build.tx_signed([signature], tx) signed_txs.append(signed_tx) # Broadcast the transactions NODE_URL = os.environ.get('TEST_URL', 'https://testnet.aeternity.io') node_cli = NodeClient(Config( external_url=NODE_URL, blocking_mode=False, )) # broadcast all transactions for stx in signed_txs: node_cli.broadcast_transaction(stx) # verify that all transactions have been posted for stx in signed_txs: height = node_cli.wait_for_transaction(stx) assert (height > 0)
'class': 'logging.StreamHandler', 'stream': 'ext://sys.stdout', 'formatter': 'default' } }, 'root': { 'level': 'INFO', 'handlers': ['wsgi'] } }) app = Flask(__name__, static_url_path='') # environment var FAUCET_ACCOUNT_PRIV_KEY = os.environ.get("FAUCET_ACCOUNT_PRIV_KEY") TOPUP_AMOUNT = amount_to_aettos(os.environ.get("TOPUP_AMOUNT", "5AE")) SPEND_TX_PAYLOAD = os.environ.get("SPEND_TX_PAYLOAD", "Faucet Tx") NODE_URL = os.environ.get("NODE_URL", "https://testnet.aeternity.io") EXPLORER_URL = os.environ.get("EXPLORER_URL", "https://testnet.aeternal.io") SUPPORT_EMAIL = os.environ.get("SUPPORT_EMAIL", "*****@*****.**") # telegram notifications TELEGRAM_API_TOKEN = os.environ.get('TELEGRAM_API_TOKEN', False) TELEGRAM_CHAT_ID = os.environ.get('TELEGRAM_CHAT_ID') # graylisting CACHE_MAX_SIZE = int(os.environ.get('CACHE_MAX_SIZE', 6000)) CACHE_MAX_AGE = int(os.environ.get('CACHE_MAX_AGE', 3600 * 4)) # default 4h # Server SERVER_LISTEN_ADDRESS = os.environ.get("SERVER_LISTEN_ADDRESS", "0.0.0.0") SERVER_LISTEN_PORT = int(os.environ.get("SERVER_LISTEN_PORT", 5000))