Руководство для разработчиков APTOS |Ваша первая транзакция с использованием SDK | Python
Tags: blockchain, tutorial, aptos, developer
Published: 2022-08-23 19:34:00

Это руководство знакомит с Aptos SDK и с тем, как генерировать, отправлять и проверять транзакции, отправленные в блокчейн Aptos.

## Шаг 1. Aptos Python SDK

У Aptos есть официальный, слегка поддерживаемый Python SDK. Он доступен на [PyPi](https://aptos.dev/sdks/python-sdk#:~:text=is%20available%20on-,PyPi,-with%20the%20source) с исходным кодом в [репозитории Aptos-core на github](https://aptos.dev/sdks/python-sdk#:~:text=Aptos%2Dcore%20github%20repository). Большая часть функциональности повторяет наш [SDK Typescript](https://aptos.dev/sdks/python-sdk#:~:text=functionality%20mirrors%20our-,Typescript%20SDK,-.%20The%20primary%20purpose). Основная цель этого SDK - помочь разработчикам Python быстро освоиться в Aptos и стать дополнением к нашему руководству.

Python SDK может быть установлен через `pip`, из исходников или встроен:

Для установки через `pip`:

```javascript 
pip3 install aptos-sdk
```
Для установки из исходного кода:

```javascript
git clone https://github.com/aptos-labs/aptos-core
cd aptos-core/ecosystem/python/sdk
python3 setup.py install
```
Для встраивания:

```javascript
cd /path/to/python/project
cp -r /path/to/aptos-core/ecosystem/python/sdk/aptos-sdk aptos-sdk
```

## Шаг 2. Выполните пример
Каждый SDK содержит каталог примеров. В данном руководстве рассматривается пример `transfer-coin`.

В каталоге SDK запустите: `python -m examples.transfer-coin`

## Шаг 3. Результат

После выполнения примера `transfer-coin` должен появиться следующий результат, хотя некоторые значения будут отличаться:

```
=== Addresses ===
Alice: 0x0baec07bfc42f8018ea304ddc307a359c1c6ab20fbce598065b6cb19acff7043
Bob: 0xc98ceafadaa32e50d06d181842406dbbf518b6586ab67cfa2b736aaddeb7c74f

=== Initial Balances ===
Alice: 20000
Bob: 0

=== Intermediate Balances ===
Alice: 18996
Bob: 1000

=== Final Balances ===
Alice: 17992
Bob: 2000
```

В данном примере показано:

- Инициализация клиентов REST и Faucet
- Создание двух учетных записей: Alice и Bob
- Финансирование и создание учетной записи Alice из faucet
- Создание учетной записи Bob из faucet
- Перевод 1000 монет от Alice к Bob
- 4 монеты за газ, оплаченные Alice для осуществления этого перевода
- Еще один перевод 1000 монет от Alice к Bob
- Дополнительные 4 монеты за газ, оплаченные Alice для осуществления этого перевода

## Шаг 4. SDK в деталях

В файле примера используются вспомогательные функции для взаимодействия с [REST API](https://fullnode.devnet.aptoslabs.com/v1/spec#/). В этом разделе рассматривается каждый из вызовов и дается представление о функциональности.

**Шаг 4.1. Инициализация клиентов**

На первом этапе в примере инициализируются клиенты REST и Faucet. Клиент REST взаимодействует с API REST, тогда как клиент Faucet взаимодействует с сервисом devnet Faucet для создания и пополнения учетных записей.

```javascript
rest_client = RestClient(NODE_URL)
faucet_client = FaucetClient(FAUCET_URL, rest_client)
```
`common.py` инициализирует эти значения таким образом:

```javascript
NODE_URL = os.getenv("APTOS_NODE_URL", "https://fullnode.devnet.aptoslabs.com/v1")
FAUCET_URL = os.getenv("APTOS_FAUCET_URL", "https://faucet.devnet.aptoslabs.com")
```

> **СОВЕТ**
> URL-адреса обеих сервисов по умолчанию указывают на наши сервисы devnet. Однако их можно настроить с помощью следующих переменных: `APTOS_NODE_URL` и `APTOS_FAUCET_URL`.

**Шаг 4.2. Создание локальных учетных записей**

Следующим шагом будет создание двух учетных записей на локальном уровне. [Учетные записи](https://aptos.dev/tutorials/your-first-transaction-sdk#step-3-understand-the-output:~:text=from%20the%20locally.-,Accounts,-represent%20both%20on) представляют собой состояние в сети и вне сети. Состояние вне сети состоит из адреса и пары открытого и закрытого ключей, используемых для аутентификации владельца. Этот шаг демонстрирует, как генерировать состояние вне сети.

```javascript
alice = Account.generate()
bob = Account.generate()
```

**Шаг 4.3: Создание учетных записей в блокчейне**

В Aptos каждая учетная запись должна иметь представление на сети, чтобы поддерживать получение токенов и Coins , а также взаимодействие с другими dApps. Учетная запись представляет собой носитель для хранения активов, поэтому она должна быть явно создана. В данном примере используется Faucet для создания и пополнения учетной записи Alice и только для создания учетной записи Bob:

```javascript
faucet_client.fund_account(alice.address(), 20_000)
faucet_client.fund_account(bob.address(), 0)
```
**Шаг 4.4. Чтение балансов**

На этом этапе SDK преобразует один вызов в процесс запроса ресурса и чтения поля из этого ресурса.

```javascript
print(f"Alice: {rest_client.account_balance(alice.address())}")
print(f"Bob: {rest_client.account_balance(bob.address())}")
```
За кулисами SDK запрашивает ресурс CoinStore для AptosCoin и считывает текущее сохраненное значение:

```javascript
def account_balance(self, account_address: str) -> int:
    """Returns the test coin balance associated with the account"""
    return self.account_resource(
        account_address, "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>"
    )["data"]["coin"]["value"]
```

**Шаг 4.5. Перевод**

Как и предыдущий шаг, это еще один вспомогательный шаг, который создает транзакцию, переводящую Coins от Alice к Bob. Для правильно созданных транзакций API возвращает хэш транзакции, который может быть использован в последующих шагах для проверки статуса транзакции. Aptos выполняет несколько проверок при отправке, и если какая-либо из них не проходит, пользователю выдается сообщение об ошибке. Эти проверки включают подпись транзакции, неиспользованный порядковый номер и отправку транзакции в соответствующую сеть.

```javascript
txn_hash = rest_client.transfer(alice, bob.address(), 1_000)
```
За кулисами SDK генерирует, подписывает и отправляет транзакцию:

```javascript
def bcs_transfer(
    self, sender: Account, recipient: AccountAddress, amount: int
) -> str:
    transaction_arguments = [
        TransactionArgument(recipient, Serializer.struct),
        TransactionArgument(amount, Serializer.u64),
    ]

    payload = EntryFunction.natural(
        "0x1::coin",
        "transfer",
        [TypeTag(StructTag.from_str("0x1::aptos_coin::AptosCoin"))],
        transaction_arguments,
    )

    signed_transaction = self.create_single_signer_bcs_transaction(
        sender, TransactionPayload(payload)
    )
    return self.submit_bcs_transaction(signed_transaction)
```

Разбиваем вышесказанное по пунктам:

1. `transfer` внутри является `EntryFunction` или функцией 
   входа в Move, которую можно вызвать напрямую.
2. Функция Move хранится в модуле coin: `0x1::coin`.
3. Поскольку модуль Coin может использоваться другими Coin, 
   трансфер должен явно использовать `TypeTag`, чтобы 
   определить, какой именно coin передавать.
4. Аргументы транзакции должны быть помещены в 
   `TransactionArguments` со спецификаторами типа 
   `(Serializer. {type})`, которые будут последовательно 
    преобразовывать значение в соответствующий тип во время 
    генерации транзакции.

**Шаг 4.6. Ожидание разрешения транзакции**

Хэш транзакции можно использовать для запроса статуса транзакции:

```javascript
rest_client.wait_for_transaction(txn_hash)
```