В этом руководстве показаны шаги по созданию, подписанию и отправке транзакции в формате BCS с использованием Aptos Typescript SDK.
Отправка транзакций в BCS в сравнении с JSON
BCS: Отправка транзакций в формате BCS более безопасна, чем отправка в формате JSON. В этом методе вы создадите BCS-сериализованное сообщение для подписи на стороне клиента. Подробное руководство по отправке в формате BCS см. в руководстве "Создание подписанной транзакции". Typescript SDK поддерживает подписание и отправку транзакций в формате BCS.
JSON: Если вы отправляете транзакции в формате JSON, вы будете использовать REST API и полагаться на сервер Aptos для создания подписывающего сообщения. Такой подход создает риск того, что пользователь подпишет непреднамеренную транзакцию, подделанную вредоносным сервером API. О том, как отправлять транзакции в формате JSON, читайте в руководстве "Ваша первая транзакция". Кроме того, Typescript SDK предоставляет оболочки, позволяющие значительно сократить объем ручной работы, необходимой для подготовки и отправки транзакций в формате JSON.
ПОДСКАЗКА
Мы настоятельно рекомендуем вам использовать формат BCS для отправки транзакций в блокчейн Aptos.
Прежде чем приступить к работе
Прежде чем продолжить, установите последнюю версию Aptos TS SDK. Перейдите в корень каталога вашего проекта и запустите:
npm install aptos
или yarn add aptos
ПРИМЕЧАНИЕ
Смотрите исходный код этого руководства. Хотя в этом руководстве используется Typescript, Aptos TS SDK также работает в проектах Javascript.
Шаг 1: Создание учетных записей
Предположим, что пользователь Alice хочет отправить 717 пробных coins пользователю Bob. Сначала нам нужно создать две учетные записи пользователей.
import { AptosClient, AptosAccount, FaucetClient, BCS, TxnBuilderTypes } from "aptos";
// devnet is used here for testing
const NODE_URL = "https://fullnode.devnet.aptoslabs.com";
const FAUCET_URL = "https://faucet.devnet.aptoslabs.com";
const client = new AptosClient(NODE_URL);
const faucetClient = new FaucetClient(NODE_URL, FAUCET_URL);
// Generates key pair for Alice
const alice = new AptosAccount();
// Creates Alice's account and mint 5000 test coins
await faucetClient.fundAccount(alice.address(), 5000);
let resources = await client.getAccountResources(alice.address());
let accountResource = resources.find((r) => r.type === "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>");
console.log(`Alice coins: ${(accountResource?.data as any).coin.value}. Should be 5000!`);
// Generates key pair for Bob
const bob = new AptosAccount();
// Creates Bob's account and mint 0 test coins
await faucetClient.fundAccount(bob.address(), 0);
resources = await client.getAccountResources(bob.address());
accountResource = resources.find((r) => r.type === "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>");
console.log(`Bob coins: ${(accountResource?.data as any).coin.value}. Should be 0!`);
С помощью приведенного выше кода мы создали две учетные записи на Aptos devnet и заминтили 5000 тестовых coins для учетной записи Alice и 0 тестовых coins для учетной записи Bob.
Шаг 2. Подготовьте полезную среду транзакции
Typescript SDK поддерживает три типа полезной среды транзакций:
ScriptFunction
-
Script
и -
ModuleBundle
.
Подробности см. на сайте https://aptos-labs.github.io/ts-sdk-doc/classes/TxnBuilderTypes.TransactionPayload.html.
Полезная среда ScriptFunction
используется для вызова функции скрипта Move на цепочке. В полезной среде ScriptFunction
вы можете указать имя функции и аргументы.
Полезная среда Script
содержит байткод для выполнения Aptos MoveVM (Move Virtual Machine). В полезной среде Script
можно указать код сценария в байтах и аргументы сценария.
Полезная нагрузка ModuleBundle
используется для публикации нескольких модулей одновременно. В полезной нагрузке ModuleBundle
вы можете предоставить байткод модуля.
Для перевода coins с учетной записи Alice на учетную запись Bob нам необходимо подготовить полезную среду ScriptFunction
с функцией transfer
.
// We need to pass a token type to the `transfer` function.
const token = new TxnBuilderTypes.TypeTagStruct(TxnBuilderTypes.StructTag.fromString("0x1::aptos_coin::AptosCoin"));
const entryFunctionPayload = new TxnBuilderTypes.TransactionPayloadEntryFunction(
TxnBuilderTypes.EntryFunction.natural(
// Fully qualified module name, `AccountAddress::ModuleName`
"0x1::coin",
// Module function
"transfer",
// The coin type to transfer
[token],
// Arguments for function `transfer`: receiver account address and amount to transfer
[BCS.bcsToBytes(TxnBuilderTypes.AccountAddress.fromHex(bob.address())), BCS.bcsSerializeUint64(717)],
),
);
Функция Move transfer
требует тип coin в качестве аргумента type. Функция transfer
определена здесь https://github.com/aptos-labs/aptos-core/blob/faf4f94260d4716c8a774b3c17f579d203cc4013/aptos-move/framework/aptos-framework/sources/Coin.move#L311.
В приведенном выше фрагменте кода мы хотим передать AptosCoin
, который определен под учетной записью 0x1
и модулем AptosCoin
. Поэтому полное имя AptosCoin
будет 0x1::aptos_coin::AptosCoin
.
ПРИМЕЧАНИЕ
Все аргументы в полезной среде ScriptFunction должны быть сериализованы BCS. В приведенном выше коде мы сериализовали адрес учетной записи Bob'а и номер суммы для перевода.
Шаг 3. Подпишите и отправьте транзакцию
После сборки полезной нагрузки транзакции мы готовы создать экземпляр RawTransaction
, который обертывает только что созданную полезную нагрузку. Затем RawTransaction
можно подписать и отправить.
// Create a raw transaction out of the transaction payload
const rawTxn = await client.generateRawTransaction(alice.address(), entryFunctionPayload);
// Sign the raw transaction with Alice's private key
const bcsTxn = AptosClient.generateBCSTransaction(alice, rawTxn);
// Submit the transaction
const transactionRes = await client.submitSignedBCSTransaction(bcsTxn);
// Wait for the transaction to finish
await client.waitForTransaction(transactionRes.hash);
resources = await client.getAccountResources(bob.address());
accountResource = resources.find((r) => r.type === "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>");
console.log(`Bob coins: ${(accountResource?.data as any).coin.value}. Should be 717!`);
Результат
Результат после выполнения:
Alice coins: 5000. Should be 5000!
Bob coins: 0. Should be 0!
Bob coins: 717. Should be 717!
Создание необработанных транзакций с помощью конструктора транзакций ABI
Чтобы уменьшить бремя сериализации аргументов полезной нагрузки вручную, Typescript SDK также предоставляет конструктор транзакций на основе ABI (Application Binary Interface). ABI включает информацию о сигнатурах функций Move. С помощью ABI, Typescript SDK может сериализовать собственные значения JS/TS. Файлы ABI создаются при компиляции пакетов Move с помощью Aptos CLI. Для создания необработанных транзакций с помощью ABI transaction builder сначала необходимо преобразовать ABI-файлы в шестнадцатеричные строки. На linux/Mac это можно сделать с помощью следующей команды:
cat aptos-core/aptos-move/framework/aptos-token/build/AptosToken/abis/token_transfers/offer_script.abi | od -v -t x1 -A n | tr -d ' \n'
А затем вы можете создавать необработанные транзакции:
import { TransactionBuilderABI, HexString } from "aptos";
// You can pass in multiple ABIs
const transactionBuilder = new TransactionBuilderABI([
new HexString("ABI_HEX_STRING_1").toUint8Array(),
new HexString("ABI_HEX_STRING_2").toUint8Array(),
]);
const rawTransaction = transactionBuilder.build(
"0x3::token_transfers::offer_script",
[],
[receiver, creator, collectionName, name, property_version, amount],
);
После создания необработанных транзакций вы можете выполнить описанный выше Шаг 3, чтобы подписать и отправить транзакцию.
Top comments (0)