diff --git a/content/courses/tokens-and-nfts/token-program-advanced.md b/content/courses/tokens-and-nfts/token-program-advanced.md index 16c827c38..4ac7d3084 100644 --- a/content/courses/tokens-and-nfts/token-program-advanced.md +++ b/content/courses/tokens-and-nfts/token-program-advanced.md @@ -51,7 +51,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( @@ -105,7 +105,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( @@ -113,7 +113,7 @@ async function buildApproveTransaction( delegate: PublicKey, owner: PublicKey, amount: number, -): Promise { +): Promise { const transaction = new Transaction().add( createApproveInstruction(account, delegate, owner, amount), ); @@ -150,13 +150,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), ); @@ -183,7 +183,7 @@ if you like, or find a friend who has a devnet account! Create a new file `delegate-tokens.ts` -```typescript +```typescript filename="delegate-tokens.ts" import "dotenv/config"; import { getExplorerLink, @@ -210,59 +210,105 @@ const delegate = new PublicKey("YOUR_DELEGATE_HERE"); // 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, -); + // 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); + // 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, -); + const approveTransactionSignature = await approve( + connection, + user, + sourceTokenAccount.address, + delegate, + user.publicKey, + 50 * MINOR_UNITS_PER_MAJOR_UNITS, + ); -console.log( - `Approve Delegate Transaction: ${getExplorerLink( - "transaction", - approveTransactionSignature, - "devnet", - )}`, -); + console.log( + ✅`Approve Delegate Transaction: ${getExplorerLink( + "transaction", + approveTransactionSignature, + "devnet", + )}`, + ); +``` + +Run the script using `npx esrun delegate-tokens.ts`. You should see: + +```bash +✅ Approve Delegate Transaction: https://explorer.solana.com/tx/31zsmGuX3NM1ip88mowaHT8B3gKDET3b6QnWSRcs2oWXeu9hgGoJunKmbTXZPF1cjpk2aaymf1wuBn58gAp5Q2h?cluster=devnet ``` #### 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 -amount to 0. +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-token.ts` -```typescript -const revokeTransactionSignature = await revoke( - connection, - user, - sourceTokenAccount.address, - user.publicKey, -); +```typescript filename="revoke-token.ts" +import "dotenv/config"; +import { + getExplorerLink, + getKeypairFromEnvironment, +} from "@solana-developers/helpers"; +import { Connection, PublicKey, clusterApiUrl } from "@solana/web3.js"; +import { + approve, + getOrCreateAssociatedTokenAccount, + revoke, +} from "@solana/spl-token"; + +const connection = new Connection(clusterApiUrl("devnet")); + +const user = getKeypairFromEnvironment("SECRET_KEY"); console.log( - `Revoke Delegate Transaction: ${getExplorerLink( - "transaction", - revokeTransactionSignature, - "devnet", - )}`, + `🔑 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"); + +// 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, + ); + + const revokeTransactionSignature = await revoke( + connection, + user, + sourceTokenAccount.address, + user.publicKey, + ); + + console.log( + ✅`Revoke Delegate Transaction: ${getExplorerLink( + "transaction", + revokeTransactionSignature, + "devnet", + )}`, + ); +``` + +Run the script using `npx esrun revoke-tokens.ts`. You should see: + +```bash +✅ Revoke Delegate Transaction: https://explorer.solana.com/tx/2jFgvXeF19nSFzjGLVoKo8vtGBp7xan3UZkRaGEpXHCuhKYerEiaE6a4oWVvJXjjYLNmt76XSx5U23J89moma31H?cluster=devnet ``` #### 3. Burn Tokens @@ -272,9 +318,9 @@ 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 +```typescript filename="burn-tokens.ts" import "dotenv/config"; import { getExplorerLink, @@ -295,32 +341,38 @@ console.log( 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, -); + 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); + // 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, -); + const transactionSignature = await burn( + connection, + user, + sourceTokenAccount.address, + tokenMintAccount, + user, + 25 * MINOR_UNITS_PER_MAJOR_UNITS, + ); -console.log( - `Burn Transaction: ${getExplorerLink( - "transaction", - transactionSignature, - "devnet", - )}`, -); + console.log( + ✅`Burn Transaction: ${getExplorerLink( + "transaction", + transactionSignature, + "devnet", + )}`, + ); +``` + +Run the script using `npx esrun burn-tokens.ts`. You should see: + +```bash +✅ Burn Transaction: https://explorer.solana.com/tx/29jRrkMsnibmW5tNaxv38bZDe2QioZMeAurPdMvdZiqVA6biwYFcn5wGFgm6YC7bAwBufZFhXz4kh9Avsh1Ggn3u?cluster=devnet ``` Well done! You've now