From 5de606aabcb966a60fc41440035db6a56c03dc04 Mon Sep 17 00:00:00 2001 From: alexey Date: Sat, 24 Dec 2022 01:58:46 +0000 Subject: [PATCH] :alien: added fixes after tutorial --- .env.example | 1 + README.md | 240 +++++++++++++++++++++++++ tests/testnet_tests/deploy.rs | 4 +- tests/testnet_tests/initialize.rs | 28 +-- tests/testnet_tests/market_interact.rs | 6 +- tests/testnet_tests/mint.rs | 6 +- tests/testnet_tests/setup.rs | 0 tests/testnet_tests/transfer.rs | 5 +- tests/utils/testnet_tests_utils.rs | 10 +- 9 files changed, 274 insertions(+), 26 deletions(-) create mode 100644 .env.example delete mode 100644 tests/testnet_tests/setup.rs diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..e62162d --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +SECRET=YOUR_SECRET_HERE diff --git a/README.md b/README.md index f80f1df..aa8b4bc 100644 --- a/README.md +++ b/README.md @@ -32,5 +32,245 @@ Example functionalities SWAY-GANG-TOKEN provides: If a Smart Contract implements the following methods and events it can be called an SWAY-GANG-TOKEN Contract and, once deployed, it will be responsible to keep track of the created tokens on Fuel. +Hello, fuel!! +Continuing [the topic](https://forum.fuel.network/t/which-token-contract-i-should-to-use/373), I want to tell you about how to deploy and use your own token in your dapp +# How to issue my own token on the fuel testnet? +# How to issue my own token on the fuel testnet using Rust SDK? + +## Intro +In the continuation of [this topic](https://forum.fuel.network/t/which-token-contract-i-should-to-use/373), I wrote a tutorial on how to work with tokens. This tutorial walks you through the process of issuing your own token on the Fuel testnet using Rust SDK. + +## Deploy + +### Clone repository +This step involves cloning the fuel-token-standard repository from GitHub onto your local computer. To do this, you will need to use the `git clone` command. + +`git clone https://github.com/sway-gang/fuel-token-standard` + +After that let's go to the project folder + +`cd fuel-token-standard` + +### Setup env +In this step, you will set up the environment for the fuel-token-standard repository. Here we should use `forc-wallet`. To create this, you will need to follow the instructions provided in the `forc-wallet` [repository on GitHub](https://github.com/FuelLabs/forc-wallet). + +After creating a wallet, you can see a list of your accounts by using this command + +`forc-wallet list` + +You also need to visit the Fuel faucet [to get some testnet FUEL tokens](https://faucet-beta-2.fuel.network/) , which you will use to deploy and interact with your token contract. + + +Here will involve creating a `.env` file and adding your wallet secret to it. To do this, you can rename the template: + +`mv ./.env.example ./.env` + +And insert your secret inside the `.env` file +``` +SECRET=YOUR_SECRET_HERE +``` + + +### Build and deploy + +> In this section I will explain in detail how to deploy, initialize, mint and transfer tokens. If you just want to deploy tokens in one click, then skip this section and move on to the next + +In this step, you will build and deploy your token contract using the `forc` command-line tool. This involves compiling the contract code, generating the required bytecode, and deploying the contract to the Fuel testnet. + +To build the contract, you will use the `forc build` command, which will compile the contract code and generate the bytecode required for deployment. + +``` +> forc build + Compiled library "core". + Compiled library "std". + Compiled contract "token_contract". + Bytecode size is 13912 bytes. +``` + + + +To deploy the contract, you will use the `forc deploy` command, which will send the deployment transaction to the Fuel testnet. + +`forc deploy --url http://node-beta-2.fuel.network/graphql --gas-price 1 ` + +Output: +``` + Compiled library "core". + Compiled library "std". + Compiled contract "token_contract". + Bytecode size is 13912 bytes. +Contract id: +Please provide the address of the wallet you are going to sign this transaction with:fuel1s0ul05vsv84ltlxfn7fwmv0765ghah4nm5zj84z6zwy9mcutnz6q97zrcl +Transaction id to sign: 4232f9c81c5104f3f9a81a120d0bec084c8fa8be40ad6397fd7f2aa79bd8af91 +Please provide the signature: +``` +Before the deployment can be completed, you will need to sign the transaction with your wallet. To do this, you will need to use the `forc-wallet` command-line tool. First, you will need to open another terminal and use the `forc-wallet list` command to view the available wallets on your machine. + +Next, you will need to use the `forc-wallet sign` command to sign the transaction with the desired wallet. The command requires you to specify the transaction ID and the index of the wallet you want to use. + +`forc-wallet sign ` + +``` +Please enter your password to decrypt initialized wallet's phrases: +Signature: 8d9c894fcbb5ae3f1a0318cca5c783e9a67b150ca953350023c673cb640171ad12e68716d17cf7bfb2e201dd72c506ede78ccf762bed621fa37275863a2010c3 +``` + +Finally, you will need to enter the signature in the first terminal to complete the deployment. If the deployment is successful, the output will include the contract ID and the block number in which the contract was deployed. + +``` +Waiting 1s before retrying +contract 777923117c7772c0680806d2a0d3a0eb5e654fa65e48d8de85516f6f85ba4887 deployed in block 0xcc6320caa393126b98bdbd0d90fba9cd659a36546b567f7d90ba8b591020133d +``` + +## Initialize +The `initialize` test case initializes the token contract by setting its name, symbol, and number of decimals. + +To run the test case, update the `TOKEN_ADDRESS` constant in the `tests/testnet_tests/initialize.rs` file with the address of your token contract, then run the following command: + +``` +cargo test --package tests --test tests -- testnet_tests::initialize::initialize --exact --nocapture +``` + +Example output: + + + +``` +running 1 test +👛 Account address @ fuel1gzv3z02hz863dhtxzhz2d30jh62verdx7lfrzxkq9txxr3jgx4qsqgstc4 +🗞 Token address @ fuel1waujxytuwaevq6qgqmf2p5aqad0x2naxteyd3h5929hklpd6fzrsyjw5jy +✅ Initialize +Decimals: 9 +Symbol: BTC +Mint amount 1000 BTC +test testnet_tests::initialize::initialize ... ok +``` + + +## Mint + +The `mint` test case mints tokens to the wallet specified in the test configuration. + +To run the test case, update the `TOKEN_ADDRESS` constant in the `tests/testnet_tests/mint.rs` file with the address of your token contract, then run the following command: + +``` +cargo test --package tests --test tests -- testnet_tests::mint::mint --exact --nocapture +``` + +Example output: + +``` +running 1 test +👛 Account address @ fuel1gzv3z02hz863dhtxzhz2d30jh62verdx7lfrzxkq9txxr3jgx4qsqgstc4 +🗞 Token address @ fuel1waujxytuwaevq6qgqmf2p5aqad0x2naxteyd3h5929hklpd6fzrsyjw5jy +Decimals: 1 +Symbol: BBC +Mint amount: 1000 BBC +Wallet balance: 1000 BBC +✅ Mint +Wallet balance: 1000 BBC +test testnet_tests::mint::mint ... ok +``` +## Transfer + +The `transfer` test case transfers a specified amount of tokens from the wallet specified in the test configuration to the recipient specified in the test configuration. + +To run the test case, update the `TOKEN_ADDRESS`, `TRANSFER_AMOUNT`, and `RECIPIENT_ADDRESS` constants in the `tests/testnet_tests/transfer.rs` file with the address of your token contract, the amount of tokens to transfer (without decimals), and the recipient address, respectively, then run the following command: + +``` +cargo test --package tests --test tests -- testnet_tests::transfer::transfer --exact --nocapture +``` + +Example output: + +``` +running 1 test +👛 Account address @ fuel1gzv3z02hz863dhtxzhz2d30jh62verdx7lfrzxkq9txxr3jgx4qsqgstc4 +🗞 Token address @ fuel1waujxytuwaevq6qgqmf2p5aqad0x2naxteyd3h5929hklpd6fzrsyjw5jy +Decimals: 1 +Symbol: BBC +Wallet balance: 1000 BBC +Wallet balance: 990 BBC +Recipient balance: 10 BBC +test testnet_tests::transfer::transfer ... ok +``` + + +## Deploy multiple tokens in one click + +To deploy multiple tokens in one click, you will need to use the `tests/testnet_tests/deploy.rs` script. In this script, you can specify an array of token configurations, each containing the name, symbol, decimals, and mint amount for the desired tokens. + +To specify the tokens you want to deploy, modify the `configs` array in the script. For example: + +``` + // YOUR TOKENS ARRAY HERE + let configs: Vec = vec![ + DeployConfig { + name: String::from("Tether"), + symbol: String::from("USDT"), + decimals: 6, + mint_amount: 10000, + }, + DeployConfig { + name: String::from("USD Coin"), + symbol: String::from("USDC"), + decimals: 6, + mint_amount: 10000, + }, + +... + + ] +``` + +Once you have specified the desired tokens, you can run the script with the following command: + +``` +cargo test --package tests --test tests -- testnet_tests::deploy::deploy --exact --nocapture +``` + +This will build and deploy the specified tokens. The output of the command will show the initialization details for each token, as well as any additional information relevant to the deployment process. + +Example output: + +``` +running 1 test +✅ Initialize + +ownerAddress: fuel1gzv3z02hz863dhtxzhz2d30jh62verdx7lfrzxkq9txxr3jgx4qsqgstc4 +name: Tether +symbol: USDT +decimals: 6 +assetId: fuel1v4eezwvca24cn9xkp84kf26wm06cvfwef0zgsyk7mfvpqw3tm2qqf0rqha +hash: 6573913998eaab8994d609eb64ab4edbf58625d94bc48812deda58103a2bda80 +salt: [229, 154, 86, 240, 24, 119, 67, 186, 120, 209, 57, 181, 200, 35, 138, 119, 12, 183, 120, 179, 122, 172, 253, 77, 193, 37, 107, 157, 45, 225, 60, 163] + +... + +test testnet_tests::deploy::deploy ... ok +``` + +### Can I just use your tokens? + +If you don't want to spend your time deploying your own contract here is the config to the token that already exists in testnet: + +https://github.com/sway-gang/sway-lend/blob/master/frontend/src/constants/tokens.json + +And here is the link where you can mint them: https://app.swaylend.com/#/faucet. + +## Conclusion +In this tutorial, you have learned how to build and deploy a token contract using the `forc` command-line tool. You have also seen how to perform various actions with the token, such as initialize, mint, transfer, and deploy multiple tokens in one click. By following the steps outlined in this tutorial, you can quickly and easily create and manage your own token on the Fuel network. + +## Resources + +https://fuellabs.github.io/fuel-docs/master/index.html + +https://fuellabs.github.io/sway/v0.32.2/book/ + +https://fuellabs.github.io/fuels-rs/v0.33.0/ + +https://github.com/FuelLabs/swayswap + +https://forum.fuel.network/t/src-20-fungible-token-standard/186 \ No newline at end of file diff --git a/tests/testnet_tests/deploy.rs b/tests/testnet_tests/deploy.rs index f514aad..e668508 100644 --- a/tests/testnet_tests/deploy.rs +++ b/tests/testnet_tests/deploy.rs @@ -5,6 +5,7 @@ use rand::prelude::Rng; use crate::utils::number_utils::parse_units; abigen!(TokenContract, "out/debug/token_contract-abi.json"); +const RPC: &str = "node-beta-2.fuel.network"; #[derive(Debug)] struct DeployConfig { @@ -14,10 +15,9 @@ struct DeployConfig { mint_amount: u64, } -const RPC: &str = "node-beta-2.fuel.network"; - #[tokio::test] async fn deploy() { + // YOUR TOKENS ARRAY HERE let configs: Vec = vec![ DeployConfig { name: String::from("Tether"), diff --git a/tests/testnet_tests/initialize.rs b/tests/testnet_tests/initialize.rs index 311e30a..6b2fb91 100644 --- a/tests/testnet_tests/initialize.rs +++ b/tests/testnet_tests/initialize.rs @@ -3,33 +3,39 @@ use fuels::prelude::*; use crate::utils::{number_utils::*, testnet_tests_utils::*}; const ADDRESS: &str = "YOUR TOKEN ADDRESS"; +const NAME: &str = "Bitcoin"; // YOUR TOKEN NAME +const SYMBOL: &str = "BTC"; // YOUR TOKEN SYMBOL +const DECIMALS: u8 = 8; // YOUR TOKEN DECIMALS #[tokio::test] async fn initialize() { let (wallet, instance, _provider) = setup(ADDRESS).await; - let config = instance.methods().config().simulate().await.unwrap().value; - let decimals = config.decimals; - let symbol = config.symbol; - println!("Decimals: {decimals}\nSymbol: {symbol}"); + let mut name = NAME.to_string().clone(); + let mut symbol = SYMBOL.to_string().clone(); + name.push_str(" ".repeat(32 - name.len()).as_str()); + symbol.push_str(" ".repeat(8 - symbol.len()).as_str()); let result = instance .methods() .initialize( TokenInitializeConfig { - name: fuels::core::types::SizedAsciiString::<32>::new(String::from( - "Big Black Coin ", - )) - .unwrap(), - symbol: fuels::core::types::SizedAsciiString::<8>::new(String::from("BBC ")) + name: fuels::core::types::SizedAsciiString::<32>::new(String::from(name)).unwrap(), + symbol: fuels::core::types::SizedAsciiString::<8>::new(String::from(symbol)) .unwrap(), - decimals, + decimals: DECIMALS, }, - parse_units(1000, decimals), + parse_units(1000, DECIMALS), Address::from(wallet.address()), ) .tx_params(TxParameters::new(Some(1), Some(1000000), None)) .call() .await; println!("{} Initialize", if result.is_ok() { "✅" } else { "❌" }); + + let config = instance.methods().config().simulate().await.unwrap().value; + let decimals = config.decimals; + let symbol = config.symbol; + println!("Decimals: {decimals}\nSymbol: {symbol}"); + let mint_amount = instance .methods() .get_mint_amount() diff --git a/tests/testnet_tests/market_interact.rs b/tests/testnet_tests/market_interact.rs index 9d91442..a8b5278 100644 --- a/tests/testnet_tests/market_interact.rs +++ b/tests/testnet_tests/market_interact.rs @@ -5,17 +5,17 @@ use crate::utils::{testnet_tests_utils::setup, number_utils::parse_units}; abigen!(Market, "tests/artefacts/market/market-abi.json"); -const USDT_ADDRESS: &str = "YOUR TOKEN ADDRESS"; +const TOKEN_ADDRESS: &str = "YOUR TOKEN ADDRESS"; const MARKET_ADDRESS: &str = "0xabc9873302b555db02ad2e79a4afb6b1d2acbab1bf4fe08149aff8fc904a8e0c"; #[tokio::test] async fn merket_interact() { - let (wallet, dapp, _provider) = setup(USDT_ADDRESS).await; + let (wallet, dapp, _provider) = setup(TOKEN_ADDRESS).await; let config = dapp.methods().config().simulate().await.unwrap().value; let decimals = config.decimals; let symbol = config.symbol; - let asset_id = AssetId::from_str(USDT_ADDRESS).unwrap(); + let asset_id = AssetId::from_str(TOKEN_ADDRESS).unwrap(); let market_dapp_id = Bech32ContractId::from(ContractId::from_str(MARKET_ADDRESS).unwrap()); let market_dapp = Market::new(market_dapp_id, wallet.clone()); diff --git a/tests/testnet_tests/mint.rs b/tests/testnet_tests/mint.rs index fd426cd..3670a92 100644 --- a/tests/testnet_tests/mint.rs +++ b/tests/testnet_tests/mint.rs @@ -3,16 +3,16 @@ use std::str::FromStr; use crate::utils::{testnet_tests_utils::setup, number_utils::*}; -const USDT_ADDRESS: &str = "YOUR TOKEN ADDRESS"; +const TOKEN_ADDRESS: &str = "YOUR TOKEN ADDRESS"; #[tokio::test] async fn mint() { - let (wallet, dapp, _provider) = setup(USDT_ADDRESS).await; + let (wallet, dapp, _provider) = setup(TOKEN_ADDRESS).await; let config = dapp.methods().config().simulate().await.unwrap().value; let decimals = config.decimals; let symbol = config.symbol; let mint_amount = dapp.methods().get_mint_amount().simulate().await.unwrap(); - let asset_id = AssetId::from_str(USDT_ADDRESS).unwrap(); + let asset_id = AssetId::from_str(TOKEN_ADDRESS).unwrap(); println!( "Decimals: {decimals}\nSymbol: {symbol}\nMint amount: {} {symbol}", diff --git a/tests/testnet_tests/setup.rs b/tests/testnet_tests/setup.rs deleted file mode 100644 index e69de29..0000000 diff --git a/tests/testnet_tests/transfer.rs b/tests/testnet_tests/transfer.rs index c97d0ec..94d8ee7 100644 --- a/tests/testnet_tests/transfer.rs +++ b/tests/testnet_tests/transfer.rs @@ -4,7 +4,8 @@ use std::str::FromStr; use crate::utils::{number_utils::*, testnet_tests_utils::setup}; const TOKEN_ADDRESS: &str = "YOUR TOKEN ADDRESS"; -const RECIPIEND_ADDRES: &str = "fuel1v3hdp7mpsy3mnsdy4jhwt4yk67n3yqgrn6mt0d4v3wvny2dn7f7sgf3ymm"; +const TRANSFER_AMOUNT: u64 = 10; //TRANSFER AMOUNT WITHOUT DECIMALS +const RECIPIEND_ADDRES: &str = "RECIPIENT ADDRESS"; #[tokio::test] async fn transfer() { @@ -25,7 +26,7 @@ async fn transfer() { let recipient = Bech32Address::from_str(RECIPIEND_ADDRES).unwrap(); let recipient = Wallet::from_address(recipient, Some(provider.clone())); - let amount = parse_units(10, decimals); + let amount = parse_units(TRANSFER_AMOUNT, decimals); let _receipts = wallet .transfer( recipient.address(), diff --git a/tests/utils/testnet_tests_utils.rs b/tests/utils/testnet_tests_utils.rs index 413909a..b731112 100644 --- a/tests/utils/testnet_tests_utils.rs +++ b/tests/utils/testnet_tests_utils.rs @@ -21,13 +21,13 @@ pub async fn setup(address: &str) -> (WalletUnlocked, TokenContract, Provider) { let wallet = WalletUnlocked::new_from_private_key(secret.parse().unwrap(), Some(provider.clone())); - let usdt_dapp_id = Bech32ContractId::from(ContractId::from_str(address).unwrap()); - let usdt_dapp_instance = TokenContract::new(usdt_dapp_id, wallet.clone()); + let token_id = Bech32ContractId::from(ContractId::from_str(address).unwrap()); + let instance = TokenContract::new(token_id, wallet.clone()); println!("👛 Account address @ {}", wallet.clone().address()); println!( - "🗞 USDT dapp address @ {}", - usdt_dapp_instance.get_contract_id() + "🗞 Token address @ {}", + instance.get_contract_id() ); - return (wallet, usdt_dapp_instance, provider); + return (wallet, instance, provider); } \ No newline at end of file