Руководство для разработчиков APTOS | Ваш первый NFT с использованием SDK | Python
Tags: blockchain, aptos, developer, tutorial
Published: 2022-08-23 20:06:03

В этом руководстве пошагово описано, как создавать и передавать NFT на блокчейне Aptos. Реализацию Aptos для основных NFT или токенов можно найти в файле [token.move](https://github.com/aptos-labs/aptos-core/blob/main/aptos-move/framework/aptos-token/sources/token.move).

## Шаг 1. Aptos Python SDK

У Aptos есть официальный, слегка поддерживаемый Python SDK. Он доступен на [PyPi](https://dev.to/egormajj/rukovodstvo-dlia-razrabotchikov-aptos-vasha-piervaia-tranzaktsiia-s-ispolzovaniiem-sdk-python-4l1i#:~:text=%D0%9E%D0%BD%20%D0%B4%D0%BE%D1%81%D1%82%D1%83%D0%BF%D0%B5%D0%BD%20%D0%BD%D0%B0-,PyPi,-%D1%81%20%D0%B8%D1%81%D1%85%D0%BE%D0%B4%D0%BD%D1%8B%D0%BC%20%D0%BA%D0%BE%D0%B4%D0%BE%D0%BC) с исходным кодом в [репозитории Aptos-core на github](https://dev.to/egormajj/rukovodstvo-dlia-razrabotchikov-aptos-vasha-piervaia-tranzaktsiia-s-ispolzovaniiem-sdk-python-4l1i#:~:text=%D1%80%D0%B5%D0%BF%D0%BE%D0%B7%D0%B8%D1%82%D0%BE%D1%80%D0%B8%D0%B8%20Aptos%2Dcore%20%D0%BD%D0%B0%20github). Большая часть функциональности повторяет наш [SDK Typescript](https://dev.to/egormajj/rukovodstvo-dlia-razrabotchikov-aptos-vasha-piervaia-tranzaktsiia-s-ispolzovaniiem-sdk-python-4l1i#:~:text=%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8%20%D0%BF%D0%BE%D0%B2%D1%82%D0%BE%D1%80%D1%8F%D0%B5%D1%82%20%D0%BD%D0%B0%D1%88-,SDK%20Typescript,-.%20%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D0%BD%D0%B0%D1%8F%20%D1%86%D0%B5%D0%BB%D1%8C%20%D1%8D%D1%82%D0%BE%D0%B3%D0%BE). Основная цель этого 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 содержит каталог примеров. В данном руководстве рассматривается пример `simple-nft`.

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

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

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

```
=== Addresses ===
Alice: 0x9df0f527f3a0b445e4d5c320cfa269cdefafc7cd1ed17ffce4b3fd485b17aafb
Bob: 0xfcc74af84dde26b0050dce35d6b3d11c60f5c8c58728ca3a0b11035942a0b1de

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

=== Creating Collection and Token ===
Alice's collection: {
    "description": "Alice's simple collection",
    "maximum": "18446744073709551615",
    "mutability_config": {
        "description": false,
        "maximum": false,
        "uri": false
    },
    "name": "Alice's",
    "supply": "1",
    "uri": "https://aptos.dev"
}
Alice's token balance: 1
Alice's token data: {
    "default_properties": {
        "map": {
            "data": []
        }
    },
    "description": "Alice's simple token",
    "largest_property_version": "0",
    "maximum": "1",
    "mutability_config": {
        "description": false,
        "maximum": false,
        "properties": false,
        "royalty": false,
        "uri": false
    },
    "name": "Alice's first token",
    "royalty": {
        "payee_address": "0x9df0f527f3a0b445e4d5c320cfa269cdefafc7cd1ed17ffce4b3fd485b17aafb",
        "royalty_points_denominator": "1000000",
        "royalty_points_numerator": "0"
    },
    "supply": "1",
    "uri": "https://aptos.dev/img/nyan.jpeg"
}

=== Transferring the token to Bob ===
Alice's token balance: 0
Bob's token balance: 1

=== Transferring the token back to Alice using MultiAgent ===
Alice's token balance: 1
Bob's token balance: 0
```
В данном примере показано:

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

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

**Шаг 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-nft-sdk#:~: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(), 20_000)
```
**Шаг 4.4. Создание коллекции**

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

Ваше приложение будет вызывать `create_collection`:

```javascript
txn_hash = rest_client.create_collection(
    alice, collection_name, "Alice's simple collection", "https://aptos.dev"
)
```
API `create_collection`, который возвращает хэш транзакции:

```javascript
def create_collection(
    self, account: Account, name: str, description: str, uri: str
) -> str:
```
**Шаг 4.5. Создание токена**

Чтобы создать токен, создатель должен указать связанную с ним коллекцию. Токен должен быть связан с коллекцией, и в этой коллекции должны быть оставшиеся токены, которые можно минтить. Существует множество атрибутов, связанных с токеном, но API-помощник раскрывает только минимальное количество, необходимое для создания статического контента.

Ваше приложение будет вызывать `create_token`:

```javascript
txn_hash = rest_client.create_token(
    alice,
    collection_name,
    token_name,
    "Alice's simple token",
    1,
    "https://aptos.dev/img/nyan.jpeg",
    0,
)
```
API `create_token`, который возвращает хэш транзакции:

```javascript
def create_token(
    self,
    account: Account,
    collection_name: str,
    name: str,
    description: str,
    supply: int,
    uri: str,
    royalty_points_per_million: int,
) -> str:
```
**Шаг 4.6. Чтение метаданных токена и коллекции**

Метаданные коллекции и токена хранятся на учетной записи создателя в таблице `Collections`. SDK предоставляют удобные оболочки для запросов к этим конкретным областям:

Чтобы прочитать метаданные коллекции:

```javascript
collection_data = rest_client.get_collection(alice.address(), collection_name)
print(f"Alice's collection: {json.dumps(collection_data, indent=4, sort_keys=True)}")
```
Чтобы прочитать метаданные токена:

```javascript
token_data = rest_client.get_token_data(alice.address(), collection_name, token_name, 0)
print(f"Alice's token data: {json.dumps(token_data, indent=4, sort_keys=True)}")
```
Вот как `get_token_data` запрашивает метаданные токена:

```javascript
def get_token_data(
    self,
    creator: AccountAddress,
    collection_name: str,
    token_name: str,
    property_version: int,
) -> Any:
    token_data = self.account_resource(creator, "0x3::token::Collections")["data"][
        "token_data"
    ]["handle"]

    token_data_id = {
        "creator": creator.hex(),
        "collection": collection_name,
        "name": token_name,
    }

    return self.get_table_item(
        token_data,
        "0x3::token::TokenDataId",
        "0x3::token::TokenData",
        token_data_id,
    )
```

**Шаг 4.7. Чтение баланса токена**

Каждый токен в Aptos является отдельным активом, активы, принадлежащие пользователю, хранятся в его TokenStore. Чтобы узнать баланс:

```javascript
balance = rest_client.get_token_balance(alice.address(), alice.address(), collection_name, token_name, 0)
print(f"Alice's token balance: {balance}")
```
**Шаг 4.8. Предложение и заявление прав на токен**

Многие пользователи получили нежелательные токены, которые могут вызвать как минимальный дискомфорт, так и серьезные последствия. Aptos предоставляет каждому владельцу учетной записи право решать, принимать или не принимать односторонние переводы. По умолчанию односторонние переводы не поддерживаются. Таким образом, Aptos обеспечивает основу для предложения и заявления прав на токен.

Чтобы предложить токен:

```javascript
txn_hash = rest_client.offer_token(
    alice,
    bob.address(),
    alice.address(),
    collection_name,
    token_name,
    0,
    1,
)
```
Чтобы заявить права на токен:

```javascript
txn_hash = rest_client.claim_token(
    bob,
    alice.address(),
    alice.address(),
    collection_name,
    token_name,
    0,
)
```
**Шаг 4.9. Безопасный односторонний перевод токена**

Для поддержки безопасной односторонней передачи токена отправитель может сначала попросить получателя подтвердить вне сети о предстоящей передаче. Это происходит в форме запроса мультиагентной транзакции. Мультиагентные транзакции содержат несколько подписей, по одной для каждой учетной записи на сети. Move затем может использовать это для предоставления разрешений на уровне подписи всем `signer`. Для передачи токенов это гарантирует, что принимающая сторона действительно желает получить этот токен, не требуя использования описанной выше структуры передачи токенов.

```javascript
txn_hash = rest_client.direct_transfer_token(
    bob, alice, alice.address(), collection_name, token_name, 0, 1
)
```