forked from aptos-labs/aptos-core
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make Rust first-transaction example in dev docs site use the Rust SDK (…
…aptos-labs#2870) * Update first transaction tutorial with TS SDK * Make Rust first-transaction example in dev docs site use the Rust SDK
- Loading branch information
Showing
9 changed files
with
380 additions
and
15 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
--- | ||
title: "Rust SDK" | ||
slug: "rust-sdk" | ||
--- | ||
|
||
# Aptos Rust SDK | ||
|
||
Aptos provides an official Rust SDK. The Rust SDK is tested carefully, though it isn't as popular as the [Typescript SDK](/sdks/typescript-sdk). | ||
|
||
For now the best way to use the Rust SDK is to add a dependency on the git repo directly, like this: | ||
```toml | ||
aptos-sdk = { git = "https://github.com/aptos-labs/aptos-core", branch = "devnet" } | ||
``` | ||
|
||
The source code is available in the [aptos-core GitHub repository](https://github.com/aptos-labs/aptos-core/tree/main/sdk). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,7 +15,7 @@ This tutorial introduces the Aptos SDKs and how to generate, submit, and verify | |
|
||
* [Official Aptos Typescript SDK][typescript-sdk] | ||
* [Official Aptos Python SDK][python-sdk] | ||
* Official Aptos Rust SDK — *TBA* | ||
* [Official Aptos Rust SDK][rust-sdk] | ||
|
||
## Step 2: Run the Example | ||
|
||
|
@@ -63,7 +63,15 @@ git clone [email protected]:aptos-labs/aptos-core.git ~/aptos-core | |
</TabItem> | ||
<TabItem value="rust" label="Rust"> | ||
|
||
In progress. | ||
Navigate to the Rust SDK directory: | ||
```sh | ||
cd ~/aptos-core/sdk | ||
``` | ||
|
||
Run the `transfer-coin` example: | ||
```sh | ||
cargo run --example transfer-coin | ||
``` | ||
</TabItem> | ||
</Tabs> | ||
|
||
|
@@ -96,7 +104,7 @@ The above output demonstrates that the `transfer-coin` example executes the foll | |
* The funding and creation of Alice's account from a faucet. | ||
* The creation of Bob's account from a faucet. | ||
* The transferring of 1000 coins from Alice to Bob. | ||
* The 4 coins of gas paid for by Alice to make that tansfer. | ||
* The 4 coins of gas paid for by Alice to make that transfer. | ||
* Another transfer of 1000 coins from Alice to Bob. | ||
* The additional 4 coins of gas paid for by Alice to make that transfer. | ||
|
||
|
@@ -106,9 +114,26 @@ Next, see below a walk-through of the Python SDK functions that are used to acco | |
|
||
The `transfer-coin` example code uses helper functions to interact with the [REST API][rest_spec]. This section reviews each of the calls and gives insights into functionality. | ||
|
||
:::tip See the example full listing | ||
See the [`transfer-coin`](https://github.com/aptos-labs/aptos-core/blob/main/ecosystem/python/sdk/examples/transfer-coin.py) for the complete code as you follow the below steps. | ||
<Tabs groupId="sdk-examples"> | ||
<TabItem value="typescript" label="Typescript"> | ||
|
||
:::tip See the full example | ||
See [`transfer-coin`](https://github.com/aptos-labs/aptos-core/blob/main/ecosystem/typescript/sdk/examples/typescript/transfer_coin.ts) for the complete code as you follow the below steps. | ||
::: | ||
</TabItem> | ||
<TabItem value="python" label="Python"> | ||
|
||
:::tip See the full example | ||
See [`transfer-coin`](https://github.com/aptos-labs/aptos-core/blob/main/ecosystem/python/sdk/examples/transfer-coin.py) for the complete code as you follow the below steps. | ||
::: | ||
</TabItem> | ||
<TabItem value="rust" label="Rust"> | ||
|
||
:::tip See the full example | ||
See [`transfer-coin`](https://github.com/aptos-labs/aptos-core/blob/main/sdk/examples/transfer-coin.rs) for the complete code as you follow the below steps. | ||
::: | ||
</TabItem> | ||
</Tabs> | ||
|
||
### Step 4.1: Initializing the Clients | ||
|
||
|
@@ -148,15 +173,27 @@ The [`common.py`](https://github.com/aptos-labs/aptos-core/tree/main/ecosystem/p | |
</TabItem> | ||
<TabItem value="rust" label="Rust"> | ||
|
||
In progress. | ||
```rust | ||
:!: static/sdks/rust/examples/transfer-coin.rs section_1a | ||
``` | ||
|
||
Using the API client we can create a `CoinClient`, which 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: | ||
- `APTOS_NODE_URL` and | ||
- `APTOS_FAUCET_URL`. | ||
- `APTOS_NODE_URL` | ||
- `APTOS_FAUCET_URL` | ||
::: | ||
|
||
### Step 4.2: Creating local accounts | ||
|
@@ -178,7 +215,9 @@ The next step is to create two accounts locally. [Accounts][account_basics] repr | |
</TabItem> | ||
<TabItem value="rust" label="Rust"> | ||
|
||
In progress. | ||
```rust | ||
:!: static/sdks/rust/examples/transfer-coin.rs section_2 | ||
``` | ||
</TabItem> | ||
</Tabs> | ||
|
||
|
@@ -201,7 +240,9 @@ In Aptos, each account must have an on-chain representation in order to support | |
</TabItem> | ||
<TabItem value="rust" label="Rust"> | ||
|
||
In progress. | ||
```rust | ||
:!: static/sdks/rust/examples/transfer-coin.rs section_3 | ||
``` | ||
</TabItem> | ||
</Tabs> | ||
|
||
|
@@ -239,7 +280,16 @@ def account_balance(self, account_address: str) -> int: | |
</TabItem> | ||
<TabItem value="rust" label="Rust"> | ||
|
||
In progress. | ||
```rust | ||
:!: static/sdks/rust/examples/transfer-coin.rs section_4 | ||
``` | ||
|
||
Behind the scenes, the SDK queries the CoinStore resource for the AptosCoin and reads the current stored value: | ||
```rust | ||
let balance = self | ||
.get_account_resource(address, "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>") | ||
.await?; | ||
``` | ||
</TabItem> | ||
</Tabs> | ||
|
||
|
@@ -292,7 +342,23 @@ Breaking the above down into pieces: | |
</TabItem> | ||
<TabItem value="rust" label="Rust"> | ||
|
||
In progress. | ||
```rust | ||
:!: static/sdks/rust/examples/transfer-coin.rs section_5 | ||
``` | ||
|
||
Behind the scenes the Rust SDK generates, signs, and submits a transaction: | ||
```rust | ||
:!: static/sdks/rust/src/coin_client.rs section_1 | ||
``` | ||
|
||
Breaking the above down into pieces: | ||
1. First, we fetch the chain ID, necessary for building the transaction payload. | ||
1. `transfer` internally is a `EntryFunction` in the [Coin Move module](https://github.com/aptos-labs/aptos-core/blob/main/aptos-move/framework/aptos-framework/sources/coin.move#L412), i.e. an entry function in Move that is directly callable. | ||
1. The Move function is stored on the coin module: `0x1::coin`. | ||
1. Because the Coin module can be used by other coins, the transfer must explicitly use a `TypeTag` to define which coin to transfer. | ||
1. The transaction arguments, such as `to_account` and `amount`, must be encoded as BCS to use with the `TransactionBuilder`. | ||
|
||
|
||
</TabItem> | ||
</Tabs> | ||
|
||
|
@@ -319,11 +385,16 @@ The transaction hash can be used to query the status of a transaction: | |
</TabItem> | ||
<TabItem value="rust" label="Rust"> | ||
|
||
In progress. | ||
The transaction hash can be used to query the status of a transaction: | ||
|
||
```rust | ||
:!: static/sdks/rust/examples/transfer-coin.rs section_6 | ||
``` | ||
</TabItem> | ||
</Tabs> | ||
|
||
[account_basics]: /concepts/basics-accounts | ||
[python-sdk]: /sdks/python-sdk | ||
[typescript-sdk]: /sdks/typescript-sdk | ||
[python-sdk]: /sdks/python-sdk | ||
[rust-sdk]: /sdks/rust-sdk | ||
[rest_spec]: https://fullnode.devnet.aptoslabs.com/v1/spec#/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
../../../sdk/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
// Copyright (c) Aptos | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
use anyhow::{Context, Result}; | ||
use aptos_sdk::coin_client::CoinClient; | ||
use aptos_sdk::rest_client::{Client, FaucetClient}; | ||
use aptos_sdk::types::LocalAccount; | ||
use once_cell::sync::Lazy; | ||
use std::str::FromStr; | ||
use url::Url; | ||
|
||
// :!:>section_1c | ||
static NODE_URL: Lazy<Url> = Lazy::new(|| { | ||
Url::from_str( | ||
std::env::var("APTOS_NODE_URL") | ||
.as_ref() | ||
.map(|s| s.as_str()) | ||
.unwrap_or("https://fullnode.devnet.aptoslabs.com"), | ||
) | ||
.unwrap() | ||
}); | ||
|
||
static FAUCET_URL: Lazy<Url> = Lazy::new(|| { | ||
Url::from_str( | ||
std::env::var("APTOS_FAUCET_URL") | ||
.as_ref() | ||
.map(|s| s.as_str()) | ||
.unwrap_or("https://faucet.devnet.aptoslabs.com"), | ||
) | ||
.unwrap() | ||
}); | ||
// <:!:section_1c | ||
|
||
#[tokio::main] | ||
async fn main() -> Result<()> { | ||
// :!:>section_1a | ||
let rest_client = Client::new(NODE_URL.clone()); | ||
let faucet_client = FaucetClient::new(FAUCET_URL.clone(), NODE_URL.clone()); // <:!:section_1a | ||
|
||
// :!:>section_1b | ||
let coin_client = CoinClient::new(&rest_client); // <:!:section_1b | ||
|
||
// Create two accounts locally, Alice and Bob. | ||
// :!:>section_2 | ||
let mut alice = LocalAccount::generate(&mut rand::rngs::OsRng); | ||
let bob = LocalAccount::generate(&mut rand::rngs::OsRng); // <:!:section_2 | ||
|
||
// Print account addresses. | ||
println!("\n=== Addresses ==="); | ||
println!("Alice: {}", alice.address().to_hex_literal()); | ||
println!("Bob: {}", bob.address().to_hex_literal()); | ||
|
||
// Create the accounts on chain, but only fund Alice. | ||
// :!:>section_3 | ||
faucet_client | ||
.fund(alice.address(), 20_000) | ||
.await | ||
.context("Failed to fund Alice's account")?; | ||
faucet_client | ||
.create_account(bob.address()) | ||
.await | ||
.context("Failed to fund Bob's account")?; // <:!:section_3 | ||
|
||
// Print initial balances. | ||
println!("\n=== Initial Balances ==="); | ||
println!( | ||
"Alice: {:?}", | ||
coin_client | ||
.get_account_balance(&alice.address()) | ||
.await | ||
.context("Failed to get Alice's account balance")? | ||
); | ||
println!( | ||
"Bob: {:?}", | ||
coin_client | ||
.get_account_balance(&bob.address()) | ||
.await | ||
.context("Failed to get Bob's account balance")? | ||
); | ||
|
||
// Have Alice send Bob some coins. | ||
let txn_hash = coin_client | ||
.transfer(&mut alice, bob.address(), 1_000, None) | ||
.await | ||
.context("Failed to submit transaction to transfer coins")?; | ||
rest_client | ||
.wait_for_transaction(&txn_hash) | ||
.await | ||
.context("Failed when waiting for the transfer transaction")?; | ||
|
||
// Print intermediate balances. | ||
println!("\n=== Intermediate Balances ==="); | ||
// :!:>section_4 | ||
println!( | ||
"Alice: {:?}", | ||
coin_client | ||
.get_account_balance(&alice.address()) | ||
.await | ||
.context("Failed to get Alice's account balance the second time")? | ||
); | ||
println!( | ||
"Bob: {:?}", | ||
coin_client | ||
.get_account_balance(&bob.address()) | ||
.await | ||
.context("Failed to get Bob's account balance the second time")? | ||
); // <:!:section_4 | ||
|
||
// Have Alice send Bob some more coins. | ||
// :!:>section_5 | ||
let txn_hash = coin_client | ||
.transfer(&mut alice, bob.address(), 1_000, None) | ||
.await | ||
.context("Failed to submit transaction to transfer coins")?; // <:!:section_5 | ||
// :!:>section_6 | ||
rest_client | ||
.wait_for_transaction(&txn_hash) | ||
.await | ||
.context("Failed when waiting for the transfer transaction")?; // <:!:section_6 | ||
|
||
// Print final balances. | ||
println!("\n=== Final Balances ==="); | ||
println!( | ||
"Alice: {:?}", | ||
coin_client | ||
.get_account_balance(&alice.address()) | ||
.await | ||
.context("Failed to get Alice's account balance the second time")? | ||
); | ||
println!( | ||
"Bob: {:?}", | ||
coin_client | ||
.get_account_balance(&bob.address()) | ||
.await | ||
.context("Failed to get Bob's account balance the second time")? | ||
); | ||
|
||
Ok(()) | ||
} |
Oops, something went wrong.