Ваша первая транзакция

В этом руководстве в пошаговом порядке описывается создание, отправка и проверка транзакций, отправленных в Aptos Blockchain:

  1. Создайте представление учетной записи.

Каждая учетная запись Aptos имеет уникальный адрес учетной записи. Владелец этой учетной записи владеет парой открытого и закрытого ключей, которая сопоставляется с адресом учетной записи Aptos, и, в свою очередь, ключом аутентификации, хранящимся в этой учетной записи.

ПРИМЕЧАНИЕ

Подробнее об учетных записях Aptos см. в разделе Учетные записи.

2. Подготовьте оболочку для интерфейсов REST.

Aptos предоставляет REST API для взаимодействия с блокчейном. Эти шаги подготавливают оболочки вокруг этого API для получения информации об учетной записи, а также для создания транзакции, ее подписания и отправки.

3. Подготовьте оболочку для интерфейса Faucet.

Используя интерфейс Faucet в Aptos devnet, этот обучающий код автоматически создает аккаунт с адресом 0x1 и пополняет его.

4. Объедините вышеуказанные оболочки в приложение, выполните и проверьте.

Прежде чем начать

Сначала убедитесь, что вы выполнили следующие шаги, чтобы вы могли запустить руководство.

  1. Клонируйте репозиторий Aptos.

git clone https://github.com/aptos-labs/aptos-core.git

2. Перейдитеcd в каталог aptos-core .

cd aptos-core

3. Проверьте ветку devnet, используя git checkout --track origin/devnet.

4. Запустите bash-скрипт scripts/dev_setup.sh , как показано ниже. Это подготовит вашу среду разработки.

./scripts/dev_setup.sh

5. Обновите текущую среду оболочки.

source ~/.cargo/env

Теперь, когда ваша среда разработки готова, вы можете запустить это руководство.

Источник GitHub

Перейдите по ссылкам ниже, чтобы получить доступ к исходному коду руководства:

См. first_transaction.py код в Python version данного руководства.

Шаг 1: Создайте представление учетной записи

Эти шаги создают представление учетной записи. См. также разделы Учетные записи и Creating a Signed Transaction.

class Account:
    """Represents an account as well as the private, public key-pair for the Aptos blockchain."""

    def __init__(self, seed: bytes = None) -> None:
        if seed is None:
            self.signing_key = SigningKey.generate()
        else:
            self.signing_key = SigningKey(seed)

    def address(self) -> str:
        """Returns the address associated with the given account"""

        return self.auth_key()

    def auth_key(self) -> str:
        """Returns the auth_key for the associated account"""

        hasher = hashlib.sha3_256()
        hasher.update(self.signing_key.verify_key.encode() + b'\x00')
        return hasher.hexdigest()

    def pub_key(self) -> str:
        """Returns the public key for the associated account"""

        return self.signing_key.verify_key.encode().hex()

Шаг 2: REST интерфейс

Хотя данные из интерфейса REST можно считывать напрямую, следующие примеры кода демонстрируют более эргономичный подход при использовании интерфейса REST для:

  • Получение данных реестра из полной ноды, включая данные учетной записи и ресурсов учетной записи.

  • Построение подписанных транзакций, представленных в формате JSON.

class RestClient:
    """A wrapper around the Aptos-core Rest API"""

    def __init__(self, url: str) -> None:
        self.url = url

Шаг 2.1: Чтение аккаунта

Ниже приведены оболочки для запроса данных учетной записи.

 def account(self, account_address: str) -> Dict[str, str]:
        """Returns the sequence number and authentication key for an account"""

        response = requests.get(f"{self.url}/accounts/{account_address}")
        assert response.status_code == 200, f"{response.text} - {account_address}"
        return response.json()

    def account_resource(self, account_address: str, resource_type: str) -> Optional[Dict[str, Any]]:
        response = requests.get(f"{self.url}/accounts/{account_address}/resource/{resource_type}")
        if response.status_code == 404:
            return None
        assert response.status_code == 200, response.text
        return response.json()

Шаг 2.2: Отправка транзакции

Далее демонстрируются основные функции построения, подписания и ожидания транзакции.

def generate_transaction(self, sender: str, payload: Dict[str, Any]) -> Dict[str, Any]:
        """Generates a transaction request that can be submitted to produce a raw transaction that
        can be signed, which upon being signed can be submitted to the blockchain. """

        account_res = self.account(sender)
        seq_num = int(account_res["sequence_number"])
        txn_request = {
            "sender": f"0x{sender}",
            "sequence_number": str(seq_num),
            "max_gas_amount": "2000",
            "gas_unit_price": "1",
            "gas_currency_code": "XUS",
            "expiration_timestamp_secs": str(int(time.time()) + 600),
            "payload": payload,
        }
        return txn_request

    def sign_transaction(self, account_from: Account, txn_request: Dict[str, Any]) -> Dict[str, Any]:
        """Converts a transaction request produced by `generate_transaction` into a properly signed
        transaction, which can then be submitted to the blockchain."""

        res = requests.post(f"{self.url}/transactions/signing_message", json=txn_request)
        assert res.status_code == 200, res.text
        to_sign = bytes.fromhex(res.json()["message"][2:])
        signature = account_from.signing_key.sign(to_sign).signature
        txn_request["signature"] = {
            "type": "ed25519_signature",
            "public_key": f"0x{account_from.pub_key()}",
            "signature": f"0x{signature.hex()}",
        }
        return txn_request

    def submit_transaction(self, txn: Dict[str, Any]) -> Dict[str, Any]:
        """Submits a signed transaction to the blockchain."""

        headers = {'Content-Type': 'application/json'}
        response = requests.post(f"{self.url}/transactions", headers=headers, json=txn)
        assert response.status_code == 202, f"{response.text} - {txn}"
        return response.json()
    
    def execute_transaction_with_payload(self, account_from: Account, payload: Dict[str, Any]) -> Dict[str, Any]:
        """Execute a transaction for the given payload."""
        
        txn_request = self.generate_transaction(account_from.address(), payload)
        signed_txn = self.sign_transaction(account_from, txn_request)
        return self.submit_transaction(signed_txn)

    def transaction_pending(self, txn_hash: str) -> bool:
        response = requests.get(f"{self.url}/transactions/{txn_hash}")
        if response.status_code == 404:
            return True
        assert response.status_code == 200, f"{response.text} - {txn_hash}"
        return response.json()["type"] == "pending_transaction"

    def wait_for_transaction(self, txn_hash: str) -> None:
        """Waits up to 10 seconds for a transaction to move past pending state."""

        count = 0
        while self.transaction_pending(txn_hash):
            assert count < 10, f"transaction {txn_hash} timed out"
            time.sleep(1)
            count += 1
        response = requests.get(f"{self.url}/transactions/{txn_hash}")
        assert "success" in response.json(), f"{response.text} - {txn_hash}"

Шаг 2.3: Логика, специфичная для конкретного приложения

Ниже показано, как считывать данные из блокчейна и как отправлять конкретную транзакцию.

def account_balance(self, account_address: str) -> Optional[int]:
        """Returns the test coin balance associated with the account"""
        return self.account_resource(account_address, "0x1::Coin::CoinStore<0x1::TestCoin::TestCoin>")

    def transfer(self, account_from: Account, recipient: str, amount: int) -> str:
        """Transfer a given coin amount from a given Account to the recipient's account address.
        Returns the sequence number of the transaction used to transfer."""

        payload = {
            "type": "script_function_payload",
            "function": "0x1::Coin::transfer",
            "type_arguments": ["0x1::TestCoin::TestCoin"],
            "arguments": [
                f"0x{recipient}",
                str(amount),
            ]
        }
        txn_request = self.generate_transaction(account_from.address(), payload)
        signed_txn = self.sign_transaction(account_from, txn_request)
        res = self.submit_transaction(signed_txn)
        return str(res["hash"])

Шаг 3: Faucet интерфейс

Сборщики Aptos Blockchain выдают учетным записям тестовые токены. Эти тестовые токены можно использовать для тестирования, например, для оплаты газа или передачи токенов между пользователями. Aptos Faucet также может создавать учетные записи, если они не существуют. Для интерфейса Aptos Faucet требуется открытый ключ, представленный в виде строки в шестнадцатеричном коде.

class FaucetClient:
    """Faucet creates and funds accounts. This is a thin wrapper around that."""

    def __init__(self, url: str, rest_client: RestClient) -> None:
        self.url = url
        self.rest_client = rest_client

    def fund_account(self, address: str, amount: int) -> None:
        """This creates an account if it does not exist and mints the specified amount of
        coins into that account."""
        txns = requests.post(f"{self.url}/mint?amount={amount}&address={address}")
        assert txns.status_code == 200, txns.text
        for txn_hash in txns.json():
            self.rest_client.wait_for_transaction(txn_hash)

Шаг 4: Запустите приложение

Наконец, мы можем запустить приложение и проверить вывод.

Для Python3:

  1. Убедитесь, что выполнены предварительные требования, описанные в разделе Прежде чем начать.

  2. Перейдите cd в каталог aptos-core/developer-docs-site/static/examples/python .

  3. Установите необходимые библиотеки: pip3 install -r requirements.txt.

  4. Запустите пример: python3 first_transaction.py.

Результат

Результат после выполнения:

=== Addresses ===
Alice: e26d69b8d3ff12874358da6a4082a2ac
Bob: c8585f009c8a90f22c6b603f28b9ed8c

=== Initial Balances ===
Alice: 1000000000
Bob: 0

=== Final Balances ===
Alice: 999998957
Bob: 1000

Результат показывает, что Боб получил 1000 монет от Алисы. Алиса заплатила 43 монеты за газ.

Проверка

Данные можно проверить, посетив либо интерфейс REST, либо программу анализа:

ПРИМЕЧАНИЕ

Aptos devnet периодически перезапускается, поэтому приведенные выше ссылки могут не работать. Попробуйте выполнить инструкцию самостоятельно, а затем проверьте учетные записи в Aptos Explorer.

Last updated