예제 #1
0
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
예제 #2
0
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')
예제 #3
0
    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
예제 #4
0
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"))
예제 #5
0
 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
예제 #6
0
    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
예제 #7
0
    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
예제 #8
0
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)
예제 #9
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))