DEV Community

EgorMajj
EgorMajj

Posted on

Руководство для разработчиков APTOS | Ваш первый модуль MOVE | Typescript

В этом руководстве подробно описано, как писать, скомпилировать, тестировать, публиковать и взаимодействовать с модулями Move на блокчейне Aptos. Шаги таковы:

  1. Написать, скомпилировать и протестировать Move-модуль.
  2. Публикация модуля Move в блокчейн Aptos
  3. Инициализировать ресурсы модуля Move и взаимодействовать с ними

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

В этом руководстве мы сосредоточимся на hello_blockchain.ts и повторно используем библиотеку first_transaction.ts из предыдущего руководства.

Вы можете найти проект typescript здесь

Шаг 1. Напишите и протестируйте модуль Move

Шаг 1.1 Загрузите Aptos-core

Для простоты этого упражнения в Aptos-core есть каталог move-examples, который позволяет легко создавать и тестировать модули Move без загрузки дополнительных ресурсов. Со временем мы расширим этот раздел, чтобы описать, как использовать инструменты Move для разработки.

А пока скачайте и подготовьте Aptos-core:

git clone https://github.com/aptos-labs/aptos-core.git
cd aptos-core
./scripts/dev_setup.sh
source ~/.cargo/env
git checkout origin/devnet
Enter fullscreen mode Exit fullscreen mode

Установите утилиту командной строки Aptos. Узнайте больше об утилите командной строки Aptos

cargo install --git https://github.com/aptos-labs/aptos-core.git aptos
Enter fullscreen mode Exit fullscreen mode

Шаг 1.2 Обзор модуля

В этом терминале измените содержимое каталогов на aptos-move/move-examples/hello_blockchain. Сохраните это окно терминала до конца этого руководства - позже мы будем называть его "Окно Move". В этом разделе мы рассмотрим файл sources/hello_blockchain.move.

Этот модуль позволяет пользователям создавать ресурс String под своей учетной записью и устанавливать его. Пользователи могут устанавливать только свой ресурс и не могут устанавливать чужие ресурсы.

module HelloBlockchain::Message {
    use std::string;
    use std::error;
    use std::signer;

    struct MessageHolder has key {
        message: string::String,
    }

    public entry fun set_message(account: signer, message_bytes: vector<u8>)
    acquires MessageHolder {
        let message = string::utf8(message_bytes);
        let account_addr = signer::address_of(&account);
        if (!exists<MessageHolder>(account_addr)) {
            move_to(&account, MessageHolder {
                message,
            })
        } else {
            let old_message_holder = borrow_global_mut<MessageHolder>(account_addr);
            old_message_holder.message = message;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

В приведенном выше коде две важные секции - это структура MessageHolder и функция set_message. set_message - это script функция, позволяющая вызывать ее непосредственно транзакциями. При ее вызове функция определяет, есть ли у текущей учетной записи ресурс MessageHolder, и создает и сохраняет message, если его нет. Если ресурс существует, message в MessageHolder перезаписывается.

Шаг 1.3 Тестирование модуля

Move позволяет проводить встроенные тесты, поэтому мы добавляем get_message для удобства получения message и тестовую функцию sender_can_set_message для проверки end-to-end процесса . Это можно проверить, запустив cargo test. В папке sources/hello_blockchain_test.move есть еще один тест, который демонстрирует другой метод написания тестов.

Его можно проверить, введя в терминале команду cargo test test test_hello_blockchain -p move-examples -- --exact.

Примечание: sender_can_set_message - это script функция для вызова script функции set_message.

    const ENO_MESSAGE: u64 = 0;

    public fun get_message(addr: address): string::String acquires MessageHolder {
        assert!(exists<MessageHolder>(addr), Errors::not_published(ENO_MESSAGE));
        *&borrow_global<MessageHolder>(addr).message
    }

    #[test(account = @0x1)]
    public(script) fun sender_can_set_message(account: signer) acquires MessageHolder {
        let addr = Signer::address_of(&account);
        set_message(account,  b"Hello, Blockchain");

        assert!(
          get_message(addr) == string::utf8(b"Hello, Blockchain"),
          0
        );
    }
Enter fullscreen mode Exit fullscreen mode

Шаг 2. Публикация и взаимодействие с модулем Move

Теперь мы возвращаемся к нашему приложению, чтобы развернуть модуль на блокчейне Aptos и взаимодействовать с ним. Как упоминалось ранее, это руководство основывается на предыдущем руководстве и использует общий код. В результате в этом руководстве обсуждаются только новые возможности этой библиотеки, включая возможность публикации, отправку транзакции set_message и чтение MessageHolder::message. Единственным отличием от публикации модуля и отправки транзакции является тип полезной нагрузки. См. следующее:

Шаг 2.1 Публикация модуля Move

const client = new AptosClient(NODE_URL);
const faucetClient = new FaucetClient(NODE_URL, FAUCET_URL);

/** Publish a new module to the blockchain within the specified account */
export async function publishModule(accountFrom: AptosAccount, moduleHex: string): Promise<string> {
  const moduleBundlePayload = new TxnBuilderTypes.TransactionPayloadModuleBundle(
    new TxnBuilderTypes.ModuleBundle([new TxnBuilderTypes.Module(new HexString(moduleHex).toUint8Array())]),
  );

  const [{ sequence_number: sequenceNumber }, chainId] = await Promise.all([
    client.getAccount(accountFrom.address()),
    client.getChainId(),
  ]);

  const rawTxn = new TxnBuilderTypes.RawTransaction(
    TxnBuilderTypes.AccountAddress.fromHex(accountFrom.address()),
    BigInt(sequenceNumber),
    moduleBundlePayload,
    1000n,
    1n,
    BigInt(Math.floor(Date.now() / 1000) + 10),
    new TxnBuilderTypes.ChainId(chainId),
  );

  const bcsTxn = AptosClient.generateBCSTransaction(accountFrom, rawTxn);
  const transactionRes = await client.submitSignedBCSTransaction(bcsTxn);

  return transactionRes.hash;
}
Enter fullscreen mode Exit fullscreen mode

СОВЕТ
Для инициализации модуля можно написать функцию init_module. Эта приватная функция выполняется автоматически при публикации модуля. Эта функция init_module должна быть приватной, принимать в качестве параметра только signer или ссылку на signer и не возвращать никакого значения. Вот пример:

 fun init_module(creator: &signer) {
        move_to(
            creator,
            ModuleData { global_counter: 0 }
        );
    }

Шаг 2.2 Чтение ресурса

Модуль публикуется по адресу. Ниже приведен адрес contract_address. Это похоже на предыдущий пример, где Coin находится по адресу 0x1. Адрес contract_address будет таким же, как и у учетной записи, которая его публикует.

/** Retrieve the resource Message::MessageHolder::message */
async function getMessage(contractAddress: HexString, accountAddress: MaybeHexString): Promise<string> {
  try {
    const resource = await client.getAccountResource(
      accountAddress,
      `${contractAddress.toString()}::message::MessageHolder`,
    );
    return (resource as any).data["message"];
  } catch (_) {
    return "";
  }
}
Enter fullscreen mode Exit fullscreen mode

Шаг 2.3 Изменение ресурса

Модули Move должны раскрывать функции script для инициализации и управления ресурсами. Затем script может быть вызван из транзакции.

Примечание: хотя интерфейс REST может отображать строки, из-за ограничений JSON и Move он не может определить, является ли аргумент строкой или строкой в шестнадцатеричном коде. Поэтому аргументы транзакции всегда предполагают последнее. Следовательно, в данном примере сообщение закодировано как шестнадцатеричная строка.

/**  Potentially initialize and set the resource Message::MessageHolder::message */
async function setMessage(contractAddress: HexString, accountFrom: AptosAccount, message: string): Promise<string> {
  const entryFunctionPayload = new TxnBuilderTypes.TransactionPayloadEntryFunction(
    TxnBuilderTypes.EntryFunction.natural(
      `${contractAddress.toString()}::message`,
      "set_message",
      [],
      [BCS.bcsSerializeStr(message)],
    ),
  );

  const [{ sequence_number: sequenceNumber }, chainId] = await Promise.all([
    client.getAccount(accountFrom.address()),
    client.getChainId(),
  ]);

  const rawTxn = new TxnBuilderTypes.RawTransaction(
    TxnBuilderTypes.AccountAddress.fromHex(accountFrom.address()),
    BigInt(sequenceNumber),
    entryFunctionPayload,
    1000n,
    1n,
    BigInt(Math.floor(Date.now() / 1000) + 10),
    new TxnBuilderTypes.ChainId(chainId),
  );

  const bcsTxn = AptosClient.generateBCSTransaction(accountFrom, rawTxn);
  const transactionRes = await client.submitSignedBCSTransaction(bcsTxn);

  return transactionRes.hash;
}
Enter fullscreen mode Exit fullscreen mode

Шаг 3. Инициализация и взаимодействие с модулем Move

Для Typescript:

  • Загрузите пример проекта
  • Откройте ваш любимый терминал и перейдите туда, где вы скачали вышеупомянутый пример проекта
  • Установите необходимые библиотеки: yarn install
  • Выполните пример: yarn hello_blockchain Message.mv
  • Через несколько мгновений появится сообщение: "Обновить модуль с адресом Alice, собрать, скопировать в указанный путь и нажать enter."
  • В терминале "Окно Move" и для файла Move, который мы рассматривали ранее:

  • Скопировать адрес Alice.

  • Скомпилируйте модули с адресом Alice командой aptos move compile --package-dir . --named-addresses hello_blockchain=0x{alice_address_here}. Здесь мы заменяем общий именованный адрес hello_blockchain='_' в hello_blockchain/move.toml на адрес Alice

  • Скопируйте build/Examples/bytecode_modules/Message.mv в ту же папку, что и код данного руководства проекта.

  • Вернитесь в другое окно терминала и нажмите "enter" в подсказке, чтобы продолжить выполнение остальной части кода

Вывод должен выглядеть следующим образом:

=== Addresses ===
Alice: 11c32982d04fbcc79b694647edff88c5b5d5b1a99c9d2854039175facbeefb40
Bob: 7ec8f962139943bc41c17a72e782b7729b1625cf65ed7812152a5677364a4f88

=== Initial Balances ===
Alice: 10000000
Bob: 10000000

Update the module with Alice's address, build, copy to the provided path, and press enter.

=== Testing Alice ===
Publishing...
Initial value: None
Setting the message to "Hello, Blockchain"
New value: Hello, Blockchain

=== Testing Bob ===
Initial value: None
Setting the message to "Hello, Blockchain"
New value: Hello, Blockchain

Enter fullscreen mode Exit fullscreen mode

Результат показывает, что Alice и Bob прошли путь от отсутствия ресурса до ресурса с message "Hello, Blockchain".

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

  • Учетная запись Alice's через интерфейс Aptos REST.
  • Учетная запись Bob's через Aptos Explorer.

Heroku

Simplify your DevOps and maximize your time.

Since 2007, Heroku has been the go-to platform for developers as it monitors uptime, performance, and infrastructure concerns, allowing you to focus on writing code.

Learn More

Top comments (0)

The Most Contextual AI Development Assistant

Pieces.app image

Our centralized storage agent works on-device, unifying various developer tools to proactively capture and enrich useful materials, streamline collaboration, and solve complex problems through a contextual understanding of your unique workflow.

👥 Ideal for solo developers, teams, and cross-company projects

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay