В этом руководстве описывается, как генерировать и отправлять транзакции в блокчейн Aptos, а также проверять эти отправленные транзакции. Пример transfer-coin, используемый в этом руководстве, создан с помощью Aptos SDKs.
Шаг 1: Выберите SDK
Установите предпочтительный SDK из приведенного ниже списка:
Приведенный выше вывод демонстрирует, что пример transfer-coin выполняет следующие шаги:
Инициализация клиентов REST и faucet.
Создание двух учетных записей: Alice и Bob.
Финансирование и создание учетной записи Alice из faucet.
Создание учетной записи Bob из faucet.
Передача 1000 coins от Alice к Bob.
4 coins газа, оплаченные Alice для осуществления этого перевода.
Еще один перевод 1000 coins от Alice к Bob.
Дополнительные 4 coins газа, заплаченные Alice за этот перевод.
Далее ниже приведено описание функций SDK, которые используются для выполнения описанных выше действий.
Шаг 4: SDK в деталях
Код примера transfer-coin использует вспомогательные функции для взаимодействия с REST API. В этом разделе рассматривается каждый из вызовов и дается представление о функциональности.
СМОТРИТЕ ПОЛНЫЙ КОД
Полный код см. в Typescript transfer-coin, следуя приведенным ниже шагам.
СМОТРИТЕ ПОЛНЫЙ КОД
Полный код смотрите в Python transfer-coin, выполнив следующие шаги.
СМОТРИТЕ ПОЛНЫЙ КОД
Смотрите полный код на Rust transfer-coin, выполнив следующие действия.
Шаг 4.1: Инициализация клиентов
На первом этапе пример transfer-coin инициализирует REST и faucet-клиенты.
Клиент REST взаимодействует с API REST, и
Клиент faucet взаимодействует с сервисом devnet Faucet для создания и пополнения учетных записей.
СОВЕТ
По умолчанию URL-адреса обеих служб указывают на службы Aptos devnet. Однако их можно настроить с помощью следующих переменных среды:
APTOS_NODE_URL
APTOS_FAUCET_URL
Шаг 4.2: Создание локальных учетных записей
Следующим шагом будет создание двух учетных записей на локальном уровне. Учетные записи представляют собой состояние в сети и вне сети. Состояние вне сети состоит из адреса и пары открытого и закрытого ключей, используемых для аутентификации владельца. Этот шаг демонстрирует, как генерировать состояние вне сети.
В Aptos каждая учетная запись должна иметь представление в сети, чтобы поддерживать получение токенов и coins, а также взаимодействие в других dApp. Учетная запись представляет собой носитель для хранения активов, поэтому она должна быть явно создана. В данном примере используется Faucet для создания и пополнения учетной записи Alice и только для создания учетной записи Bob:
faucet_client.fund(alice.address(), 20_000).await.context("Failed to fund Alice's account")?;faucet_client.create_account(bob.address()).await.context("Failed to fund Bob's account")?;
Шаг 4.4: Чтение балансов
На этом этапе SDK преобразует один вызов в процесс запроса ресурса и чтения поля из этого ресурса.
За кулисами SDK запрашивает ресурс CoinStore для AptosCoin и считывает текущее хранимое значение:
defaccount_balance(self,account_address:str) ->int:"""Returns the test coin balance associated with the account"""returnself.account_resource(account_address,"0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>" )["data"]["coin"]["value"]
println!("Alice: {:?}",coin_client.get_account_balance(&alice.address()).await.context("Failed to get Alice's account balance the second time")?);println!("Bob: {:?}",coin_client.get_account_balance(&bob.address()).await.context("Failed to get Bob's account balance the second time")?);
За кулисами SDK запрашивает ресурс CoinStore для AptosCoin и считывает текущее хранимое значение:
Как и предыдущий шаг, это еще один вспомогательный шаг, который создает транзакцию, передающую coins от Alice к Bob. Для правильно созданных транзакций API возвращает хэш транзакции, который можно использовать в последующих шагах для проверки статуса транзакции. Блокчейн Aptos выполняет несколько проверок при отправке, и если какая-либо из них не проходит, пользователю выдается сообщение об ошибке. Эти проверки включают подпись транзакции, неиспользованный порядковый номер и отправку транзакции в соответствующую сеть.
transfer внутренне является EntryFunction в модуле Coin Move, т.е. функцией входа в Move, которую можно вызвать напрямую.
Функция Move хранится на модуле coin: 0x1::coin.
Поскольку модуль Coin может использоваться другими coins, при передаче необходимо явно указать, какой тип coins передавать. Если coinType не указан, то по умолчанию используется 0x1::aptos_coin::AptosCoin.
transfer внутренне является EntryFunction в модуле Coin Move, т.е. функцией входа в Move, которую можно вызвать напрямую.
Функция Move хранится на модуле coin:0x1::coin.
Поскольку модуль Coin может использоваться другими coins, при передаче необходимо явно использовать TypeTag, чтобы определить, какой coin передавать.
Аргументы транзакции должны быть помещены в TransactionArguments со спецификаторами типа (Serializer.{type}), которые будут сериализовать значение в соответствующий тип во время генерации транзакции.
lettxn_hash=coin_client.transfer(&mutalice,bob.address(),1_000,None).await.context("Failed to submit transaction to transfer coins")?;
За кулисами Rust SDK генерирует, подписывает и отправляет транзакцию:
letchain_id=self.api_client.get_index() .await .context("Failed to get chain ID")?.inner() .chain_id;let transaction_builder = TransactionBuilder::new(TransactionPayload::EntryFunction(EntryFunction::new(ModuleId::new(AccountAddress::ONE,Identifier::new("coin").unwrap()),Identifier::new("transfer").unwrap(),vec![TypeTag::from_str(options.coin_type).unwrap()],vec![bcs::to_bytes(&to_account).unwrap(),bcs::to_bytes(&amount).unwrap(), ], )),SystemTime::now() .duration_since(UNIX_EPOCH).unwrap() .as_secs()+options.timeout_secs,ChainId::new(chain_id),).sender(from_account.address()).sequence_number(from_account.sequence_number()).max_gas_amount(options.max_gas_amount).gas_unit_price(options.gas_unit_price);letsigned_txn=from_account.sign_with_transaction_builder(transaction_builder);Ok(self.api_client.submit(&signed_txn).await.context("Failed to submit transfer transaction")?.into_inner())
Разбиваем вышесказанное на части:
Сначала мы получаем ID сети, необходимый для создания рабочей нагрузки транзакции.
transfer внутренне является EntryFunction в модуле Coin Move, т.е. функцией входа в Move, которую можно вызвать напрямую.
Функция Move хранится на модуле coin: 0x1::coin.
Поскольку модуль Coin может использоваться другими coins, при передаче необходимо явно использовать TypeTag, чтобы определить, какой coin передавать.
Аргументы транзакции, такие как to_account и amount, должны быть закодированы как BCS для использования с TransactionBuilder.
Шаг 4.6: Ожидание разрешения транзакции
В Typescript достаточно просто вызвать coinClient.transfer, чтобы дождаться завершения транзакции. Функция вернет Transaction, возвращенную API, как только она будет обработана (успешно или неуспешно), или выдаст ошибку, если время обработки превысит таймаут.
Вы можете установить checkSuccess в true при вызове transfer, если хотите, чтобы он выбрасывал сообщение, если транзакция не была успешно зафиксирована:
awaitclient.waitForTransaction(txnHash);
Хэш транзакции можно использовать для запроса статуса транзакции:
rest_client.wait_for_transaction(txn_hash)
Хэш транзакции можно использовать для запроса статуса транзакции:
rest_client.wait_for_transaction(&txn_hash).await.context("Failed when waiting for the transfer transaction")?;