From 4cd6af703d47d735bcdc93ca8988755f06e41545 Mon Sep 17 00:00:00 2001 From: Jeff Wood Date: Sat, 24 Aug 2024 03:12:35 +0000 Subject: [PATCH 01/14] Update the Token Extensions Program link --- content/courses/tokens-and-nfts/token-program.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/courses/tokens-and-nfts/token-program.md b/content/courses/tokens-and-nfts/token-program.md index f06d0e69c..74e27b33d 100644 --- a/content/courses/tokens-and-nfts/token-program.md +++ b/content/courses/tokens-and-nfts/token-program.md @@ -28,7 +28,7 @@ description: - Creating Token Mints and Token Accounts requires allocating **rent** in SOL. The rent for a Token Account can be refunded when the account is closed. Additionally, tokens created with the - [Token Extensions Program](/developers/courses/token-extensions-for-mints/close-mint) + [Token Extensions Program](/content/courses/token-extensions/close-mint) can also close Token Mints. ### Lesson From d2d2cae3413e6d3f0455830b4923811e9964ff80 Mon Sep 17 00:00:00 2001 From: Jeff Wood Date: Sat, 24 Aug 2024 07:36:25 +0000 Subject: [PATCH 02/14] update the Cryptography fundamentals link --- content/courses/tokens-and-nfts/token-program.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/courses/tokens-and-nfts/token-program.md b/content/courses/tokens-and-nfts/token-program.md index 74e27b33d..a585f52d4 100644 --- a/content/courses/tokens-and-nfts/token-program.md +++ b/content/courses/tokens-and-nfts/token-program.md @@ -461,7 +461,7 @@ We’re going to use the Token Token Program to create a Token Mint, create an Associated Token Account, mint tokens, transfer tokens, and burn tokens. Assuming you already have a `.env` file with a `SECRET_KEY` setup per -[Cryptography fundamentals](/developers/courses/intro-to-solana/intro-to-cryptography). +[Cryptography fundamentals](/content/courses/intro-to-solana/intro-to-cryptography). ```bash npm i @solana/web3.js @solana/spl-token @solana-developers/helpers esrun From 15bc1459f45df5006c1323e348cde0131c27246d Mon Sep 17 00:00:00 2001 From: Jeff Wood Date: Sat, 24 Aug 2024 08:17:07 +0000 Subject: [PATCH 03/14] add try/catch following the CONTRIBUTING.md --- content/courses/tokens-and-nfts/token-program.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/content/courses/tokens-and-nfts/token-program.md b/content/courses/tokens-and-nfts/token-program.md index a585f52d4..7ed945af2 100644 --- a/content/courses/tokens-and-nfts/token-program.md +++ b/content/courses/tokens-and-nfts/token-program.md @@ -497,11 +497,18 @@ console.log( // SystemProgram.createAccount() // token.createInitializeMintInstruction() // See https://www.soldev.app/course/token-program -const tokenMint = await createMint(connection, user, user.publicKey, null, 2); +try { + const tokenMint = await createMint(connection, user, user.publicKey, null, 2); -const link = getExplorerLink("address", tokenMint.toString(), "devnet"); + const link = getExplorerLink("address", tokenMint.toString(), "devnet"); -console.log(`✅ Finished! Created token mint: ${link}`); + console.log(`✅ Finished! Created token mint: ${link}`); + +} catch (error) { + + console.log("createMint failed with errors: "); + console.log(error); +} ``` Run the script using `npx esrun create-token-mint.ts`. You should see From 4b26ed22d3fdfe2705d69d73f105d9753862dd79 Mon Sep 17 00:00:00 2001 From: Jeff Wood Date: Sat, 24 Aug 2024 09:46:39 +0000 Subject: [PATCH 04/14] continuing adding try/catch add some missing instructions fix a wrong ts command fix [add a second account on devnet] link --- .../courses/tokens-and-nfts/token-program.md | 201 +++++++++++------- 1 file changed, 124 insertions(+), 77 deletions(-) diff --git a/content/courses/tokens-and-nfts/token-program.md b/content/courses/tokens-and-nfts/token-program.md index 7ed945af2..3e0831d66 100644 --- a/content/courses/tokens-and-nfts/token-program.md +++ b/content/courses/tokens-and-nfts/token-program.md @@ -506,8 +506,8 @@ try { } catch (error) { - console.log("createMint failed with errors: "); - console.log(error); + console.log("❌ createMint failed with errors: "); + console.log(error.message); } ``` @@ -612,28 +612,37 @@ const createMetadataAccountInstruction = transaction.add(createMetadataAccountInstruction); -const transactionSignature = await sendAndConfirmTransaction( - connection, - transaction, - [user], -); +try { -const transactionLink = getExplorerLink( - "transaction", - transactionSignature, - "devnet", -); + const transactionSignature = await sendAndConfirmTransaction( + connection, + transaction, + [user], + ); -console.log(`✅ Transaction confirmed, explorer link is: ${transactionLink}!`); + const transactionLink = getExplorerLink( + "transaction", + transactionSignature, + "devnet", + ); -const tokenMintLink = getExplorerLink( - "address", - tokenMintAccount.toString(), - "devnet", -); + console.log(`✅ Transaction confirmed, explorer link is: ${transactionLink}`); + + const tokenMintLink = getExplorerLink( + "address", + tokenMintAccount.toString(), + "devnet", + ); + + console.log(`✅ Look at the token mint again: ${tokenMintLink}`); -console.log(`✅ Look at the token mint again: ${tokenMintLink}!`); +} catch (error) { + + console.log("❌ Make token metadata failed with errors:"); + console.log(error.message); +} ``` +Replace `YOUR_TOKEN_MINT_ADDRESS_HERE` with your address of the mint and Run the script using `npx esrun create-token-metadata.ts`. You'll now see Solana Explorer is updated, showing the token's name and symbol on the mint! @@ -686,25 +695,29 @@ const tokenMintAccount = new PublicKey("YOUR_TOKEN_MINT"); // const recipient = new PublicKey("SOMEONE_ELSES_DEVNET_ADDRESS"); const recipient = user.publicKey; -const tokenAccount = await getOrCreateAssociatedTokenAccount( - connection, - user, - tokenMintAccount, - recipient, -); - -console.log(`Token Account: ${tokenAccount.address.toBase58()}`); - -const link = getExplorerLink( - "address", - tokenAccount.address.toBase58(), - "devnet", -); - -console.log(`✅ Created token Account: ${link}`); +try { + const tokenAccount = await getOrCreateAssociatedTokenAccount( + connection, + user, + tokenMintAccount, + recipient + ); + + console.log(`Token Account: ${tokenAccount.address.toBase58()}`); + + const link = getExplorerLink( + "address", + tokenAccount.address.toBase58(), + "devnet" + ); + + console.log(`✅ Created token Account: ${link}`); +} catch (error) { + console.log("❌ Create token account failed with errors:"); + console.log(error.message); +} ``` - -Run the script using `npx esrun create-token-mint.ts`. You should see: +Run the script using `npx esrun create-token-account.ts`. You should see: ```bash ✅ Success! Created token account: https://explorer.solana.com/address/CTjoLdEeK8rk4YWYW9ZqACyjHexbYKH3hEoagHxLVEFs?cluster=devnet @@ -714,14 +727,17 @@ Open the token account in Solana Explorer. Look at the owner - it's the account you made the ATA for! The balance will be zero, as we haven't sent any tokens there yet. Let's mint some tokens there and fix that! +Remember the address of your token account ! We'll use it to mint tokens. + #### Mint Tokens Now that we have a token mint and a token account, let's mint tokens to the token account. Recall that we set the `user` as the `mintAuthority` for the `mint` we created. -Create a function `mintTokens` that uses the `spl-token` function `mintTo` to -mint tokens: +Create an empty file called `mint-tokens.ts`. Then uses the `spl-token` function `mintTo` to +mint tokens. +Remember to substitute in your token mint address and token account address below! ```typescript import { mintTo } from "@solana/spl-token"; @@ -746,18 +762,23 @@ const recipientAssociatedTokenAccount = new PublicKey( "RECIPIENT_TOKEN_ACCOUNT", ); -const transactionSignature = await mintTo( - connection, - user, - tokenMintAccount, - recipientAssociatedTokenAccount, - user, - 10 * MINOR_UNITS_PER_MAJOR_UNITS, -); - -const link = getExplorerLink("transaction", transactionSignature, "devnet"); - -console.log(`✅ Success! Mint Token Transaction: ${link}`); +try { + const transactionSignature = await mintTo( + connection, + user, + tokenMintAccount, + recipientAssociatedTokenAccount, + user, + 10 * MINOR_UNITS_PER_MAJOR_UNITS, + ); + + const link = getExplorerLink("transaction", transactionSignature, "devnet"); + + console.log(`✅ Success! Mint Token Transaction: ${link}`); +} catch (error) { + console.log("❌ mintToken failed with errors: "); + console.log(error.message); +} ``` Run the script using `npx esrun mint-tokens.ts`. You should see: @@ -773,7 +794,7 @@ account! Next, let's transfer some of the tokens we just minted using the `spl-token` library's `transfer` function. You can -[add a second account on devnet](/developers/courses/intro-to-solana/intro-to-cryptography) +[add a second account on devnet](/content/courses/intro-to-solana/intro-to-cryptography) if you like, or find a friend who has a devnet account and send them your token! As you saw in Explorer, the tokens currently reside in an Associated Token @@ -783,6 +804,9 @@ associated token account - we can just look it up using mint of the token we want to send. Likewise, we can find (or make) an ATA for our recipient to hold this token too. +Create an empty file called `transfer-tokens.ts`. Then replace `YOUR_RECIPIENT_HERE` with your recipient public key +and replace `YOUR_TOKEN_MINT_ADDRESS_HERE` with your token mint address. + ```typescript import "dotenv/config"; import { @@ -810,36 +834,59 @@ const MINOR_UNITS_PER_MAJOR_UNITS = Math.pow(10, 2); console.log(`💸 Attempting to send 1 token to ${recipient.toBase58()}...`); -// Get or create the source and destination token accounts to store this token -const sourceTokenAccount = await getOrCreateAssociatedTokenAccount( - connection, - sender, - tokenMintAccount, - sender.publicKey, -); -const destinationTokenAccount = await getOrCreateAssociatedTokenAccount( - connection, - sender, - tokenMintAccount, - recipient, -); +let sourceTokenAccount: { address: PublicKey; }; +try { + // Get or create the source token account to store this token + const sourceTokenAccount = await getOrCreateAssociatedTokenAccount( + connection, + sender, + tokenMintAccount, + sender.publicKey, + ); +} catch (error) { + console.log("❌ Get or create the source token account failed with errors."); + throw new Error(error.message); +} -// Transfer the tokens -const signature = await transfer( - connection, - sender, - sourceTokenAccount.address, - destinationTokenAccount.address, - sender, - 1 * MINOR_UNITS_PER_MAJOR_UNITS, -); +let destinationTokenAccount: { address: PublicKey; }; +try { + // Get or create the destination token account to store this token + const destinationTokenAccount = await getOrCreateAssociatedTokenAccount( + connection, + sender, + tokenMintAccount, + recipient, + ); +} catch (error) { + console.log("❌ Get or create the destination token account failed with errors."); + throw new Error(error.message); +} -const explorerLink = getExplorerLink("transaction", signature, "devnet"); +try { + // Transfer the tokens + const signature = await transfer( + connection, + sender, + sourceTokenAccount.address, + destinationTokenAccount.address, + sender, + 1 * MINOR_UNITS_PER_MAJOR_UNITS, + ); -console.log(`✅ Transaction confirmed, explorer link is: ${explorerLink}!`); -``` + const explorerLink = getExplorerLink("transaction", signature, "devnet"); + console.log(`✅ Transaction confirmed, explorer link is: ${explorerLink}`); + +} catch (error) { + console.log("❌ transfer tokens failed with errors: "); + console.log(error.message); +} +``` +Run the script using `npx esrun transfer-tokens.ts`. You should see: +```bash +✅ Transaction confirmed, explorer link is: https://explorer.solana.com/tx/SgV2j2DkaErYf7ERiB11USoZzGqAk8HPEqVJLP8HWdz9M61FSFgyEMXJycHQtfCooCAPBom7Vi3akEAwSUHQUsu?cluster=devnet +``` Open the Explorer link. You see your balance go down, and the recipient's balance go up! From 5e3d519f27eef746e9b504c323d94aed8e6365c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B9=9D=E5=8D=81=E6=9B=BF=20=E9=99=88=E4=B8=BD=E8=99=B9?= Date: Sat, 24 Aug 2024 18:26:32 +0800 Subject: [PATCH 05/14] prettier:fix --- .../courses/tokens-and-nfts/token-program.md | 210 +++++++++--------- .../getstarted/local-rust-hello-world.md | 4 +- docs/programs/examples.md | 5 +- 3 files changed, 111 insertions(+), 108 deletions(-) diff --git a/content/courses/tokens-and-nfts/token-program.md b/content/courses/tokens-and-nfts/token-program.md index 3e0831d66..def05b909 100644 --- a/content/courses/tokens-and-nfts/token-program.md +++ b/content/courses/tokens-and-nfts/token-program.md @@ -28,8 +28,8 @@ description: - Creating Token Mints and Token Accounts requires allocating **rent** in SOL. The rent for a Token Account can be refunded when the account is closed. Additionally, tokens created with the - [Token Extensions Program](/content/courses/token-extensions/close-mint) - can also close Token Mints. + [Token Extensions Program](/content/courses/token-extensions/close-mint) can + also close Token Mints. ### Lesson @@ -498,16 +498,14 @@ console.log( // token.createInitializeMintInstruction() // See https://www.soldev.app/course/token-program try { - const tokenMint = await createMint(connection, user, user.publicKey, null, 2); + const tokenMint = await createMint(connection, user, user.publicKey, null, 2); - const link = getExplorerLink("address", tokenMint.toString(), "devnet"); - - console.log(`✅ Finished! Created token mint: ${link}`); + const link = getExplorerLink("address", tokenMint.toString(), "devnet"); + console.log(`✅ Finished! Created token mint: ${link}`); } catch (error) { - - console.log("❌ createMint failed with errors: "); - console.log(error.message); + console.log("❌ createMint failed with errors: "); + console.log(error.message); } ``` @@ -613,36 +611,35 @@ const createMetadataAccountInstruction = transaction.add(createMetadataAccountInstruction); try { + const transactionSignature = await sendAndConfirmTransaction( + connection, + transaction, + [user], + ); - const transactionSignature = await sendAndConfirmTransaction( - connection, - transaction, - [user], - ); - - const transactionLink = getExplorerLink( - "transaction", - transactionSignature, - "devnet", - ); - - console.log(`✅ Transaction confirmed, explorer link is: ${transactionLink}`); + const transactionLink = getExplorerLink( + "transaction", + transactionSignature, + "devnet", + ); - const tokenMintLink = getExplorerLink( - "address", - tokenMintAccount.toString(), - "devnet", - ); + console.log(`✅ Transaction confirmed, explorer link is: ${transactionLink}`); - console.log(`✅ Look at the token mint again: ${tokenMintLink}`); + const tokenMintLink = getExplorerLink( + "address", + tokenMintAccount.toString(), + "devnet", + ); + console.log(`✅ Look at the token mint again: ${tokenMintLink}`); } catch (error) { - - console.log("❌ Make token metadata failed with errors:"); - console.log(error.message); + console.log("❌ Make token metadata failed with errors:"); + console.log(error.message); } ``` -Replace `YOUR_TOKEN_MINT_ADDRESS_HERE` with your address of the mint and Run the script using `npx esrun create-token-metadata.ts`. + +Replace `YOUR_TOKEN_MINT_ADDRESS_HERE` with your address of the mint and Run the +script using `npx esrun create-token-metadata.ts`. You'll now see Solana Explorer is updated, showing the token's name and symbol on the mint! @@ -696,27 +693,28 @@ const tokenMintAccount = new PublicKey("YOUR_TOKEN_MINT"); const recipient = user.publicKey; try { - const tokenAccount = await getOrCreateAssociatedTokenAccount( - connection, - user, - tokenMintAccount, - recipient - ); - - console.log(`Token Account: ${tokenAccount.address.toBase58()}`); - - const link = getExplorerLink( - "address", - tokenAccount.address.toBase58(), - "devnet" - ); - - console.log(`✅ Created token Account: ${link}`); + const tokenAccount = await getOrCreateAssociatedTokenAccount( + connection, + user, + tokenMintAccount, + recipient, + ); + + console.log(`Token Account: ${tokenAccount.address.toBase58()}`); + + const link = getExplorerLink( + "address", + tokenAccount.address.toBase58(), + "devnet", + ); + + console.log(`✅ Created token Account: ${link}`); } catch (error) { - console.log("❌ Create token account failed with errors:"); - console.log(error.message); + console.log("❌ Create token account failed with errors:"); + console.log(error.message); } ``` + Run the script using `npx esrun create-token-account.ts`. You should see: ```bash @@ -735,9 +733,9 @@ Now that we have a token mint and a token account, let's mint tokens to the token account. Recall that we set the `user` as the `mintAuthority` for the `mint` we created. -Create an empty file called `mint-tokens.ts`. Then uses the `spl-token` function `mintTo` to -mint tokens. -Remember to substitute in your token mint address and token account address below! +Create an empty file called `mint-tokens.ts`. Then uses the `spl-token` function +`mintTo` to mint tokens. Remember to substitute in your token mint address and +token account address below! ```typescript import { mintTo } from "@solana/spl-token"; @@ -763,21 +761,21 @@ const recipientAssociatedTokenAccount = new PublicKey( ); try { - const transactionSignature = await mintTo( - connection, - user, - tokenMintAccount, - recipientAssociatedTokenAccount, - user, - 10 * MINOR_UNITS_PER_MAJOR_UNITS, - ); - - const link = getExplorerLink("transaction", transactionSignature, "devnet"); - - console.log(`✅ Success! Mint Token Transaction: ${link}`); + const transactionSignature = await mintTo( + connection, + user, + tokenMintAccount, + recipientAssociatedTokenAccount, + user, + 10 * MINOR_UNITS_PER_MAJOR_UNITS, + ); + + const link = getExplorerLink("transaction", transactionSignature, "devnet"); + + console.log(`✅ Success! Mint Token Transaction: ${link}`); } catch (error) { - console.log("❌ mintToken failed with errors: "); - console.log(error.message); + console.log("❌ mintToken failed with errors: "); + console.log(error.message); } ``` @@ -804,8 +802,9 @@ associated token account - we can just look it up using mint of the token we want to send. Likewise, we can find (or make) an ATA for our recipient to hold this token too. -Create an empty file called `transfer-tokens.ts`. Then replace `YOUR_RECIPIENT_HERE` with your recipient public key -and replace `YOUR_TOKEN_MINT_ADDRESS_HERE` with your token mint address. +Create an empty file called `transfer-tokens.ts`. Then replace +`YOUR_RECIPIENT_HERE` with your recipient public key and replace +`YOUR_TOKEN_MINT_ADDRESS_HERE` with your token mint address. ```typescript import "dotenv/config"; @@ -834,59 +833,62 @@ const MINOR_UNITS_PER_MAJOR_UNITS = Math.pow(10, 2); console.log(`💸 Attempting to send 1 token to ${recipient.toBase58()}...`); - -let sourceTokenAccount: { address: PublicKey; }; +let sourceTokenAccount: { address: PublicKey }; try { - // Get or create the source token account to store this token - const sourceTokenAccount = await getOrCreateAssociatedTokenAccount( - connection, - sender, - tokenMintAccount, - sender.publicKey, - ); + // Get or create the source token account to store this token + const sourceTokenAccount = await getOrCreateAssociatedTokenAccount( + connection, + sender, + tokenMintAccount, + sender.publicKey, + ); } catch (error) { - console.log("❌ Get or create the source token account failed with errors."); - throw new Error(error.message); + console.log("❌ Get or create the source token account failed with errors."); + throw new Error(error.message); } -let destinationTokenAccount: { address: PublicKey; }; +let destinationTokenAccount: { address: PublicKey }; try { - // Get or create the destination token account to store this token - const destinationTokenAccount = await getOrCreateAssociatedTokenAccount( - connection, - sender, - tokenMintAccount, - recipient, - ); + // Get or create the destination token account to store this token + const destinationTokenAccount = await getOrCreateAssociatedTokenAccount( + connection, + sender, + tokenMintAccount, + recipient, + ); } catch (error) { - console.log("❌ Get or create the destination token account failed with errors."); - throw new Error(error.message); + console.log( + "❌ Get or create the destination token account failed with errors.", + ); + throw new Error(error.message); } try { - // Transfer the tokens - const signature = await transfer( - connection, - sender, - sourceTokenAccount.address, - destinationTokenAccount.address, - sender, - 1 * MINOR_UNITS_PER_MAJOR_UNITS, - ); - - const explorerLink = getExplorerLink("transaction", signature, "devnet"); + // Transfer the tokens + const signature = await transfer( + connection, + sender, + sourceTokenAccount.address, + destinationTokenAccount.address, + sender, + 1 * MINOR_UNITS_PER_MAJOR_UNITS, + ); - console.log(`✅ Transaction confirmed, explorer link is: ${explorerLink}`); + const explorerLink = getExplorerLink("transaction", signature, "devnet"); + console.log(`✅ Transaction confirmed, explorer link is: ${explorerLink}`); } catch (error) { - console.log("❌ transfer tokens failed with errors: "); - console.log(error.message); + console.log("❌ transfer tokens failed with errors: "); + console.log(error.message); } ``` + Run the script using `npx esrun transfer-tokens.ts`. You should see: + ```bash ✅ Transaction confirmed, explorer link is: https://explorer.solana.com/tx/SgV2j2DkaErYf7ERiB11USoZzGqAk8HPEqVJLP8HWdz9M61FSFgyEMXJycHQtfCooCAPBom7Vi3akEAwSUHQUsu?cluster=devnet ``` + Open the Explorer link. You see your balance go down, and the recipient's balance go up! diff --git a/content/guides/getstarted/local-rust-hello-world.md b/content/guides/getstarted/local-rust-hello-world.md index a905ddc63..2af5badd5 100644 --- a/content/guides/getstarted/local-rust-hello-world.md +++ b/content/guides/getstarted/local-rust-hello-world.md @@ -229,8 +229,8 @@ library. ### Install Node.js To use node in WSL2 on Windows, please follow this -[guide to installing node in WSL2](https://learn.microsoft.com/en-us/windows/dev-environment/javascript/nodejs-on-wsl) -to install node. +[guide to installing node in WSL2](https://learn.microsoft.com/en-us/windows/dev-environment/javascript/nodejs-on-wsl) to +install node. ```shell sudo apt-get install curl diff --git a/docs/programs/examples.md b/docs/programs/examples.md index bd70d765d..6a013545e 100644 --- a/docs/programs/examples.md +++ b/docs/programs/examples.md @@ -39,8 +39,9 @@ framework), [Anchor](https://www.anchor-lang.com/docs/installation), [Seahorse](https://seahorse-lang.org/) and it also contains a list of examples that we would love to [see as contributions](https://github.com/solana-developers/program-examples?tab=readme-ov-file#examples-wed-love-to-see). -Within the repo you will find the following subfolder, each with assorted -example programs within them: +Within +the repo you will find the following subfolder, each with assorted example +programs within them: - [Basics](#basics) - [Compression](#compression) From 707b2b2e0e6974ca4ae6da0bd1dc23ac57d99ae1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B9=9D=E5=8D=81=E6=9B=BF=20=E9=99=88=E4=B8=BD=E8=99=B9?= Date: Sat, 24 Aug 2024 18:59:20 +0800 Subject: [PATCH 06/14] prettier:fix --- content/guides/getstarted/local-rust-hello-world.md | 4 ++-- docs/programs/examples.md | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/content/guides/getstarted/local-rust-hello-world.md b/content/guides/getstarted/local-rust-hello-world.md index 2af5badd5..a905ddc63 100644 --- a/content/guides/getstarted/local-rust-hello-world.md +++ b/content/guides/getstarted/local-rust-hello-world.md @@ -229,8 +229,8 @@ library. ### Install Node.js To use node in WSL2 on Windows, please follow this -[guide to installing node in WSL2](https://learn.microsoft.com/en-us/windows/dev-environment/javascript/nodejs-on-wsl) to -install node. +[guide to installing node in WSL2](https://learn.microsoft.com/en-us/windows/dev-environment/javascript/nodejs-on-wsl) +to install node. ```shell sudo apt-get install curl diff --git a/docs/programs/examples.md b/docs/programs/examples.md index 6a013545e..bd70d765d 100644 --- a/docs/programs/examples.md +++ b/docs/programs/examples.md @@ -39,9 +39,8 @@ framework), [Anchor](https://www.anchor-lang.com/docs/installation), [Seahorse](https://seahorse-lang.org/) and it also contains a list of examples that we would love to [see as contributions](https://github.com/solana-developers/program-examples?tab=readme-ov-file#examples-wed-love-to-see). -Within -the repo you will find the following subfolder, each with assorted example -programs within them: +Within the repo you will find the following subfolder, each with assorted +example programs within them: - [Basics](#basics) - [Compression](#compression) From c4bfac6d6f08d037c6af862d9c33e36a451fb0ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B9=9D=E5=8D=81=E6=9B=BF=20=E9=99=88=E4=B8=BD=E8=99=B9?= Date: Sun, 25 Aug 2024 14:04:52 +0800 Subject: [PATCH 07/14] Delete "web3." for "web3.Transaction" in the section Brun Tokens. Using the system program as the delegate in the typescript of Delegating tokens. Add some instructions for Delegating tokens, Revoke Delegate, and Burn Tokens. Fix [creating NFTs with Metaplex] link. Fix [previous chapter] link. Fix [Transferring Tokens] link. Fix the import @solana/web3.js statements in the section Brun Tokens. Fix a wrong argument passed to calling the revoke function in the typescript for Revoke Delegate. --- .../tokens-and-nfts/token-program-advanced.md | 212 +++++++++++++----- 1 file changed, 156 insertions(+), 56 deletions(-) diff --git a/content/courses/tokens-and-nfts/token-program-advanced.md b/content/courses/tokens-and-nfts/token-program-advanced.md index fd9472e45..815a26391 100644 --- a/content/courses/tokens-and-nfts/token-program-advanced.md +++ b/content/courses/tokens-and-nfts/token-program-advanced.md @@ -4,15 +4,14 @@ objectives: - Understand why and how to burn tokens - Allow a token holder to allocate a limited amount of tokens to another account to spend or burn using token delegation. -description: - "How to burn tokens, and approve/revoke token delegations on Solana." +description: "How to burn tokens, and approve/revoke token delegations on Solana." --- ### Lesson Finally, we'll cover burning tokens, and delegation. You may not use these in your own application, so if you're really excited about NFTs, feel free to skip -to [creating NFTs with Metaplex](/content/courses/tokens/nfts-with-metaplex)! +to [creating NFTs with Metaplex](/content/courses/tokens-and-nfts/nfts-with-metaplex)! ### Burn Tokens @@ -50,7 +49,7 @@ Under the hood, the `burn` function creates a transaction with instructions obtained from the `createBurnInstruction` function: ```typescript -import { PublicKey, Transaction } from "@solana/web3"; +import { PublicKey, Transaction } from "@solana/web3.js"; import { createBurnInstruction } from "@solana/spl-token"; async function buildBurnTransaction( @@ -104,7 +103,7 @@ Under the hood, the `approve` function creates a transaction with instructions obtained from the `createApproveInstruction` function: ```typescript -import { PublicKey, Transaction } from "@solana/web3"; +import { PublicKey, Transaction } from "@solana/web3.js"; import { createApproveInstruction } from "@solana/spl-token"; async function buildApproveTransaction( @@ -112,7 +111,7 @@ async function buildApproveTransaction( delegate: PublicKey, owner: PublicKey, amount: number, -): Promise { +): Promise { const transaction = new Transaction().add( createApproveInstruction(account, delegate, owner, amount), ); @@ -149,13 +148,13 @@ Under the hood, the `revoke` function creates a transaction with instructions obtained from the `createRevokeInstruction` function: ```typescript -import { PublicKey, Transaction } from "@solana/web3"; +import { PublicKey, Transaction } from "@solana/web3.js"; import { revoke } from "@solana/spl-token"; async function buildRevokeTransaction( account: PublicKey, owner: PublicKey, -): Promise { +): Promise { const transaction = new Transaction().add( createRevokeInstruction(account, owner), ); @@ -167,19 +166,19 @@ async function buildRevokeTransaction( ### Lab This lab extends the lab from the -[previous chapter](/content/courses/tokens/token-program). +[previous chapter](/content/courses/tokens-and-nfts/token-program). #### 1. Delegating tokens Let's use `approve` from `spl-token` to authorize a delegate to transfer or burn up to 50 tokens from our token account. -Just like [Transferring Tokens](/content/courses/tokens/token-program) in the +Just like [Transferring Tokens](/content/courses/tokens-and-nfts/token-program) in the previous lab, you can -[add a second account on devnet](/developers/courses/intro-to-solana/intro-to-cryptography) +[add a second account on devnet](/content/courses/intro-to-solana/intro-to-cryptography) if you like, or find a friend who has a devnet account! -Create a new file `delegate-tokens.ts` +Create a new file `delegate-tokens.ts`. We use the system program account as the delegate here for demonstration. ```typescript import "dotenv/config"; @@ -202,34 +201,46 @@ console.log( `🔑 Loaded our keypair securely, using an env file! Our public key is: ${user.publicKey.toBase58()}`, ); -// Add the delegate public key here. -const delegate = new PublicKey("YOUR_DELEGATE_HERE"); +// Use the system program public key +const delegate = new PublicKey("11111111111111111111111111111111"); // Substitute in your token mint account const tokenMintAccount = new PublicKey("YOUR_TOKEN_MINT_ADDRESS_HERE"); -// Get or create the source and destination token accounts to store this token -const sourceTokenAccount = await getOrCreateAssociatedTokenAccount( - connection, - user, - tokenMintAccount, - user.publicKey, -); +let sourceTokenAccount: Account; +try { + // Get or create the source and destination token accounts to store this token + sourceTokenAccount = await getOrCreateAssociatedTokenAccount( + connection, + user, + tokenMintAccount, + user.publicKey, + ); +} catch (error) { + console.log("❌ getOrCreateAssociatedTokenAccount failed with errors:"); + throw new Error(error.message); +} // Our token has two decimal places const MINOR_UNITS_PER_MAJOR_UNITS = Math.pow(10, 2); -const approveTransactionSignature = await approve( - connection, - user, - sourceTokenAccount.address, - delegate, - user.publicKey, - 50 * MINOR_UNITS_PER_MAJOR_UNITS, -); +let approveTransactionSignature: string; +try { + approveTransactionSignature = await approve( + connection, + user, + sourceTokenAccount.address, + delegate, + user.publicKey, + 50 * MINOR_UNITS_PER_MAJOR_UNITS, + ); +} catch (error) { + console.log("❌ approve failed with errors:"); + throw new Error(error.message); +} console.log( - `Approve Delegate Transaction: ${getExplorerLink( + `✅ Approve Delegate Transaction: ${getExplorerLink( "transaction", approveTransactionSignature, "devnet", @@ -237,25 +248,78 @@ console.log( ); ``` +Replace `YOUR_TOKEN_MINT_ADDRESS_HERE` with your mint token address obtained from the previous chapter. + +Run the script using `npx esrun delegate-tokens.ts`. You should see: + +```bash +✅ Approve Delegate Transaction: https://explorer.solana.com/tx/3sBr62x2VMaoJ4Z3SQMy6ZPzQKaa5Bs9ni9dgwwZZ5qEViKh1gQznCgH489h6pgfruMmqPbc2GgminTPK4UXRRZd?cluster=devnet +``` + +Open the explorer link, you will see the ‌approval information. + #### 2. Revoke Delegate Lets revoke the `delegate` using the `spl-token` library's `revoke` function. -Revoke will set delegate for the token account to null and reset the delegated +Revoke will set delegate for the associated token account to null and reset the delegated amount to 0. -All we will need for this function is the token account and user. After the +Create a new file `revoke-approve-tokens.ts`. ```typescript -const revokeTransactionSignature = await revoke( - connection, - user, - delegate, - user.publicKey, +import "dotenv/config"; +import { + getExplorerLink, + getKeypairFromEnvironment, +} from "@solana-developers/helpers"; +import { Connection, PublicKey, clusterApiUrl } from "@solana/web3.js"; +import { + Account, + getOrCreateAssociatedTokenAccount, + revoke, +} from "@solana/spl-token"; + +const connection = new Connection(clusterApiUrl("devnet")); + +const user = getKeypairFromEnvironment("SECRET_KEY"); + +console.log( + `🔑 Loaded our keypair securely, using an env file! Our public key is: ${user.publicKey.toBase58()}`, ); +// Substitute in your token mint account +const tokenMintAccount = new PublicKey("YOUR_TOKEN_MINT_ADDRESS_HERE"); + +let sourceTokenAccount: Account; +try { + // Get or create the source and destination token accounts to store this token + sourceTokenAccount = await getOrCreateAssociatedTokenAccount( + connection, + user, + tokenMintAccount, + user.publicKey, + ); +} catch (error) { + console.log("❌ getOrCreateAssociatedTokenAccount failed with errors:"); + throw new Error(error.message); +} + +let revokeTransactionSignature: String; +try { + revokeTransactionSignature = await revoke( + connection, + user, + sourceTokenAccount.address, + user.publicKey, + ); +} catch (error) { + console.log("❌ revoke failed with errors:"); + throw new Error(error.message); +} + console.log( - `Revoke Delegate Transaction: ${getExplorerLink( + `✅ Revoke Delegate Transaction: ${getExplorerLink( "transaction", revokeTransactionSignature, "devnet", @@ -263,6 +327,16 @@ console.log( ); ``` +Replace `YOUR_TOKEN_MINT_ADDRESS_HERE` with your mint token address obtained from the previous chapter. + +Run the script using `npx esrun revoke-approve-tokens.ts`. You should see: + +```bash +✅ Revoke Delegate Transaction: https://explorer.solana.com/tx/5UboxLULHT3pPznBxThfQMc73NNjYNLmvqrB3JVVXPwWxUFWA49WG58sFQP8B5rv4FXxxZm3mur319YNiyYxYgBd?cluster=devnet +``` + +Open the explorer link, you will see the revoke information. + #### 3. Burn Tokens Finally, let's remove some tokens from circulation by burning them. @@ -270,7 +344,7 @@ Finally, let's remove some tokens from circulation by burning them. Use the `spl-token` library's `burn` function to remove half of your tokens from circulation. -Now call this new function in `main` to burn 25 of the user's tokens. +Create a new file `burn-tokens.ts`. ```typescript import "dotenv/config"; @@ -279,7 +353,11 @@ import { getKeypairFromEnvironment, } from "@solana-developers/helpers"; import { Connection, PublicKey, clusterApiUrl } from "@solana/web3.js"; -import { getOrCreateAssociatedTokenAccount, burn } from "@solana/spl-token"; +import { + getOrCreateAssociatedTokenAccount, + Account, + burn, +} from "@solana/spl-token"; const connection = new Connection(clusterApiUrl("devnet")); @@ -292,28 +370,40 @@ console.log( // Substitute in your token mint account const tokenMintAccount = new PublicKey("YOUR_TOKEN_MINT_ADDRESS_HERE"); -// Get the account where the user stores these tokens -const sourceTokenAccount = await getOrCreateAssociatedTokenAccount( - connection, - user, - tokenMintAccount, - user.publicKey, -); +let sourceTokenAccount: Account; +try { + // Get or create the source and destination token accounts to store this token + sourceTokenAccount = await getOrCreateAssociatedTokenAccount( + connection, + user, + tokenMintAccount, + user.publicKey, + ); +} catch (error) { + console.log("❌ getOrCreateAssociatedTokenAccount failed with errors:"); + throw new Error(error.message); +} // Our token has two decimal places const MINOR_UNITS_PER_MAJOR_UNITS = Math.pow(10, 2); -const transactionSignature = await burn( - connection, - user, - sourceTokenAccount.address, - tokenMintAccount, - user, - 25 * MINOR_UNITS_PER_MAJOR_UNITS, -); +let transactionSignature: string; +try { + transactionSignature = await burn( + connection, + user, + sourceTokenAccount.address, + tokenMintAccount, + user, + 25 * MINOR_UNITS_PER_MAJOR_UNITS, + ); +} catch (error) { + console.log("❌ burn failed with errors:"); + throw new Error(error.message); +} console.log( - `Burn Transaction: ${getExplorerLink( + `✅ Burn Transaction: ${getExplorerLink( "transaction", transactionSignature, "devnet", @@ -321,6 +411,16 @@ console.log( ); ``` +Replace `YOUR_TOKEN_MINT_ADDRESS_HERE` with your mint token address obtained from the previous chapter. + +Run the script using `npx esrun burn-tokens.ts`. You should see: + +```bash +✅ Burn Transaction: https://explorer.solana.com/tx/P9JAK7bSAhycccGunDEThgt12QFiqMr9oexenEmRXXKoXsLKr2x64k9BWNppjTxFeVMUYjBEncRKe3gZsyd29JY?cluster=devnet +``` + +Open the explorer link, you will see the burn information. + Well done! You've now From bee0da2b8871672d9303c9a4a21aef1a08b3c3ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B9=9D=E5=8D=81=E6=9B=BF=20=E9=99=88=E4=B8=BD=E8=99=B9?= Date: Sun, 25 Aug 2024 14:14:58 +0800 Subject: [PATCH 08/14] prettier:fix --- .../tokens-and-nfts/token-program-advanced.md | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/content/courses/tokens-and-nfts/token-program-advanced.md b/content/courses/tokens-and-nfts/token-program-advanced.md index 815a26391..2c0a4a385 100644 --- a/content/courses/tokens-and-nfts/token-program-advanced.md +++ b/content/courses/tokens-and-nfts/token-program-advanced.md @@ -4,14 +4,16 @@ objectives: - Understand why and how to burn tokens - Allow a token holder to allocate a limited amount of tokens to another account to spend or burn using token delegation. -description: "How to burn tokens, and approve/revoke token delegations on Solana." +description: + "How to burn tokens, and approve/revoke token delegations on Solana." --- ### Lesson Finally, we'll cover burning tokens, and delegation. You may not use these in your own application, so if you're really excited about NFTs, feel free to skip -to [creating NFTs with Metaplex](/content/courses/tokens-and-nfts/nfts-with-metaplex)! +to +[creating NFTs with Metaplex](/content/courses/tokens-and-nfts/nfts-with-metaplex)! ### Burn Tokens @@ -173,12 +175,13 @@ This lab extends the lab from the Let's use `approve` from `spl-token` to authorize a delegate to transfer or burn up to 50 tokens from our token account. -Just like [Transferring Tokens](/content/courses/tokens-and-nfts/token-program) in the -previous lab, you can +Just like [Transferring Tokens](/content/courses/tokens-and-nfts/token-program) +in the previous lab, you can [add a second account on devnet](/content/courses/intro-to-solana/intro-to-cryptography) if you like, or find a friend who has a devnet account! -Create a new file `delegate-tokens.ts`. We use the system program account as the delegate here for demonstration. +Create a new file `delegate-tokens.ts`. We use the system program account as the +delegate here for demonstration. ```typescript import "dotenv/config"; @@ -248,7 +251,8 @@ console.log( ); ``` -Replace `YOUR_TOKEN_MINT_ADDRESS_HERE` with your mint token address obtained from the previous chapter. +Replace `YOUR_TOKEN_MINT_ADDRESS_HERE` with your mint token address obtained +from the previous chapter. Run the script using `npx esrun delegate-tokens.ts`. You should see: @@ -262,8 +266,8 @@ Open the explorer link, you will see the ‌approval information. Lets revoke the `delegate` using the `spl-token` library's `revoke` function. -Revoke will set delegate for the associated token account to null and reset the delegated -amount to 0. +Revoke will set delegate for the associated token account to null and reset the +delegated amount to 0. Create a new file `revoke-approve-tokens.ts`. @@ -327,7 +331,8 @@ console.log( ); ``` -Replace `YOUR_TOKEN_MINT_ADDRESS_HERE` with your mint token address obtained from the previous chapter. +Replace `YOUR_TOKEN_MINT_ADDRESS_HERE` with your mint token address obtained +from the previous chapter. Run the script using `npx esrun revoke-approve-tokens.ts`. You should see: @@ -411,7 +416,8 @@ console.log( ); ``` -Replace `YOUR_TOKEN_MINT_ADDRESS_HERE` with your mint token address obtained from the previous chapter. +Replace `YOUR_TOKEN_MINT_ADDRESS_HERE` with your mint token address obtained +from the previous chapter. Run the script using `npx esrun burn-tokens.ts`. You should see: From 76294b1be119a7fe51e65ac4df5a13a9e387fdc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B9=9D=E5=8D=81=E6=9B=BF=20=E9=99=88=E4=B8=BD=E8=99=B9?= Date: Mon, 26 Aug 2024 21:46:12 +0800 Subject: [PATCH 09/14] change "mint" to "token mint account" add a typescript code example for using an account on devnet while calling "initializeKeypair" in the section [2. Run validator node] add a typescript code example for importing our new function in the section [3. Create a mint with close authority] change "const mintInfo" to "let mintInfo" because "mintInfo" is used again in "CLOSE MINT". --- .../courses/token-extensions/close-mint.md | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/content/courses/token-extensions/close-mint.md b/content/courses/token-extensions/close-mint.md index f2751b852..53ea110bb 100644 --- a/content/courses/token-extensions/close-mint.md +++ b/content/courses/token-extensions/close-mint.md @@ -198,10 +198,10 @@ await setAuthority( ## Lab -In this lab, we'll create a mint with the `close mint` extension. We will then -mint some of the tokens and see what happens when we try to close it with a -non-zero supply (hint, the close transaction will fail). Lastly, we will burn -the supply and close the account. +In this lab, we'll create a token mint account with the `close mint` extension. +We will then mint some of the tokens and see what happens when we try to close +it with a non-zero supply (hint, the close transaction will fail). Lastly, we +will burn the supply and close the account. ### 1. Getting Started @@ -304,6 +304,14 @@ running `solana config get` in your terminal. And then go to address. You can get your address from running `solana address` in your terminal. +For example, assuming `keypairPath` is `/home/.config/solana/id.json` + +```typescript +const payer = initializeKeypair(connection, { + keypairPath: "/home/.config/solana/id.json", +}); +``` + ### 3. Create a mint with close authority Let's create a closable mint by creating the function `createClosableMint` in a @@ -399,7 +407,13 @@ export async function createClosableMint( ``` Now let's call this function in `src/index.ts`. First you'll need to import our -new function. Then paste the following under the right comment section: +new function by uncommenting the 3rd line. + +```ts +import { createClosableMint } from "./create-mint"; +``` + +Then paste the following under the right comment section: ```ts // CREATE A MINT WITH CLOSE AUTHORITY @@ -470,7 +484,7 @@ Underneath the minting functions, add the following code block: /** * Get mint information to verify supply */ -const mintInfo = await getMint( +let mintInfo = await getMint( connection, mintKeypair.publicKey, "finalized", @@ -591,7 +605,7 @@ Putting this all together we get: ```ts // CLOSE MINT -const mintInfo = await getMint( +mintInfo = await getMint( connection, mintKeypair.publicKey, "finalized", From d80ab057edd6fe580b22138044083a94d9eec8a5 Mon Sep 17 00:00:00 2001 From: wuuer Date: Tue, 27 Aug 2024 11:07:59 +0800 Subject: [PATCH 10/14] Update content/courses/tokens-and-nfts/token-program-advanced.md Co-authored-by: Mike MacCana --- content/courses/tokens-and-nfts/token-program-advanced.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/courses/tokens-and-nfts/token-program-advanced.md b/content/courses/tokens-and-nfts/token-program-advanced.md index 2c0a4a385..8842fb286 100644 --- a/content/courses/tokens-and-nfts/token-program-advanced.md +++ b/content/courses/tokens-and-nfts/token-program-advanced.md @@ -425,7 +425,7 @@ Run the script using `npx esrun burn-tokens.ts`. You should see: ✅ Burn Transaction: https://explorer.solana.com/tx/P9JAK7bSAhycccGunDEThgt12QFiqMr9oexenEmRXXKoXsLKr2x64k9BWNppjTxFeVMUYjBEncRKe3gZsyd29JY?cluster=devnet ``` -Open the explorer link, you will see the burn information. +Open the Explorer link, you will see the burn information. Well done! You've now From 6f655d671dbf7b47124fc0b9909870f321bb221b Mon Sep 17 00:00:00 2001 From: wuuer Date: Tue, 27 Aug 2024 11:08:42 +0800 Subject: [PATCH 11/14] Update content/courses/tokens-and-nfts/token-program.md Co-authored-by: Mike MacCana --- content/courses/tokens-and-nfts/token-program.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/courses/tokens-and-nfts/token-program.md b/content/courses/tokens-and-nfts/token-program.md index def05b909..d7aaf554d 100644 --- a/content/courses/tokens-and-nfts/token-program.md +++ b/content/courses/tokens-and-nfts/token-program.md @@ -734,7 +734,7 @@ token account. Recall that we set the `user` as the `mintAuthority` for the `mint` we created. Create an empty file called `mint-tokens.ts`. Then uses the `spl-token` function -`mintTo` to mint tokens. Remember to substitute in your token mint address and +`mintTo()` to mint tokens. Remember to substitute in your token mint address and token account address below! ```typescript From 30d0f453390fcb9a8834ba96551ded4a59c9d4bf Mon Sep 17 00:00:00 2001 From: wuuer Date: Tue, 27 Aug 2024 11:09:17 +0800 Subject: [PATCH 12/14] Update content/courses/tokens-and-nfts/token-program-advanced.md Co-authored-by: Mike MacCana --- content/courses/tokens-and-nfts/token-program-advanced.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/courses/tokens-and-nfts/token-program-advanced.md b/content/courses/tokens-and-nfts/token-program-advanced.md index 8842fb286..599180973 100644 --- a/content/courses/tokens-and-nfts/token-program-advanced.md +++ b/content/courses/tokens-and-nfts/token-program-advanced.md @@ -13,7 +13,7 @@ description: Finally, we'll cover burning tokens, and delegation. You may not use these in your own application, so if you're really excited about NFTs, feel free to skip to -[creating NFTs with Metaplex](/content/courses/tokens-and-nfts/nfts-with-metaplex)! +[creating NFTs with Metaplex](/content/courses/tokens-and-nfts/nfts-with-metaplex.md)! ### Burn Tokens From 9c42ab69852058c64362b115de7650cb917051ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B9=9D=E5=8D=81=E6=9B=BF=20=E9=99=88=E4=B8=BD=E8=99=B9?= Date: Tue, 27 Aug 2024 11:30:11 +0800 Subject: [PATCH 13/14] Change "explorer" to "Explorer" add "()" to "mintTo" add "md" extension to link --- .../tokens-and-nfts/token-program-advanced.md | 17 +++++++++-------- .../courses/tokens-and-nfts/token-program.md | 10 +++++----- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/content/courses/tokens-and-nfts/token-program-advanced.md b/content/courses/tokens-and-nfts/token-program-advanced.md index 2c0a4a385..88f9715fc 100644 --- a/content/courses/tokens-and-nfts/token-program-advanced.md +++ b/content/courses/tokens-and-nfts/token-program-advanced.md @@ -13,7 +13,7 @@ description: Finally, we'll cover burning tokens, and delegation. You may not use these in your own application, so if you're really excited about NFTs, feel free to skip to -[creating NFTs with Metaplex](/content/courses/tokens-and-nfts/nfts-with-metaplex)! +[creating NFTs with Metaplex](/content/courses/tokens-and-nfts/nfts-with-metaplex.md)! ### Burn Tokens @@ -168,16 +168,17 @@ async function buildRevokeTransaction( ### Lab This lab extends the lab from the -[previous chapter](/content/courses/tokens-and-nfts/token-program). +[previous chapter](/content/courses/tokens-and-nfts/token-program.md). #### 1. Delegating tokens Let's use `approve` from `spl-token` to authorize a delegate to transfer or burn up to 50 tokens from our token account. -Just like [Transferring Tokens](/content/courses/tokens-and-nfts/token-program) -in the previous lab, you can -[add a second account on devnet](/content/courses/intro-to-solana/intro-to-cryptography) +Just like +[Transferring Tokens](/content/courses/tokens-and-nfts/token-program.md) in the +previous lab, you can +[add a second account on devnet](/content/courses/intro-to-solana/intro-to-cryptography.md) if you like, or find a friend who has a devnet account! Create a new file `delegate-tokens.ts`. We use the system program account as the @@ -260,7 +261,7 @@ Run the script using `npx esrun delegate-tokens.ts`. You should see: ✅ Approve Delegate Transaction: https://explorer.solana.com/tx/3sBr62x2VMaoJ4Z3SQMy6ZPzQKaa5Bs9ni9dgwwZZ5qEViKh1gQznCgH489h6pgfruMmqPbc2GgminTPK4UXRRZd?cluster=devnet ``` -Open the explorer link, you will see the ‌approval information. +Open the Explorer link, you will see the ‌approval information. #### 2. Revoke Delegate @@ -340,7 +341,7 @@ Run the script using `npx esrun revoke-approve-tokens.ts`. You should see: ✅ Revoke Delegate Transaction: https://explorer.solana.com/tx/5UboxLULHT3pPznBxThfQMc73NNjYNLmvqrB3JVVXPwWxUFWA49WG58sFQP8B5rv4FXxxZm3mur319YNiyYxYgBd?cluster=devnet ``` -Open the explorer link, you will see the revoke information. +Open the Explorer link, you will see the revoke information. #### 3. Burn Tokens @@ -425,7 +426,7 @@ Run the script using `npx esrun burn-tokens.ts`. You should see: ✅ Burn Transaction: https://explorer.solana.com/tx/P9JAK7bSAhycccGunDEThgt12QFiqMr9oexenEmRXXKoXsLKr2x64k9BWNppjTxFeVMUYjBEncRKe3gZsyd29JY?cluster=devnet ``` -Open the explorer link, you will see the burn information. +Open the Explorer link, you will see the burn information. Well done! You've now diff --git a/content/courses/tokens-and-nfts/token-program.md b/content/courses/tokens-and-nfts/token-program.md index def05b909..77709c799 100644 --- a/content/courses/tokens-and-nfts/token-program.md +++ b/content/courses/tokens-and-nfts/token-program.md @@ -28,8 +28,8 @@ description: - Creating Token Mints and Token Accounts requires allocating **rent** in SOL. The rent for a Token Account can be refunded when the account is closed. Additionally, tokens created with the - [Token Extensions Program](/content/courses/token-extensions/close-mint) can - also close Token Mints. + [Token Extensions Program](/content/courses/token-extensions/close-mint.md) + can also close Token Mints. ### Lesson @@ -461,7 +461,7 @@ We’re going to use the Token Token Program to create a Token Mint, create an Associated Token Account, mint tokens, transfer tokens, and burn tokens. Assuming you already have a `.env` file with a `SECRET_KEY` setup per -[Cryptography fundamentals](/content/courses/intro-to-solana/intro-to-cryptography). +[Cryptography fundamentals](/content/courses/intro-to-solana/intro-to-cryptography.md). ```bash npm i @solana/web3.js @solana/spl-token @solana-developers/helpers esrun @@ -734,7 +734,7 @@ token account. Recall that we set the `user` as the `mintAuthority` for the `mint` we created. Create an empty file called `mint-tokens.ts`. Then uses the `spl-token` function -`mintTo` to mint tokens. Remember to substitute in your token mint address and +`mintTo()` to mint tokens. Remember to substitute in your token mint address and token account address below! ```typescript @@ -792,7 +792,7 @@ account! Next, let's transfer some of the tokens we just minted using the `spl-token` library's `transfer` function. You can -[add a second account on devnet](/content/courses/intro-to-solana/intro-to-cryptography) +[add a second account on devnet](/content/courses/intro-to-solana/intro-to-cryptography.md) if you like, or find a friend who has a devnet account and send them your token! As you saw in Explorer, the tokens currently reside in an Associated Token From f6da84f5dc75f62acb2cb0e36d3b1aecdb61d71e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B9=9D=E5=8D=81=E6=9B=BF=20=E9=99=88=E4=B8=BD=E8=99=B9?= Date: Tue, 27 Aug 2024 12:12:24 +0800 Subject: [PATCH 14/14] delete unnessary try/catch as misunderstanding of CONTINUTING.md --- .../tokens-and-nfts/token-program-advanced.md | 128 +++++-------- .../courses/tokens-and-nfts/token-program.md | 175 +++++++----------- 2 files changed, 112 insertions(+), 191 deletions(-) diff --git a/content/courses/tokens-and-nfts/token-program-advanced.md b/content/courses/tokens-and-nfts/token-program-advanced.md index 88f9715fc..aea2a8649 100644 --- a/content/courses/tokens-and-nfts/token-program-advanced.md +++ b/content/courses/tokens-and-nfts/token-program-advanced.md @@ -211,37 +211,25 @@ const delegate = new PublicKey("11111111111111111111111111111111"); // Substitute in your token mint account const tokenMintAccount = new PublicKey("YOUR_TOKEN_MINT_ADDRESS_HERE"); -let sourceTokenAccount: Account; -try { - // Get or create the source and destination token accounts to store this token - sourceTokenAccount = await getOrCreateAssociatedTokenAccount( - connection, - user, - tokenMintAccount, - user.publicKey, - ); -} catch (error) { - console.log("❌ getOrCreateAssociatedTokenAccount failed with errors:"); - throw new Error(error.message); -} +// Get or create the source and destination token accounts to store this token +const sourceTokenAccount = await getOrCreateAssociatedTokenAccount( + connection, + user, + tokenMintAccount, + user.publicKey, +); // Our token has two decimal places const MINOR_UNITS_PER_MAJOR_UNITS = Math.pow(10, 2); -let approveTransactionSignature: string; -try { - approveTransactionSignature = await approve( - connection, - user, - sourceTokenAccount.address, - delegate, - user.publicKey, - 50 * MINOR_UNITS_PER_MAJOR_UNITS, - ); -} catch (error) { - console.log("❌ approve failed with errors:"); - throw new Error(error.message); -} +const approveTransactionSignature = await approve( + connection, + user, + sourceTokenAccount.address, + delegate, + user.publicKey, + 50 * MINOR_UNITS_PER_MAJOR_UNITS, +); console.log( `✅ Approve Delegate Transaction: ${getExplorerLink( @@ -279,11 +267,7 @@ import { getKeypairFromEnvironment, } from "@solana-developers/helpers"; import { Connection, PublicKey, clusterApiUrl } from "@solana/web3.js"; -import { - Account, - getOrCreateAssociatedTokenAccount, - revoke, -} from "@solana/spl-token"; +import { getOrCreateAssociatedTokenAccount, revoke } from "@solana/spl-token"; const connection = new Connection(clusterApiUrl("devnet")); @@ -296,32 +280,20 @@ console.log( // Substitute in your token mint account const tokenMintAccount = new PublicKey("YOUR_TOKEN_MINT_ADDRESS_HERE"); -let sourceTokenAccount: Account; -try { - // Get or create the source and destination token accounts to store this token - sourceTokenAccount = await getOrCreateAssociatedTokenAccount( - connection, - user, - tokenMintAccount, - user.publicKey, - ); -} catch (error) { - console.log("❌ getOrCreateAssociatedTokenAccount failed with errors:"); - throw new Error(error.message); -} +// Get or create the source and destination token accounts to store this token +const sourceTokenAccount = await getOrCreateAssociatedTokenAccount( + connection, + user, + tokenMintAccount, + user.publicKey, +); -let revokeTransactionSignature: String; -try { - revokeTransactionSignature = await revoke( - connection, - user, - sourceTokenAccount.address, - user.publicKey, - ); -} catch (error) { - console.log("❌ revoke failed with errors:"); - throw new Error(error.message); -} +const revokeTransactionSignature = await revoke( + connection, + user, + sourceTokenAccount.address, + user.publicKey, +); console.log( `✅ Revoke Delegate Transaction: ${getExplorerLink( @@ -376,37 +348,25 @@ console.log( // Substitute in your token mint account const tokenMintAccount = new PublicKey("YOUR_TOKEN_MINT_ADDRESS_HERE"); -let sourceTokenAccount: Account; -try { - // Get or create the source and destination token accounts to store this token - sourceTokenAccount = await getOrCreateAssociatedTokenAccount( - connection, - user, - tokenMintAccount, - user.publicKey, - ); -} catch (error) { - console.log("❌ getOrCreateAssociatedTokenAccount failed with errors:"); - throw new Error(error.message); -} +// Get or create the source and destination token accounts to store this token +const sourceTokenAccount = await getOrCreateAssociatedTokenAccount( + connection, + user, + tokenMintAccount, + user.publicKey, +); // Our token has two decimal places const MINOR_UNITS_PER_MAJOR_UNITS = Math.pow(10, 2); -let transactionSignature: string; -try { - transactionSignature = await burn( - connection, - user, - sourceTokenAccount.address, - tokenMintAccount, - user, - 25 * MINOR_UNITS_PER_MAJOR_UNITS, - ); -} catch (error) { - console.log("❌ burn failed with errors:"); - throw new Error(error.message); -} +const transactionSignature = await burn( + connection, + user, + sourceTokenAccount.address, + tokenMintAccount, + user, + 25 * MINOR_UNITS_PER_MAJOR_UNITS, +); console.log( `✅ Burn Transaction: ${getExplorerLink( diff --git a/content/courses/tokens-and-nfts/token-program.md b/content/courses/tokens-and-nfts/token-program.md index 77709c799..b21a3fdd5 100644 --- a/content/courses/tokens-and-nfts/token-program.md +++ b/content/courses/tokens-and-nfts/token-program.md @@ -497,16 +497,11 @@ console.log( // SystemProgram.createAccount() // token.createInitializeMintInstruction() // See https://www.soldev.app/course/token-program -try { - const tokenMint = await createMint(connection, user, user.publicKey, null, 2); +const tokenMint = await createMint(connection, user, user.publicKey, null, 2); - const link = getExplorerLink("address", tokenMint.toString(), "devnet"); +const link = getExplorerLink("address", tokenMint.toString(), "devnet"); - console.log(`✅ Finished! Created token mint: ${link}`); -} catch (error) { - console.log("❌ createMint failed with errors: "); - console.log(error.message); -} +console.log(`✅ Finished! Created token mint: ${link}`); ``` Run the script using `npx esrun create-token-mint.ts`. You should see @@ -610,32 +605,27 @@ const createMetadataAccountInstruction = transaction.add(createMetadataAccountInstruction); -try { - const transactionSignature = await sendAndConfirmTransaction( - connection, - transaction, - [user], - ); +const transactionSignature = await sendAndConfirmTransaction( + connection, + transaction, + [user], +); - const transactionLink = getExplorerLink( - "transaction", - transactionSignature, - "devnet", - ); +const transactionLink = getExplorerLink( + "transaction", + transactionSignature, + "devnet", +); - console.log(`✅ Transaction confirmed, explorer link is: ${transactionLink}`); +console.log(`✅ Transaction confirmed, explorer link is: ${transactionLink}`); - const tokenMintLink = getExplorerLink( - "address", - tokenMintAccount.toString(), - "devnet", - ); +const tokenMintLink = getExplorerLink( + "address", + tokenMintAccount.toString(), + "devnet", +); - console.log(`✅ Look at the token mint again: ${tokenMintLink}`); -} catch (error) { - console.log("❌ Make token metadata failed with errors:"); - console.log(error.message); -} +console.log(`✅ Look at the token mint again: ${tokenMintLink}`); ``` Replace `YOUR_TOKEN_MINT_ADDRESS_HERE` with your address of the mint and Run the @@ -692,27 +682,22 @@ const tokenMintAccount = new PublicKey("YOUR_TOKEN_MINT"); // const recipient = new PublicKey("SOMEONE_ELSES_DEVNET_ADDRESS"); const recipient = user.publicKey; -try { - const tokenAccount = await getOrCreateAssociatedTokenAccount( - connection, - user, - tokenMintAccount, - recipient, - ); +const tokenAccount = await getOrCreateAssociatedTokenAccount( + connection, + user, + tokenMintAccount, + recipient, +); - console.log(`Token Account: ${tokenAccount.address.toBase58()}`); +console.log(`Token Account: ${tokenAccount.address.toBase58()}`); - const link = getExplorerLink( - "address", - tokenAccount.address.toBase58(), - "devnet", - ); +const link = getExplorerLink( + "address", + tokenAccount.address.toBase58(), + "devnet", +); - console.log(`✅ Created token Account: ${link}`); -} catch (error) { - console.log("❌ Create token account failed with errors:"); - console.log(error.message); -} +console.log(`✅ Created token Account: ${link}`); ``` Run the script using `npx esrun create-token-account.ts`. You should see: @@ -760,23 +745,18 @@ const recipientAssociatedTokenAccount = new PublicKey( "RECIPIENT_TOKEN_ACCOUNT", ); -try { - const transactionSignature = await mintTo( - connection, - user, - tokenMintAccount, - recipientAssociatedTokenAccount, - user, - 10 * MINOR_UNITS_PER_MAJOR_UNITS, - ); +const transactionSignature = await mintTo( + connection, + user, + tokenMintAccount, + recipientAssociatedTokenAccount, + user, + 10 * MINOR_UNITS_PER_MAJOR_UNITS, +); - const link = getExplorerLink("transaction", transactionSignature, "devnet"); +const link = getExplorerLink("transaction", transactionSignature, "devnet"); - console.log(`✅ Success! Mint Token Transaction: ${link}`); -} catch (error) { - console.log("❌ mintToken failed with errors: "); - console.log(error.message); -} +console.log(`✅ Success! Mint Token Transaction: ${link}`); ``` Run the script using `npx esrun mint-tokens.ts`. You should see: @@ -833,54 +813,35 @@ const MINOR_UNITS_PER_MAJOR_UNITS = Math.pow(10, 2); console.log(`💸 Attempting to send 1 token to ${recipient.toBase58()}...`); -let sourceTokenAccount: { address: PublicKey }; -try { - // Get or create the source token account to store this token - const sourceTokenAccount = await getOrCreateAssociatedTokenAccount( - connection, - sender, - tokenMintAccount, - sender.publicKey, - ); -} catch (error) { - console.log("❌ Get or create the source token account failed with errors."); - throw new Error(error.message); -} +// Get or create the source token account to store this token +const sourceTokenAccount = await getOrCreateAssociatedTokenAccount( + connection, + sender, + tokenMintAccount, + sender.publicKey, +); -let destinationTokenAccount: { address: PublicKey }; -try { - // Get or create the destination token account to store this token - const destinationTokenAccount = await getOrCreateAssociatedTokenAccount( - connection, - sender, - tokenMintAccount, - recipient, - ); -} catch (error) { - console.log( - "❌ Get or create the destination token account failed with errors.", - ); - throw new Error(error.message); -} +// Get or create the destination token account to store this token +const destinationTokenAccount = await getOrCreateAssociatedTokenAccount( + connection, + sender, + tokenMintAccount, + recipient, +); -try { - // Transfer the tokens - const signature = await transfer( - connection, - sender, - sourceTokenAccount.address, - destinationTokenAccount.address, - sender, - 1 * MINOR_UNITS_PER_MAJOR_UNITS, - ); +// Transfer the tokens +const signature = await transfer( + connection, + sender, + sourceTokenAccount.address, + destinationTokenAccount.address, + sender, + 1 * MINOR_UNITS_PER_MAJOR_UNITS, +); - const explorerLink = getExplorerLink("transaction", signature, "devnet"); +const explorerLink = getExplorerLink("transaction", signature, "devnet"); - console.log(`✅ Transaction confirmed, explorer link is: ${explorerLink}`); -} catch (error) { - console.log("❌ transfer tokens failed with errors: "); - console.log(error.message); -} +console.log(`✅ Transaction confirmed, explorer link is: ${explorerLink}`); ``` Run the script using `npx esrun transfer-tokens.ts`. You should see: