コード例 #1
0
ファイル: test_cli.py プロジェクト: noandrea/aepp-sdk-python
def test_cli_name_claim(chain_fixture, tempdir):
    account_alice_path = _account_path(tempdir, chain_fixture.ALICE)
    # get a domain that is not under auction scheme
    domain = random_domain(
        length=13,
        tld='chain' if chain_fixture.NODE_CLI.get_consensus_protocol_version()
        >= identifiers.PROTOCOL_LIMA else 'test')
    # let alice preclaim a name
    j = call_aecli('name', 'pre-claim', '--password', 'aeternity_bc',
                   account_alice_path, domain, '--wait')
    # retrieve the salt and the transaction hash
    salt = j.get("metadata", {}).get("salt")
    preclaim_hash = j.get("hash")
    # test that they are what we expect to be
    assert (isinstance(salt, int))
    assert (salt > 0)
    assert (utils.is_valid_hash(preclaim_hash, identifiers.TRANSACTION_HASH))
    # wait for confirmation
    chain_fixture.NODE_CLI.wait_for_confirmation(preclaim_hash)
    # now run the claim
    j = call_aecli('name', 'claim', account_alice_path, domain, '--password',
                   'aeternity_bc', '--name-salt', f"{salt}",
                   '--preclaim-tx-hash', preclaim_hash, '--wait')
    assert (utils.is_valid_hash(j.get("hash"), identifiers.TRANSACTION_HASH))
    # now run the name update
    j = call_aecli('name', 'update', '--password',
                   'aeternity_bc', account_alice_path, domain,
                   chain_fixture.ALICE.get_address())
    assert (utils.is_valid_hash(j.get("hash"), identifiers.TRANSACTION_HASH))
    # now inspect the name
    j = call_aecli('inspect', domain)
    pointers = j.get('pointers', [])
    assert (len(pointers) == 1)
    assert (pointers[0]['id'] == chain_fixture.ALICE.get_address())
コード例 #2
0
ファイル: test_cli.py プロジェクト: noandrea/aepp-sdk-python
def test_cli_contract_deploy_call(chain_fixture, compiler_fixture, tempdir):
    node_cli = chain_fixture.NODE_CLI
    account_alice_path = _account_path(tempdir, chain_fixture.ALICE)
    # the contract
    c_src = "contract Identity =\n  entrypoint main(x : int) = x"
    c_deploy_function = "init"
    c_call_function = "main"
    c_call_function_param = 42
    # compile the contract
    compiler = compiler_fixture.COMPILER
    # compile and encode calldatas
    c_bin = compiler.compile(c_src).bytecode
    c_init_calldata = compiler.encode_calldata(c_src,
                                               c_deploy_function).calldata
    c_call_calldata = compiler.encode_calldata(c_src, c_call_function,
                                               c_call_function_param).calldata
    # write the contract to a file and execute the command
    contract_bin_path = os.path.join(tempdir, 'contract.bin')
    with open(contract_bin_path, "w") as fp:
        fp.write(c_bin)
    # deploy the contract
    j = call_aecli("contract", "deploy", "--wait", "--password",
                   "aeternity_bc", account_alice_path, contract_bin_path,
                   "--calldata", c_init_calldata)
    c_id = j.get("metadata", {}).get("contract_id")
    assert utils.is_valid_hash(c_id, prefix=identifiers.CONTRACT_ID)
    # now call
    j = call_aecli("contract", "call", "--wait", "--password", "aeternity_bc",
                   account_alice_path, c_id, c_call_function, "--calldata",
                   c_call_calldata)
    th = j.get("hash")
    assert utils.is_valid_hash(th, prefix=identifiers.TRANSACTION_HASH)
コード例 #3
0
ファイル: test_cli.py プロジェクト: noandrea/aepp-sdk-python
def test_cli_generate_account_and_account_info(tempdir):
    account_path = os.path.join(tempdir, 'key')
    j = call_aecli('account', 'create', account_path, '--password', 'secret')
    gen_address = j.get("Address")
    assert utils.is_valid_hash(gen_address, prefix='ak')
    j1 = call_aecli('account', 'address', account_path, '--password', 'secret')
    assert utils.is_valid_hash(j1.get('Address'), prefix='ak')
コード例 #4
0
ファイル: test_cli.py プロジェクト: noandrea/aepp-sdk-python
def test_cli_name_auction(chain_fixture, tempdir):
    if chain_fixture.NODE_CLI.get_consensus_protocol_version(
    ) < identifiers.PROTOCOL_LIMA:
        pytest.skip("name auction is only supported after Lima HF")
        return
    node_cli = chain_fixture.NODE_CLI
    account_alice_path = _account_path(tempdir, chain_fixture.ALICE)
    account_bob_path = _account_path(tempdir, chain_fixture.BOB)
    # get a domain that is under auction scheme
    domain = random_domain(
        length=9,
        tld='chain' if chain_fixture.NODE_CLI.get_consensus_protocol_version()
        >= identifiers.PROTOCOL_LIMA else 'test')
    # let alice preclaim a name
    j = call_aecli('name', 'pre-claim', '--password', 'aeternity_bc',
                   account_alice_path, domain, '--wait')
    # retrieve the salt and the transaction hash
    salt = j.get("metadata", {}).get("salt")
    preclaim_hash = j.get("hash")
    # test that they are what we expect to be
    assert (isinstance(salt, int))
    assert (salt > 0)
    assert (utils.is_valid_hash(preclaim_hash, identifiers.TRANSACTION_HASH))
    # wait for confirmation
    chain_fixture.NODE_CLI.wait_for_confirmation(preclaim_hash)
    # now run the claim
    j = call_aecli('name', 'claim', account_alice_path, domain, '--password',
                   'aeternity_bc', '--name-salt', f"{salt}",
                   '--preclaim-tx-hash', preclaim_hash, '--wait')
    assert (utils.is_valid_hash(j.get("hash"), identifiers.TRANSACTION_HASH))
    # check that the tx was mined
    claim_height = chain_fixture.NODE_CLI.get_transaction_by_hash(
        hash=j.get('hash')).block_height
    assert (isinstance(claim_height, int) and claim_height > 0)
    # now we have a first claim
    # this is the name fee and the end block
    name_fee = AEName.compute_bid_fee(domain)
    aucion_end = AEName.compute_auction_end_block(domain, claim_height)
    print(
        f"Name {domain}, name_fee {name_fee}, claim height: {claim_height}, auction_end: {aucion_end}"
    )
    # now make another bid
    # first compute the new name fee
    name_fee = AEName.compute_bid_fee(domain, name_fee)
    j = call_aecli('name', 'bid', account_bob_path, domain, f'{name_fee}',
                   '--password', 'aeternity_bc', '--wait')
    assert (utils.is_valid_hash(j.get("hash"), identifiers.TRANSACTION_HASH))
    # check that the tx was mined
    claim_height = chain_fixture.NODE_CLI.get_transaction_by_hash(
        hash=j.get('hash')).block_height
    assert (isinstance(claim_height, int) and claim_height > 0)
    aucion_end = AEName.compute_auction_end_block(domain, claim_height)
    print(
        f"Name {domain}, name_fee {name_fee}, claim height: {claim_height}, auction_end: {aucion_end}"
    )
    name = chain_fixture.NODE_CLI.AEName(domain)
    # name should still be available
    assert (name.is_available())
コード例 #5
0
    def tx_call(self,
                keypair,
                function,
                arg,
                amount=10,
                gas=CONTRACT_DEFAULT_GAS,
                gas_price=CONTRACT_DEFAULT_GAS_PRICE,
                fee=DEFAULT_FEE,
                vm_version=CONTRACT_DEFAULT_VM_VERSION,
                tx_ttl=DEFAULT_TX_TTL):
        """Call a sophia contract"""

        if not utils.is_valid_hash(self.address, prefix="ct"):
            raise ValueError("Missing contract id")

        try:
            call_data = self.encode_calldata(function, arg)
            txb = TxBuilder(self.client, keypair)
            tx, sg, tx_hash = txb.tx_contract_call(self.address, call_data,
                                                   function, arg, amount, gas,
                                                   gas_price, vm_version, fee,
                                                   tx_ttl)
            # post the transaction to the chain
            txb.post_transaction(tx, tx_hash)
            # wait for transaction to be mined
            txb.wait_tx(tx_hash)
            # unsigned transaction of the call
            call_obj = self.client.cli.get_transaction_info_by_hash(
                hash=tx_hash)
            return call_obj
        except OpenAPIClientException as e:
            raise ContractError(e)
コード例 #6
0
ファイル: node.py プロジェクト: delimitry/aepp-sdk-python
 def get_transaction(self, transaction_hash):  # TODO: continue
     if not utils.is_valid_hash(transaction_hash,
                                identifiers.TRANSACTION_HASH):
         raise TypeError(
             f"Input {transaction_hash} is not a valid aeternity address")
     tx = self.get_transaction_by_hash(hash=transaction_hash)
     return self.tx_builder.parse_node_reply(tx)
コード例 #7
0
ファイル: contract.py プロジェクト: aeternity/aepp-sdk-python
    def __prepare_call_tx(self, contract_id, address, function, calldata,
                          amount, gas, gas_price, fee, abi_version, tx_ttl):
        """
        Prepare a Contract call transaction

        :param contract_id: the contract address
        :param address: the address preparing the transaction
        """

        if not utils.is_valid_hash(contract_id,
                                   prefix=identifiers.CONTRACT_ID):
            raise ValueError(f"Invalid contract id {contract_id}")
        # parse amounts
        amount, gas_price, fee = utils._amounts_to_aettos(
            amount, gas_price, fee)
        # check if the contract exists
        try:
            self.client.get_contract(pubkey=contract_id)
        except openapi.OpenAPIClientException:
            raise ContractError(f"Contract {contract_id} not found")

        try:
            # retrieve the correct vm/abi version
            _, abi = self.client.get_vm_abi_versions()
            abi_version = abi if abi_version is None else abi_version
            # get the transaction builder
            txb = self.client.tx_builder
            # get the account nonce and ttl
            nonce, ttl = self.client._get_nonce_ttl(address, tx_ttl)
            # build the transaction
            return txb.tx_contract_call(address, contract_id, calldata,
                                        function, amount, gas, gas_price,
                                        abi_version, fee, ttl, nonce)
        except openapi.OpenAPIClientException as e:
            raise ContractError(e)
コード例 #8
0
 def get_account(self, address: str) -> Account:
     """
     Retrieve an account by it's public key
     """
     if not utils.is_valid_hash(address, identifiers.ACCOUNT_ID):
         raise TypeError(f"Input {address} is not a valid aeternity address")
     remote_account = self.get_account_by_pubkey(pubkey=address)
     return Account.from_node_api(remote_account)
コード例 #9
0
ファイル: aens.py プロジェクト: aeternity/aepp-sdk-python
 def _get_pointers(self, targets):
     """
     Create a list of pointers given a list of addresses
     """
     pointers = []
     for t in targets:
         if isinstance(t, tuple):
             # custom target
             pointers.append({'key': t[0], 'id': t[1]})
         elif utils.is_valid_hash(t, prefix=identifiers.ACCOUNT_ID):
             pointers.append({'id': t, 'key': 'account_pubkey'})
         elif utils.is_valid_hash(t, prefix=identifiers.ORACLE_ID):
             pointers.append({'id': t, 'key': 'oracle_pubkey'})
         elif utils.is_valid_hash(t, prefix=identifiers.CONTRACT_ID):
             pointers.append({'id': t, 'key': 'contract_pubkey'})
         else:
             raise TypeError(f"invalid aens update pointer target {t}")
     return pointers
コード例 #10
0
ファイル: test_cli.py プロジェクト: noandrea/aepp-sdk-python
def test_cli_generate_account(tempdir):
    account_key = os.path.join(tempdir, 'key')
    j = call_aecli('account', 'create', account_key, '--password', 'secret',
                   '--overwrite')
    gen_address = j.get("Address")
    assert utils.is_valid_hash(gen_address, prefix='ak')
    # make sure the folder contains the keys
    files = sorted(os.listdir(tempdir))
    assert len(files) == 1
    assert files[0].startswith("key")
コード例 #11
0
 def at(self, address):
     """
     Set contract address
     """
     if not address or not utils.is_valid_hash(
             address, prefix=identifiers.CONTRACT_ID):
         raise ValueError(f"Invalid contract address {address}")
     if not self.contract.is_deployed(address):
         raise ValueError("Contract not deployed")
     self.address = address
     self.deployed = True
コード例 #12
0
ファイル: node.py プロジェクト: aeternity/aepp-sdk-python
    def get_transaction(self, transaction_hash: str) -> transactions.TxObject:
        """
        Retrieve a transaction by it's hash.

        Args:
            transaction_hash: the hash of the transaction to retrieve
        Returns:
           the TxObject of the transaction
        Raises:
            ValueError: if the transaction  hash is not a valid hash for transactions
        """
        if not utils.is_valid_hash(transaction_hash, identifiers.TRANSACTION_HASH):
            raise ValueError(f"Input {transaction_hash} is not a valid aeternity address")
        tx = self.get_transaction_by_hash(hash=transaction_hash)
        return self.tx_builder.parse_node_reply(tx)
コード例 #13
0
def test_signing_is_valid_hash():
    # input (hash_str, prefix, expected output)
    args = [
        ('ak_me6L5SSXL4NLWv5EkQ7a16xaA145Br7oV4sz9JphZgsTsYwGC', None, True),
        ('ak_me6L5SSXL4NLWv5EkQ7a16xaA145Br7oV4sz9JphZgsTsYwGC', 'ak', True),
        ('ak_me6L5SSXL4NLWv5EkQ7a16xaA145Br7oV4sz9JphZgsTsYwGC', 'bh', False),
        ('ak_me6L5SSXL4NLWv5EkQ7a16xaA145Br7oV4sz9JphZgsTsYwYC', None, False),
        ('ak_me6L5SSXL4NLWv5EkQ7a18xaA145Br7oV4sz9JphZgsTsYwGC', None, False),
        ('bh_vzUC2jVuAfpBC3tMAHhxwxJnTFymckNYeQ5TWZua1pydabqNu', None, True),
        ('th_YqPSTzs73PiKFhFcALYWWu41uNLc6yp63ZC35jzzuJYA9PMui', None, True),
    ]

    for a in args:
        got = is_valid_hash(a[0], a[1])
        expected = a[2]
        assert got == expected
コード例 #14
0
    def call(self,
             contract_id,
             account,
             function,
             arg,
             calldata,
             amount=defaults.CONTRACT_AMOUNT,
             gas=defaults.CONTRACT_GAS,
             gas_price=defaults.CONTRACT_GAS_PRICE,
             fee=defaults.FEE,
             abi_version=None,
             tx_ttl=defaults.TX_TTL):
        """Call a sophia contract"""

        if not utils.is_valid_hash(contract_id,
                                   prefix=identifiers.CONTRACT_ID):
            raise ValueError(f"Invalid contract id {contract_id}")
        # check if the contract exists
        try:
            self.client.get_contract(pubkey=contract_id)
        except openapi.OpenAPIClientException:
            raise ContractError(f"Contract {contract_id} not found")

        try:
            # retrieve the correct vm/abi version
            _, abi = self.client.get_vm_abi_versions()
            abi_version = abi if abi_version is None else abi_version
            # 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)
            # build the transaction
            tx = txb.tx_contract_call(account.get_address(), self.address,
                                      calldata, function, arg, amount, gas,
                                      gas_price, abi_version, fee, ttl, nonce)
            # sign the transaction
            tx_signed = self.client.sign_transaction(account, tx.tx)
            # post the transaction to the chain
            self.client.broadcast_transaction(tx_signed.tx, tx_signed.hash)
            return tx_signed
        except openapi.OpenAPIClientException as e:
            raise ContractError(e)
コード例 #15
0
ファイル: node.py プロジェクト: noandrea/aepp-sdk-python
    def spend(self, account: Account,
              recipient_id: str,
              amount,
              payload: str = "",
              fee: int = defaults.FEE,
              tx_ttl: int = defaults.TX_TTL) -> transactions.TxObject:
        """
        Create and execute a spend transaction,
        automatically retrieve the nonce for the siging account
        and calculate the absolut ttl.

        :param account: the account signing the spend transaction (sender)
        :param recipient_id: the recipient address or name_id
        :param amount: the amount to spend
        :param payload: the payload for the transaction
        :param fee: the fee for the transaction (automatically calculated if not provided)
        :param tx_ttl: the transaction ttl expressed in relative number of blocks

        :return: the TxObject of the transaction

        :raises TypeError:  if the recipient_id is not a valid name_id or address

        """
        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.")
        # parse amount and fee
        amount, fee = utils._amounts_to_aettos(amount, fee)
        # retrieve the nonce
        account.nonce = self.get_next_nonce(account.get_address()) if account.nonce == 0 else account.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, amount, payload, fee, tx_ttl.absolute_ttl, account.nonce)
        # get the signature
        tx = self.sign_transaction(account, tx)
        # post the signed transaction transaction
        self.broadcast_transaction(tx)
        return tx
コード例 #16
0
ファイル: node.py プロジェクト: noandrea/aepp-sdk-python
 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
コード例 #17
0
    def tx_call(self, account, function, arg,
                amount=defaults.CONTRACT_AMOUNT,
                gas=defaults.CONTRACT_GAS,
                gas_price=defaults.CONTRACT_GAS_PRICE,
                fee=defaults.FEE,
                vm_version=None,
                abi_version=None,
                tx_ttl=defaults.TX_TTL):
        """Call a sophia contract"""

        if not utils.is_valid_hash(self.address, prefix=CONTRACT_ID):
            raise ValueError("Missing contract id")

        try:
            # retrieve the correct vm/abi version
            vm, abi = self._get_vm_abi_versions()
            vm_version = vm if vm_version is None else vm_version
            abi_version = abi if abi_version is None else abi_version
            # prepare the call data
            call_data = self.encode_calldata(function, arg)
            # 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)
            # build the transaction
            tx = txb.tx_contract_call(account.get_address(), self.address, call_data, function, arg,
                                      amount, gas, gas_price, abi_version,
                                      fee, ttl, nonce)
            # sign the transaction
            tx_signed = self.client.sign_transaction(account, tx.tx)
            # post the transaction to the chain
            self.client.broadcast_transaction(tx_signed.tx, tx_signed.hash)
            # unsigned transaction of the call
            call_obj = self.client.get_transaction_info_by_hash(hash=tx_signed.hash)
            return tx_signed, call_obj
        except OpenAPIClientException as e:
            raise ContractError(e)
コード例 #18
0
ファイル: signing.py プロジェクト: delimitry/aepp-sdk-python
 def _raw_key(cls, key_string):
     """decode a key with different method between signing and addresses"""
     key_string = str(key_string)
     if utils.is_valid_hash(key_string, prefix=ACCOUNT_ID):
         return hashing.decode(key_string.strip())
     return bytes.fromhex(key_string.strip())
コード例 #19
0
def test_evm_contract_compile():
    contract = EPOCH_CLI.Contract(aer_identity_contract, abi=Contract.EVM)
    print(contract)
    assert contract.bytecode is not None
    assert utils.is_valid_hash(contract.bytecode, prefix='cb')
コード例 #20
0
def test_sophia_encode_calldata():
    contract = EPOCH_CLI.Contract(aer_identity_contract)
    result = contract.encode_calldata('main', '1')
    assert result is not None
    assert utils.is_valid_hash(result, prefix='cb')
コード例 #21
0
def test_sophia_contract_compile():
    contract = EPOCH_CLI.Contract(aer_identity_contract)
    assert contract is not None
    utils.is_valid_hash(contract.bytecode, prefix='cb')
コード例 #22
0
def test_sophia_contract_compile(chain_fixture):
    contract = chain_fixture.NODE_CLI.Contract(aer_identity_contract)
    assert contract is not None
    utils.is_valid_hash(contract.bytecode, prefix='cb')
コード例 #23
0
ファイル: faucet.py プロジェクト: apeunit/aepp-faucet
def rest_faucet(recipient_address):
    """top up an account"""
    notification_message = ""
    try:
        # validate the address
        app.logger.info(f"Top up request for {recipient_address}")
        if not is_valid_hash(recipient_address, prefix='ak'):
            notification_message = "The provided account is not valid"
            return jsonify({"message": notification_message}), 400
        # check if the account is still in the cache
        registration_date = app.config['address_cache'].get(recipient_address)
        if registration_date is not None:
            graylist_exp = registration_date + timedelta(
                seconds=app.config['cache_max_age'])
            notification_message = f"The account `{recipient_address}` is graylisted for another {pretty_time_delta(graylist_exp, datetime.now())}"
            msg = f"The account is graylisted for another {pretty_time_delta(graylist_exp, datetime.now())}"
            return jsonify({"message": msg}), 425
        app.config['address_cache'][recipient_address] = datetime.now()
        # sender account
        sender = signing.Account.from_private_key_string(
            FAUCET_ACCOUNT_PRIV_KEY)
        # execute the spend transaction
        client = app.config.get("node_client")
        tx = client.spend(sender,
                          recipient_address,
                          TOPUP_AMOUNT,
                          payload=SPEND_TX_PAYLOAD)
        # print the full transaction
        balance = client.get_account_by_pubkey(
            pubkey=recipient_address).balance
        app.logger.info(
            f"Top up account {recipient_address} of {TOPUP_AMOUNT} tx_hash: {tx.hash} completed"
        )
        app.logger.debug(f"tx: {tx.tx}")
        # notifications
        node = NODE_URL.replace("https://", "")
        notification_message = f"Account `{recipient_address}` credited with {format_amount(TOPUP_AMOUNT)} tokens on `{node}`. (tx hash: `{tx}`)"
        # return
        return jsonify({"tx_hash": tx.hash, "balance": balance})
    except OpenAPIClientException as e:
        app.logger.error(
            f"API error: top up account {recipient_address} of {TOPUP_AMOUNT} failed with error",
            e)
        # notifications
        node = NODE_URL.replace("https://", "")
        notification_message = f"API error: top up account {recipient_address} of {TOPUP_AMOUNT} on {node} failed with error {e}"
        return jsonify({
            "message":
            "The node is temporarily unavailable, please try again later"
        }), 503
    except Exception as e:
        app.logger.error(
            f"Generic error: top up account {recipient_address} of {TOPUP_AMOUNT} failed with error",
            e)
        # notifications
        node = NODE_URL.replace("https://", "")
        notification_message = f"API error: top up account {recipient_address} of {TOPUP_AMOUNT} on {node} failed with error {e}"
        return jsonify({
            "message":
            f"""Unknown error, please contact
        <a href="{SUPPORT_EMAIL}" class="hover:text-pink-lighter">{SUPPORT_EMAIL}</a>"""
        }), 500
    finally:
        try:
            # telegram bot notifications
            if TELEGRAM_API_TOKEN:
                if TELEGRAM_CHAT_ID is None or TELEGRAM_API_TOKEN is None:
                    app.logger.warning(
                        f"missing chat_id ({TELEGRAM_CHAT_ID}) or token {TELEGRAM_API_TOKEN} for telegram integration"
                    )
                bot = telegram.Bot(token=TELEGRAM_API_TOKEN)
                bot.send_message(chat_id=TELEGRAM_CHAT_ID,
                                 text=notification_message,
                                 parse_mode=telegram.ParseMode.MARKDOWN)
        except Exception as e:
            app.logger.error(f"Error delivering notifications", e)
コード例 #24
0
def rest_faucet(recipient_address):
    """top up an account"""
    amount = int(os.environ.get('TOPUP_AMOUNT', 250))
    ttl = int(os.environ.get('TX_TTL', 100))
    try:
        # validate the address
        logging.info(f"Top up request for {recipient_address}")
        if not is_valid_hash(recipient_address, prefix='ak'):
            return jsonify({"message":
                            "The provided account is not valid"}), 400

        # genesys key
        bank_wallet_key = os.environ.get('FAUCET_ACCOUNT_PRIV_KEY')
        kp = Account.from_private_key_string(bank_wallet_key)
        # target node
        Config.set_defaults(
            Config(
                external_url=os.environ.get('EPOCH_URL',
                                            "https://sdk-testnet.aepps.com"),
                internal_url=os.environ.get('EPOCH_URL_DEBUG',
                                            "https://sdk-testnet.aepps.com"),
                network_id=os.environ.get('NETWORK_ID', "ae_devnet"),
            ))
        # payload
        payload = os.environ.get('TX_PAYLOAD', "Faucet Tx")
        # execute the spend transaction
        client = EpochClient()
        _, _, _, tx = client.spend(kp,
                                   recipient_address,
                                   amount,
                                   payload=payload,
                                   tx_ttl=ttl)
        balance = client.get_account_by_pubkey(
            pubkey=recipient_address).balance
        logging.info(
            f"Top up accont {recipient_address} of {amount} tx_ttl: {ttl} tx_hash: {tx} completed"
        )

        # telegram bot notifications
        enable_telegaram = os.environ.get('TELEGRAM_API_TOKEN', False)
        if enable_telegaram:
            token = os.environ.get('TELEGRAM_API_TOKEN', None)
            chat_id = os.environ.get('TELEGRAM_CHAT_ID', None)
            node = os.environ.get('EPOCH_URL',
                                  "https://sdk-testnet.aepps.com").replace(
                                      "https://", "")
            if token is None or chat_id is None:
                logging.warning(
                    f"missing chat_id ({chat_id}) or token {token} for telegram integration"
                )
            bot = telegram.Bot(token=token)
            bot.send_message(
                chat_id=chat_id,
                text=
                f"Account `{recipient_address}` credited with {amount} tokens on `{node}`. (tx hash: `{tx}`)",
                parse_mode=telegram.ParseMode.MARKDOWN)
        return jsonify({"tx_hash": tx, "balance": balance})
    except OpenAPIClientException as e:
        logging.error(
            f"Api error: top up accont {recipient_address} of {amount} failed with error",
            e)
        return jsonify({
            "message":
            "The node is temporarily unavailable, contact aepp-dev[at]aeternity.com"
        }), 503
    except Exception as e:
        logging.error(
            f"Generic error: top up accont {recipient_address} of {amount} failed with error",
            e)
        return jsonify({
            "message":
            "Unknow error, please contact contact aepp-dev[at]aeternity.com"
        }), 500
コード例 #25
0
 def to_sophia_bytes(self, arg, generic, bindings={}):
     if isinstance(arg, str):
         val = hashing.decode(arg).hex() if utils.is_valid_hash(arg) else arg
         return f'#{val}'
     elif isinstance(arg, bytes):
         return f"#{arg.hex()}"
コード例 #26
0
ファイル: test_cli.py プロジェクト: noandrea/aepp-sdk-python
def test_cli_inspect_key_block_by_height(chain_fixture):
    height = chain_fixture.NODE_CLI.get_current_key_block_height()
    j = call_aecli('inspect', str(height))
    assert utils.is_valid_hash(j.get("hash"), prefix=["kh", "mh"])
    assert j.get("height") == height