Skip to content

Commit

Permalink
Test and edit Your First NFT tutorial (aptos-labs#5097)
Browse files Browse the repository at this point in the history
* Update your-first-nft.md

* Replace Python output with TypeScript output

* Continue edits, fix links to SDKs

* Create your-first-nft.md

* Add Rust examples

* Update your-first-nft.md

* Finish including transfer-coin.rs

* Finish edits to First NFT tutorial

* Fix last var link

* Add resource account

* Add resource account Move example to First NFT tutorial
  • Loading branch information
clay-aptos authored Oct 26, 2022
1 parent 60b8814 commit 4df7d72
Showing 1 changed file with 64 additions and 52 deletions.
116 changes: 64 additions & 52 deletions developer-docs-site/docs/tutorials/your-first-nft.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,17 @@ import useBaseUrl from '@docusaurus/useBaseUrl';

This tutorial describes how to create and transfer NFTs on the Aptos blockchain. The Aptos implementation for core NFTs can be found in the [token.move](https://github.com/aptos-labs/aptos-core/blob/main/aptos-move/framework/aptos-token/sources/token.move) Move module.

For reference, also see:
* [mint_nft](https://github.com/aptos-labs/aptos-core/tree/main/aptos-move/move-examples/mint_nft) Move example
* [mint_nft.rs](https://github.com/aptos-labs/aptos-core/blob/main/aptos-move/e2e-move-tests/src/tests/mint_nft.rs) Rust end-to-end test

## Step 1: Pick an SDK

Install your preferred SDK from the below list:

* [Typescript SDK][typescript-sdk]
* [Python SDK][python-sdk]
* [Rust SDK][rust-sdk]
* [TypeScript SDK](../sdks/ts-sdk/index.md)
* [Python SDK](../sdks/python-sdk.md)
* [Rust SDK](../sdks/rust-sdk.md)

---

Expand Down Expand Up @@ -81,12 +85,12 @@ The following output should appear after executing the `simple-nft` example, tho

```yaml
=== Addresses ===
Alice: 0x9df0f527f3a0b445e4d5c320cfa269cdefafc7cd1ed17ffce4b3fd485b17aafb
Bob: 0xfcc74af84dde26b0050dce35d6b3d11c60f5c8c58728ca3a0b11035942a0b1de
Alice: 0xeef95e86c160fa10a71675c6075f44f8f2c6125f57b4b589424f1fbee385f754
Bob: 0x4dcd7b180c123fdb989d10f71fba6c978bda268c2e3660c169bdb55f67aab776

=== Initial Coin Balances ===
Alice: 20000
Bob: 20000
Alice: 100000000
Bob: 100000000

=== Creating Collection and Token ===
Alice's collection: {
Expand All @@ -99,7 +103,7 @@ Alice's collection: {
},
"name": "Alice's",
"supply": "1",
"uri": "https://aptos.dev"
"uri": "https://alice.com"
}
Alice's token balance: 1
Alice's token data: {
Expand All @@ -110,7 +114,7 @@ Alice's token data: {
},
"description": "Alice's simple token",
"largest_property_version": "0",
"maximum": "1",
"maximum": "18446744073709551615",
"mutability_config": {
"description": false,
"maximum": false,
Expand All @@ -120,8 +124,8 @@ Alice's token data: {
},
"name": "Alice's first token",
"royalty": {
"payee_address": "0x9df0f527f3a0b445e4d5c320cfa269cdefafc7cd1ed17ffce4b3fd485b17aafb",
"royalty_points_denominator": "1000000",
"payee_address": "0xeef95e86c160fa10a71675c6075f44f8f2c6125f57b4b589424f1fbee385f754",
"royalty_points_denominator": "0",
"royalty_points_numerator": "0"
},
"supply": "1",
Expand Down Expand Up @@ -173,9 +177,9 @@ Coming soon.

### Step 4.1: Initializing the clients

In the first step the example initializes both the API and faucet clients.
In the first step, the example initializes both the API and faucet clients.

- The API client interacts with the REST API, and
- The API client interacts with the REST API.
- The faucet client interacts with the devnet Faucet service for creating and funding accounts.

<Tabs groupId="sdk-examples">
Expand All @@ -185,7 +189,7 @@ In the first step the example initializes both the API and faucet clients.
:!: static/sdks/typescript/examples/typescript/simple_nft.ts section_1a
```

Using the API client we can create a `TokenClient`, which we use for common token operations such as creating collections and tokens, transferring them, claiming them, and so on.
Using the API client we can create a `TokenClient` that we use for common token operations such as creating collections and tokens, transferring them, claiming them, and so on.
```ts
:!: static/sdks/typescript/examples/typescript/simple_nft.ts section_1b
```
Expand All @@ -209,14 +213,27 @@ Using the API client we can create a `TokenClient`, which we use for common toke
</TabItem>
<TabItem value="rust" label="Rust">

Coming soon.

```rust
:!: static/sdks/rust/examples/transfer-coin.rs section_1a
```

Using the API client we can create a `CoinClient` that we use for common coin operations such as transferring coins and checking balances.
```rust
:!: static/sdks/rust/examples/transfer-coin.rs section_1b
```

In the example we initialize the URL values as such:
```rust
:!: static/sdks/rust/examples/transfer-coin.rs section_1c
```
</TabItem>
</Tabs>


:::tip

By default the URLs for both the services point to Aptos devnet services. However, they can be configured with the following environment variables:
By default, the URLs for both the services point to Aptos devnet services. However, they can be configured with the following environment variables:
- `APTOS_NODE_URL`
- `APTOS_FAUCET_URL`
:::
Expand All @@ -225,7 +242,7 @@ By default the URLs for both the services point to Aptos devnet services. Howeve

### Step 4.2: Creating local accounts

The next step is to create two accounts locally. [Accounts][account_basics] represent both on and off-chain state. Off-chain state consists of an address and the public, private key pair used to authenticate ownership. This step demonstrates how to generate that off-chain state.
The next step is to create two accounts locally. [Accounts](../concepts/basics-accounts.md) represent both on and off-chain state. Off-chain state consists of an address and the public/private key pair used to authenticate ownership. This step demonstrates how to generate that off-chain state.

<Tabs groupId="sdk-examples">
<TabItem value="typescript" label="Typescript">
Expand All @@ -242,15 +259,18 @@ The next step is to create two accounts locally. [Accounts][account_basics] repr
</TabItem>
<TabItem value="rust" label="Rust">

Coming soon.

```rust
:!: static/sdks/rust/examples/transfer-coin.rs section_2
```
</TabItem>
</Tabs>

---

### Step 4.3: Creating blockchain accounts

In Aptos, each account must have an on-chain representation in order to support receive tokens and coins as well as interacting in other dApps. An account represents a medium for storing assets, hence it must be explicitly created. This example leverages the Faucet to create Alice and Bob's accounts:
In Aptos, each account must have an on-chain representation in order to receive tokens and coins and interact with other dApps. An account represents a medium for storing assets; hence, it must be explicitly created. This example leverages the Faucet to create Alice and Bob's accounts:

<Tabs groupId="sdk-examples">
<TabItem value="typescript" label="Typescript">
Expand All @@ -266,14 +286,23 @@ In Aptos, each account must have an on-chain representation in order to support
```
</TabItem>
<TabItem value="rust" label="Rust">

Since the Rust example here uses the same `transfer-coin.rs` function as in the [Your First Transaction](first-transaction.md) tutorial, it creates but does not fund Bob's account.

Coming soon.
```rust
:!: static/sdks/rust/examples/transfer-coin.rs section_3
```
</TabItem>
</Tabs>

---

### Step 4.4: Creating a collection
### Step 4.4: Creating a resource account

Create a [resource account](../reference/glossary.md#resource-account) to [initialize](https://github.com/aptos-labs/aptos-core/tree/main/aptos-move/move-examples/resource_account) the `mint_nft` module and retrieve the signer capability from both the resource account and module account. To do so, call `create_resource_account_and_publish_package` to publish the module under the resource account's address and make this example code work. For an example, see: [mint_nft.rs](https://github.com/aptos-labs/aptos-core/blob/main/aptos-move/e2e-move-tests/src/tests/mint_nft.rs#L62).


### Step 4.5: Creating a collection

Now begins the process of creating tokens. First, the creator must create a collection to store tokens. A collection can contain zero, one, or many distinct tokens within it. The collection does not restrict the attributes of the tokens, as it is only a container.

Expand All @@ -285,7 +314,7 @@ Your application will call `createCollection`:
:!: static/sdks/typescript/examples/typescript/simple_nft.ts section_4
```

The function signature of `createCollection`. It returns a transaction hash:
The is the function signature of `createCollection`. It returns a transaction hash:
```ts
:!: static/sdks/typescript/src/token_client.ts createCollection
```
Expand All @@ -297,7 +326,7 @@ Your application will call `create_collection`:
:!: static/sdks/python/examples/simple-nft.py section_4
```

The function signature of `create_collection`. It returns a transaction hash:
The is the function signature of `create_collection`. It returns a transaction hash:
```python
:!: static/sdks/python/aptos_sdk/client.py create_collection
```
Expand All @@ -312,7 +341,7 @@ Coming soon.

### Step 4.5: Creating a token

To create a token, the creator must specify an associated collection. A token must be associated with a collection and that collection must have remaining tokens that can be minted. There are many attributes associated with a token, but the helper API only exposes the minimal amount required to create static content.
To create a token, the creator must specify an associated collection. A token must be associated with a collection, and that collection must have remaining tokens that can be minted. There are many attributes associated with a token, but the helper API exposes only the minimal amount required to create static content.

<Tabs groupId="sdk-examples">
<TabItem value="typescript" label="Typescript">
Expand All @@ -322,7 +351,7 @@ Your application will call `createToken`:
:!: static/sdks/typescript/examples/typescript/simple_nft.ts section_5
```

The function signature of `createToken`. It returns a transaction hash:
The is the function signature of `createToken`. It returns a transaction hash:
```ts
:!: static/sdks/typescript/src/token_client.ts createToken
```
Expand All @@ -334,7 +363,7 @@ Your application will call `create_token`:
:!: static/sdks/python/examples/simple-nft.py section_5
```

The function signature of `create_token`. It returns a transaction hash:
The is the function signature of `create_token`. It returns a transaction hash:
```python
:!: static/sdks/python/aptos_sdk/client.py create_token
```
Expand Down Expand Up @@ -398,7 +427,7 @@ Coming soon.

### Step 4.7: Reading a token balance

Each token within Aptos is a distinct asset, the assets owned by the user are stored within their `TokenStore`. To get the balance:
Each token within Aptos is a distinct asset. The assets owned by the user are stored within their `TokenStore`. To get the balance:

<Tabs groupId="sdk-examples">
<TabItem value="typescript" label="Typescript">
Expand All @@ -423,7 +452,7 @@ Coming soon.

### Step 4.8: Offering and claiming a token

Many users have received unwanted tokens that may cause minimally embarrassment to serious ramifications. Aptos gives the rights to each owner of an account to dictate whether or not to receive unilateral transfers. By default, unilateral transfers are unsupported. So Aptos provides a framework for *offering* and *claiming* tokens.
Many users of other blockchains have received unwanted tokens that may cause anything from minimal embarrassment to serious ramifications. Aptos gives the rights to each account owner to dictate whether or not to receive unilateral transfers. By default, unilateral transfers are unsupported. So Aptos provides a framework for *offering* and *claiming* tokens.

To offer a token:

Expand Down Expand Up @@ -471,7 +500,7 @@ Coming soon.

### Step 4.9: Safe unilateral transferring of a token

To support safe unilateral transfers of a token, the sender may first ask the recipient to acknowledge off-chain about a pending transfer. This comes in the form of a multiagent transaction request. Multiagent transactions contain multiple signatures, one for each on-chain account. Move then can leverage this to give `signer` level permissions to all that signed. For token transfers, this ensures that the receiving party does indeed desire to receive this token without requiring the use of the token transfer framework described above.
To support safe unilateral transfers of a token, the sender may first ask the recipient to acknowledge off-chain a pending transfer. This comes in the form of a multiagent transaction request. Multiagent transactions contain multiple signatures, one for each on-chain account. Move then can leverage this to give `signer`-level permissions to all who signed the transaction. For token transfers, this process ensures the receiving party does indeed want to receive this token without requiring the use of the token transfer framework described above.

<Tabs groupId="sdk-examples">
<TabItem value="typescript" label="Typescript">
Expand All @@ -494,27 +523,10 @@ Coming soon.

---

### Step 4.10: Enabling unilateral token transfers

Coming soon.

<Tabs groupId="sdk-examples">
<TabItem value="python" label="Python">

Coming soon.
</TabItem>
<TabItem value="rust" label="Rust">

Coming soon.
</TabItem>
<TabItem value="typescript" label="Typescript">

Coming soon.
</TabItem>
</Tabs>
## Supporting documentation

[account_basics]: /concepts/basics-accounts
[typescript-sdk]: /sdks/ts-sdk/index
[python-sdk]: /sdks/python-sdk
[rust-sdk]: /sdks/rust-sdk
[rest_spec]: https://fullnode.devnet.aptoslabs.com/v1/spec#/
* [Account basics](../concepts/basics-accounts.md)
* [TypeScript SDK](../sdks/ts-sdk/index.md)
* [Python SDK](../sdks/python-sdk.md)
* [Rust SDK](../sdks/rust-sdk.md)
* [REST API specification](https://fullnode.devnet.aptoslabs.com/v1/spec#/)

0 comments on commit 4df7d72

Please sign in to comment.