DEV Community

EgorMajj
EgorMajj

Posted on

Транзакции с использованием Typescript SDK

В этом руководстве показаны шаги по созданию, подписанию и отправке транзакции в формате 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!`);
Enter fullscreen mode Exit fullscreen mode

С помощью приведенного выше кода мы создали две учетные записи на Aptos devnet и заминтили 5000 тестовых coins для учетной записи Alice и 0 тестовых coins для учетной записи Bob.

Шаг 2. Подготовьте полезную среду транзакции

Typescript SDK поддерживает три типа полезной среды транзакций:

  1. ScriptFunction
  2. Script и
  3. 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)],
  ),
);
Enter fullscreen mode Exit fullscreen mode

Функция 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!`);
Enter fullscreen mode Exit fullscreen mode

Результат

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

Alice coins: 5000. Should be 5000!
Bob coins: 0. Should be 0!
Bob coins: 717. Should be 717!
Enter fullscreen mode Exit fullscreen mode

Создание необработанных транзакций с помощью конструктора транзакций 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'
Enter fullscreen mode Exit fullscreen mode

А затем вы можете создавать необработанные транзакции:

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],
);
Enter fullscreen mode Exit fullscreen mode

После создания необработанных транзакций вы можете выполнить описанный выше Шаг 3, чтобы подписать и отправить транзакцию.

Top comments (0)