From 6f68cad11c5a2561dae578a8a3ea63d778c7db3f Mon Sep 17 00:00:00 2001 From: Swenschaeferjohann Date: Mon, 22 Dec 2025 11:53:32 +0100 Subject: [PATCH 1/9] fix quickstart, bump alphas, refactor --- .env.example | 1 + .gitignore | 11 +- .prettierrc | 3 + README.md | 40 ++-- cookbook/.env.example | 2 - cookbook/actions/compress-batch.ts | 109 +++++----- cookbook/actions/compress.ts | 106 ++++----- cookbook/actions/create-ata.ts | 73 +++---- cookbook/actions/create-mint.ts | 88 ++++---- .../actions/decompress-with-token-pool.ts | 118 +++++----- cookbook/actions/decompress.ts | 96 ++++----- cookbook/actions/delegate-approve.ts | 110 +++++----- cookbook/actions/delegate-revoke.ts | 110 +++++----- cookbook/actions/load-ata.ts | 94 ++++---- cookbook/actions/merge-token-accounts.ts | 136 ++++++------ cookbook/actions/mint-to.ts | 101 +++++---- cookbook/actions/transfer-interface.ts | 111 +++++----- cookbook/actions/unwrap.ts | 97 ++++----- cookbook/actions/wrap.ts | 114 +++++----- cookbook/instructions/create-ata.ts | 107 ++++----- cookbook/instructions/create-mint.ts | 140 ++++++------ cookbook/instructions/load-ata.ts | 124 +++++------ cookbook/instructions/mint-to.ts | 147 ++++++------- cookbook/instructions/transfer-interface.ts | 129 +++++------ cookbook/instructions/unwrap.ts | 154 ++++++------- cookbook/instructions/wrap.ts | 158 +++++++------- cookbook/package.json | 78 +++---- cookbook/tsconfig.json | 26 +-- devnet-quickstart/.env.example | 2 - devnet-quickstart/.gitignore | 4 - devnet-quickstart/index.ts | 120 ++++++----- devnet-quickstart/package.json | 32 +-- devnet-quickstart/tsconfig.json | 26 +-- package.json | 14 ++ toolkits/payments-and-wallets/README.md | 37 ++-- .../comparison-spl-light.md | 203 +++++++++--------- toolkits/payments-and-wallets/get-balance.ts | 87 ++++---- toolkits/payments-and-wallets/get-history.ts | 126 ++++++----- toolkits/payments-and-wallets/package.json | 43 ++-- .../payments-and-wallets/send-and-receive.ts | 163 +++++++------- toolkits/payments-and-wallets/tsconfig.json | 26 +-- .../payments-and-wallets/unwrap-to-spl.ts | 71 ------ toolkits/payments-and-wallets/unwrap.ts | 67 ++++++ .../payments-and-wallets/wrap-from-spl.ts | 80 ------- toolkits/payments-and-wallets/wrap.ts | 81 +++++++ toolkits/streaming-tokens/README.mdx | 2 +- toolkits/streaming-tokens/src/main.rs | 2 +- 47 files changed, 1915 insertions(+), 1854 deletions(-) create mode 100644 .env.example create mode 100644 .prettierrc delete mode 100644 cookbook/.env.example delete mode 100644 devnet-quickstart/.env.example delete mode 100644 devnet-quickstart/.gitignore create mode 100644 package.json delete mode 100644 toolkits/payments-and-wallets/unwrap-to-spl.ts create mode 100644 toolkits/payments-and-wallets/unwrap.ts delete mode 100644 toolkits/payments-and-wallets/wrap-from-spl.ts create mode 100644 toolkits/payments-and-wallets/wrap.ts diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..5c6ddac --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +API_KEY=YOUR_KEY diff --git a/.gitignore b/.gitignore index 941faf8..d78cbc9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ -node_modules/ -dist/ -.env -pnpm-lock.yaml -package-lock.json +**/node_modules/ +**/dist/ +**/.env +**/pnpm-lock.yaml +**/package-lock.json +**/*.json.bak diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..0a02bce --- /dev/null +++ b/.prettierrc @@ -0,0 +1,3 @@ +{ + "tabWidth": 4 +} diff --git a/README.md b/README.md index 6e03325..1036aa7 100644 --- a/README.md +++ b/README.md @@ -34,29 +34,29 @@ End-to-end example: create a mint, token account, mint tokens, and transfer on d ## Cookbook -Step-by-step recipes for light-token on localnet. +Step-by-step recipes for light-token on Devnet/Localnet. ### [Actions](cookbook/actions/) -- **[create-mint](cookbook/actions/create-mint.ts)** - Create a new light-token mint -- **[create-ata](cookbook/actions/create-ata.ts)** - Create an associated light-token account -- **[load-ata](cookbook/actions/load-ata.ts)** - Load a cold token account (compressed) to hot balance (light-token ata) -- **[mint-to](cookbook/actions/mint-to.ts)** - Mint tokens to a light-account -- **[transfer-interface](cookbook/actions/transfer-interface.ts)** - Transfer tokens between light-token, T22, and SPL token accounts. -- **[wrap](cookbook/actions/wrap.ts)** - Wrap SPL to light-token -- **[unwrap](cookbook/actions/unwrap.ts)** - Unwrap light-token to SPL for off-ramps and legacy integrations +- **[create-mint](cookbook/actions/create-mint.ts)** - Create a new light-token mint +- **[create-ata](cookbook/actions/create-ata.ts)** - Create an associated light-token account +- **[load-ata](cookbook/actions/load-ata.ts)** - Load a cold token account (compressed) to hot balance (light-token ata) +- **[mint-to](cookbook/actions/mint-to.ts)** - Mint tokens to a light-account +- **[transfer-interface](cookbook/actions/transfer-interface.ts)** - Transfer tokens between light-token, T22, and SPL token accounts. +- **[wrap](cookbook/actions/wrap.ts)** - Wrap SPL to light-token +- **[unwrap](cookbook/actions/unwrap.ts)** - Unwrap light-token to SPL for off-ramps and legacy integrations ### [Instructions](cookbook/instructions/) Low-level instruction builders: -- **[create-mint](cookbook/instructions/create-mint.ts)** - Build create mint instruction -- **[create-ata](cookbook/instructions/create-ata.ts)** - Build create ATA instruction -- **[load-ata](cookbook/instructions/load-ata.ts)** - Build load ATA instruction -- **[mint-to](cookbook/instructions/mint-to.ts)** - Build mint-to instruction -- **[transfer-interface](cookbook/instructions/transfer-interface.ts)** - Build transfer interface instruction for transfers between light-token, T22, and SPL token accounts. -- **[wrap](cookbook/instructions/wrap.ts)** - Build wrap instruction -- **[unwrap](cookbook/instructions/unwrap.ts)** - Build unwrap instruction for off-ramps and legacy integrations +- **[create-mint](cookbook/instructions/create-mint.ts)** - Build create mint instruction +- **[create-ata](cookbook/instructions/create-ata.ts)** - Build create ATA instruction +- **[load-ata](cookbook/instructions/load-ata.ts)** - Build load ATA instruction +- **[mint-to](cookbook/instructions/mint-to.ts)** - Build mint-to instruction +- **[transfer-interface](cookbook/instructions/transfer-interface.ts)** - Build transfer interface instruction for transfers between light-token, T22, and SPL token accounts. +- **[wrap](cookbook/instructions/wrap.ts)** - Build wrap instruction +- **[unwrap](cookbook/instructions/unwrap.ts)** - Build unwrap instruction for off-ramps and legacy integrations ## Toolkits @@ -64,11 +64,11 @@ Low-level instruction builders: Examples for wallet integrations and payment flows: -- **[get-balance](toolkits/payments-and-wallets/get-balance.ts)** - Fetch token balances for light-token accounts -- **[get-history](toolkits/payments-and-wallets/get-history.ts)** - Fetch transaction history for light-token accounts -- **[send-and-receive](toolkits/payments-and-wallets/send-and-receive.ts)** - Send and receive light-tokens using the transfer interface -- **[wrap-from-spl](toolkits/payments-and-wallets/wrap-from-spl.ts)** - Wrap SPL tokens to light-token -- **[unwrap-to-spl](toolkits/payments-and-wallets/unwrap-to-spl.ts)** - Unwrap light-token to SPL for off-ramps and legacy integrations +- **[get-balance](toolkits/payments-and-wallets/get-balance.ts)** - Fetch token balances for light-token accounts +- **[get-history](toolkits/payments-and-wallets/get-history.ts)** - Fetch transaction history for light-token accounts +- **[send-and-receive](toolkits/payments-and-wallets/send-and-receive.ts)** - Send and receive light-tokens using the transfer interface +- **[wrap](toolkits/payments-and-wallets/wrap.ts)** - Wrap SPL tokens to light-token +- **[unwrap](toolkits/payments-and-wallets/unwrap.ts)** - Unwrap light-token to SPL for off-ramps and legacy integrations ### [Streaming Tokens](toolkits/streaming-tokens/) diff --git a/cookbook/.env.example b/cookbook/.env.example deleted file mode 100644 index abc0cdb..0000000 --- a/cookbook/.env.example +++ /dev/null @@ -1,2 +0,0 @@ -HELIUS_API_KEY=your-helius-api-key-here -LIGHT_PROTOCOL_VERSION=V2 diff --git a/cookbook/actions/compress-batch.ts b/cookbook/actions/compress-batch.ts index 654a4d5..219b2bc 100644 --- a/cookbook/actions/compress-batch.ts +++ b/cookbook/actions/compress-batch.ts @@ -2,71 +2,74 @@ import "dotenv/config"; import { Keypair } from "@solana/web3.js"; import { createRpc, bn } from "@lightprotocol/stateless.js"; import { - createMint, - mintTo, - decompress, - compress, + createMint, + mintTo, + decompress, + compress, } from "@lightprotocol/compressed-token"; import { createAssociatedTokenAccount } from "@solana/spl-token"; async function main() { - // 1. Setup RPC and fund accounts - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); + // 1. Setup RPC and fund accounts + const rpc = createRpc(); + const payer = Keypair.generate(); + const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); + await rpc.confirmTransaction(airdropSig, "confirmed"); + console.log("Payer:", payer.publicKey.toBase58()); - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); + const owner = Keypair.generate(); + const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); + await rpc.confirmTransaction(airdropSig2, "confirmed"); - // 2. Create SPL mint with token pool - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair - ); - console.log("Mint:", mint.toBase58()); + // 2. Create SPL mint with token pool + const mintAuthority = Keypair.generate(); + const mintKeypair = Keypair.generate(); + const { mint } = await createMint( + rpc, + payer, + mintAuthority.publicKey, + 9, + mintKeypair, + ); + console.log("Mint:", mint.toBase58()); - // 3. Create SPL ATA and fund it - const splAta = await createAssociatedTokenAccount( - rpc, - payer, - mint, - owner.publicKey - ); - console.log("SPL ATA:", splAta.toBase58()); + // 3. Create SPL ATA and fund it + const splAta = await createAssociatedTokenAccount( + rpc, + payer, + mint, + owner.publicKey, + ); + console.log("SPL ATA:", splAta.toBase58()); - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(10000)); - await decompress(rpc, payer, mint, bn(10000), owner, splAta); - console.log("Funded SPL ATA with 10000 tokens"); + await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(10000)); + await decompress(rpc, payer, mint, bn(10000), owner, splAta); + console.log("Funded SPL ATA with 10000 tokens"); - // 4. Batch compress to multiple recipients (max 10 for V2 trees) - const recipients = Array.from({ length: 5 }, () => Keypair.generate().publicKey); - const amounts = [bn(100), bn(200), bn(300), bn(400), bn(500)]; + // 4. Batch compress to multiple recipients (max 10 for V2 trees) + const recipients = Array.from( + { length: 5 }, + () => Keypair.generate().publicKey, + ); + const amounts = [bn(100), bn(200), bn(300), bn(400), bn(500)]; - const signature = await compress( - rpc, - payer, - mint, - amounts, // array of amounts - owner, - splAta, - recipients // array of recipients (same length as amounts) - ); + const signature = await compress( + rpc, + payer, + mint, + amounts, // array of amounts + owner, + splAta, + recipients, // array of recipients (same length as amounts) + ); - console.log("Batch compressed to 5 recipients"); - console.log("Amounts:", amounts.map((a) => a.toString()).join(", ")); - console.log("Transaction:", signature); + console.log("Batch compressed to 5 recipients"); + console.log("Amounts:", amounts.map((a) => a.toString()).join(", ")); + console.log("Transaction:", signature); } main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); + console.error("Error:", err); + if (err.logs) console.error("Logs:", err.logs); + process.exit(1); }); diff --git a/cookbook/actions/compress.ts b/cookbook/actions/compress.ts index 3047502..f511689 100644 --- a/cookbook/actions/compress.ts +++ b/cookbook/actions/compress.ts @@ -2,71 +2,71 @@ import "dotenv/config"; import { Keypair } from "@solana/web3.js"; import { createRpc, bn } from "@lightprotocol/stateless.js"; import { - createMint, - mintTo, - decompress, - compress, + createMint, + mintTo, + decompress, + compress, } from "@lightprotocol/compressed-token"; import { createAssociatedTokenAccount } from "@solana/spl-token"; async function main() { - // 1. Setup RPC and fund accounts - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); + // 1. Setup RPC and fund accounts + const rpc = createRpc(); + const payer = Keypair.generate(); + const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); + await rpc.confirmTransaction(airdropSig, "confirmed"); + console.log("Payer:", payer.publicKey.toBase58()); - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); + const owner = Keypair.generate(); + const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); + await rpc.confirmTransaction(airdropSig2, "confirmed"); - // 2. Create SPL mint with token pool - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair - ); - console.log("Mint:", mint.toBase58()); + // 2. Create SPL mint with token pool + const mintAuthority = Keypair.generate(); + const mintKeypair = Keypair.generate(); + const { mint } = await createMint( + rpc, + payer, + mintAuthority.publicKey, + 9, + mintKeypair, + ); + console.log("Mint:", mint.toBase58()); - // 3. Create SPL ATA and fund it with SPL tokens - const splAta = await createAssociatedTokenAccount( - rpc, - payer, - mint, - owner.publicKey - ); - console.log("SPL ATA:", splAta.toBase58()); + // 3. Create SPL ATA and fund it with SPL tokens + const splAta = await createAssociatedTokenAccount( + rpc, + payer, + mint, + owner.publicKey, + ); + console.log("SPL ATA:", splAta.toBase58()); - // Mint compressed then decompress to get SPL tokens - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); - await decompress(rpc, payer, mint, bn(1000), owner, splAta); - console.log("Funded SPL ATA with 1000 tokens"); + // Mint compressed then decompress to get SPL tokens + await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); + await decompress(rpc, payer, mint, bn(1000), owner, splAta); + console.log("Funded SPL ATA with 1000 tokens"); - // 4. Compress SPL tokens to cold storage - const recipient = Keypair.generate(); + // 4. Compress SPL tokens to cold storage + const recipient = Keypair.generate(); - const signature = await compress( - rpc, - payer, - mint, - bn(500), // amount to compress - owner, // owner of SPL account (signer) - splAta, // source SPL token account - recipient.publicKey // recipient of compressed tokens - ); + const signature = await compress( + rpc, + payer, + mint, + bn(500), // amount to compress + owner, // owner of SPL account (signer) + splAta, // source SPL token account + recipient.publicKey, // recipient of compressed tokens + ); - console.log("Compressed 500 tokens to cold storage"); - console.log("Recipient:", recipient.publicKey.toBase58()); - console.log("Transaction:", signature); + console.log("Compressed 500 tokens to cold storage"); + console.log("Recipient:", recipient.publicKey.toBase58()); + console.log("Transaction:", signature); } main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); + console.error("Error:", err); + if (err.logs) console.error("Logs:", err.logs); + process.exit(1); }); diff --git a/cookbook/actions/create-ata.ts b/cookbook/actions/create-ata.ts index d477592..9e0f52d 100644 --- a/cookbook/actions/create-ata.ts +++ b/cookbook/actions/create-ata.ts @@ -1,51 +1,52 @@ import "dotenv/config"; import { Keypair } from "@solana/web3.js"; +import { createRpc, featureFlags, VERSION } from "@lightprotocol/stateless.js"; import { - createRpc, - featureFlags, - VERSION, -} from "@lightprotocol/stateless.js"; -import { - createMintInterface, - createAtaInterface, - getAssociatedTokenAddressInterface, + createMintInterface, + createAtaInterface, + getAssociatedTokenAddressInterface, } from "@lightprotocol/compressed-token"; featureFlags.version = VERSION.V2; async function main() { - // 1. Setup RPC and fund payer - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); + // 1. Setup RPC and fund payer + const rpc = createRpc(); + const payer = Keypair.generate(); + const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); + await rpc.confirmTransaction(airdropSig, "confirmed"); + console.log("Payer:", payer.publicKey.toBase58()); - // 2. Create a light-mint - const mintSigner = Keypair.generate(); - const { mint } = await createMintInterface( - rpc, - payer, - payer, // mintAuthority - null, // freezeAuthority - 9, // decimals - mintSigner - ); - console.log("Mint:", mint.toBase58()); + // 2. Create a light-mint + const mintSigner = Keypair.generate(); + const { mint } = await createMintInterface( + rpc, + payer, + payer, // mintAuthority + null, // freezeAuthority + 9, // decimals + mintSigner, + ); + console.log("Mint:", mint.toBase58()); - // 3. Create associated token account for owner - const owner = Keypair.generate(); - const txSignature = await createAtaInterface(rpc, payer, mint, owner.publicKey); - console.log("ATA created for:", owner.publicKey.toBase58()); - console.log("Transaction:", txSignature); + // 3. Create associated token account for owner + const owner = Keypair.generate(); + const txSignature = await createAtaInterface( + rpc, + payer, + mint, + owner.publicKey, + ); + console.log("ATA created for:", owner.publicKey.toBase58()); + console.log("Transaction:", txSignature); - // 4. Derive the ATA address - const ata = getAssociatedTokenAddressInterface(mint, owner.publicKey); - console.log("ATA address:", ata.toBase58()); + // 4. Derive the ATA address + const ata = getAssociatedTokenAddressInterface(mint, owner.publicKey); + console.log("ATA address:", ata.toBase58()); } main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); + console.error("Error:", err); + if (err.logs) console.error("Logs:", err.logs); + process.exit(1); }); diff --git a/cookbook/actions/create-mint.ts b/cookbook/actions/create-mint.ts index 858dd7d..ab2a77b 100644 --- a/cookbook/actions/create-mint.ts +++ b/cookbook/actions/create-mint.ts @@ -1,57 +1,53 @@ import "dotenv/config"; import { Keypair } from "@solana/web3.js"; +import { createRpc, featureFlags, VERSION } from "@lightprotocol/stateless.js"; import { - createRpc, - featureFlags, - VERSION, -} from "@lightprotocol/stateless.js"; -import { - createMintInterface, - createTokenMetadata, + createMintInterface, + createTokenMetadata, } from "@lightprotocol/compressed-token"; featureFlags.version = VERSION.V2; async function main() { - // 1. Connect to local test-validator (default: localhost:8899) - // Start with: light test-validator - const rpc = createRpc(); - - // 2. Load payer keypair from local Solana config - // For localnet, use the test keypair or airdrop SOL - const payer = Keypair.generate(); - - // Airdrop SOL to payer for localnet - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); - - // 3. Generate a new mint signer keypair - const mintSigner = Keypair.generate(); - - // 4. Generate mint authority keypair - const mintAuthority = Keypair.generate(); - - // 5. Create compressed mint with token metadata - // The SDK auto-fetches V2 tree info from local validator - const { mint, transactionSignature } = await createMintInterface( - rpc, - payer, - mintAuthority, // mintAuthority (must be Signer for compressed mints) - null, // freezeAuthority - 9, // decimals - mintSigner, - { skipPreflight: true }, // confirmOptions - undefined, // programId (defaults to CTOKEN_PROGRAM_ID) - createTokenMetadata( - "Example Token", - "EXT", - "https://example.com/metadata.json" - ), - ); - - console.log("Mint created:", mint.toBase58()); - console.log(`Transaction: ${transactionSignature}`); + // 1. Connect to local test-validator (default: localhost:8899) + // Start with: light test-validator + const rpc = createRpc(); + + // 2. Load payer keypair from local Solana config + // For localnet, use the test keypair or airdrop SOL + const payer = Keypair.generate(); + + // Airdrop SOL to payer for localnet + const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); + await rpc.confirmTransaction(airdropSig, "confirmed"); + console.log("Payer:", payer.publicKey.toBase58()); + + // 3. Generate a new mint signer keypair + const mintSigner = Keypair.generate(); + + // 4. Generate mint authority keypair + const mintAuthority = Keypair.generate(); + + // 5. Create compressed mint with token metadata + // The SDK auto-fetches V2 tree info from local validator + const { mint, transactionSignature } = await createMintInterface( + rpc, + payer, + mintAuthority, // mintAuthority (must be Signer for compressed mints) + null, // freezeAuthority + 9, // decimals + mintSigner, + { skipPreflight: true }, // confirmOptions + undefined, // programId (defaults to CTOKEN_PROGRAM_ID) + createTokenMetadata( + "Example Token", + "EXT", + "https://example.com/metadata.json", + ), + ); + + console.log("Mint created:", mint.toBase58()); + console.log(`Transaction: ${transactionSignature}`); } main().catch(console.error); diff --git a/cookbook/actions/decompress-with-token-pool.ts b/cookbook/actions/decompress-with-token-pool.ts index 3f325a5..22df6d7 100644 --- a/cookbook/actions/decompress-with-token-pool.ts +++ b/cookbook/actions/decompress-with-token-pool.ts @@ -2,78 +2,78 @@ import "dotenv/config"; import { Keypair } from "@solana/web3.js"; import { createRpc, bn } from "@lightprotocol/stateless.js"; import { - createMint, - mintTo, - decompress, - getTokenPoolInfos, - selectTokenPoolInfosForDecompression, + createMint, + mintTo, + decompress, + getTokenPoolInfos, + selectTokenPoolInfosForDecompression, } from "@lightprotocol/compressed-token"; import { createAssociatedTokenAccount } from "@solana/spl-token"; async function main() { - // 1. Setup RPC and fund accounts - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); + // 1. Setup RPC and fund accounts + const rpc = createRpc(); + const payer = Keypair.generate(); + const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); + await rpc.confirmTransaction(airdropSig, "confirmed"); + console.log("Payer:", payer.publicKey.toBase58()); - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); + const owner = Keypair.generate(); + const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); + await rpc.confirmTransaction(airdropSig2, "confirmed"); - // 2. Create SPL mint with token pool - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair - ); - console.log("Mint:", mint.toBase58()); + // 2. Create SPL mint with token pool + const mintAuthority = Keypair.generate(); + const mintKeypair = Keypair.generate(); + const { mint } = await createMint( + rpc, + payer, + mintAuthority.publicKey, + 9, + mintKeypair, + ); + console.log("Mint:", mint.toBase58()); - // 3. Mint compressed tokens (cold storage) - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); - console.log("Minted 1000 compressed tokens"); + // 3. Mint compressed tokens (cold storage) + await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); + console.log("Minted 1000 compressed tokens"); - // 4. Create destination SPL ATA - const splAta = await createAssociatedTokenAccount( - rpc, - payer, - mint, - owner.publicKey - ); - console.log("SPL ATA:", splAta.toBase58()); + // 4. Create destination SPL ATA + const splAta = await createAssociatedTokenAccount( + rpc, + payer, + mint, + owner.publicKey, + ); + console.log("SPL ATA:", splAta.toBase58()); - // 5. Get token pool infos and select for decompression - const tokenPoolInfos = await getTokenPoolInfos(rpc, mint); - console.log("Token pools found:", tokenPoolInfos.length); + // 5. Get token pool infos and select for decompression + const tokenPoolInfos = await getTokenPoolInfos(rpc, mint); + console.log("Token pools found:", tokenPoolInfos.length); - const selectedPools = selectTokenPoolInfosForDecompression( - tokenPoolInfos, - bn(500) // amount to decompress - ); - console.log("Selected pools:", selectedPools.length); + const selectedPools = selectTokenPoolInfosForDecompression( + tokenPoolInfos, + bn(500), // amount to decompress + ); + console.log("Selected pools:", selectedPools.length); - // 6. Decompress with explicit token pool selection - const signature = await decompress( - rpc, - payer, - mint, - bn(500), - owner, - splAta, - selectedPools // optional: explicitly pass token pools - ); + // 6. Decompress with explicit token pool selection + const signature = await decompress( + rpc, + payer, + mint, + bn(500), + owner, + splAta, + selectedPools, // optional: explicitly pass token pools + ); - console.log("Decompressed 500 tokens to SPL ATA"); - console.log("Transaction:", signature); + console.log("Decompressed 500 tokens to SPL ATA"); + console.log("Transaction:", signature); } main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); + console.error("Error:", err); + if (err.logs) console.error("Logs:", err.logs); + process.exit(1); }); diff --git a/cookbook/actions/decompress.ts b/cookbook/actions/decompress.ts index b462724..97c9b40 100644 --- a/cookbook/actions/decompress.ts +++ b/cookbook/actions/decompress.ts @@ -2,65 +2,65 @@ import "dotenv/config"; import { Keypair } from "@solana/web3.js"; import { createRpc, bn } from "@lightprotocol/stateless.js"; import { - createMint, - mintTo, - decompress, + createMint, + mintTo, + decompress, } from "@lightprotocol/compressed-token"; import { createAssociatedTokenAccount } from "@solana/spl-token"; async function main() { - // 1. Setup RPC and fund accounts - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); + // 1. Setup RPC and fund accounts + const rpc = createRpc(); + const payer = Keypair.generate(); + const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); + await rpc.confirmTransaction(airdropSig, "confirmed"); + console.log("Payer:", payer.publicKey.toBase58()); - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); + const owner = Keypair.generate(); + const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); + await rpc.confirmTransaction(airdropSig2, "confirmed"); - // 2. Create SPL mint with token pool - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair - ); - console.log("Mint:", mint.toBase58()); + // 2. Create SPL mint with token pool + const mintAuthority = Keypair.generate(); + const mintKeypair = Keypair.generate(); + const { mint } = await createMint( + rpc, + payer, + mintAuthority.publicKey, + 9, + mintKeypair, + ); + console.log("Mint:", mint.toBase58()); - // 3. Mint compressed tokens (cold storage) - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); - console.log("Minted 1000 compressed tokens"); + // 3. Mint compressed tokens (cold storage) + await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); + console.log("Minted 1000 compressed tokens"); - // 4. Create destination SPL ATA (must exist before decompressing) - const splAta = await createAssociatedTokenAccount( - rpc, - payer, - mint, - owner.publicKey - ); - console.log("SPL ATA:", splAta.toBase58()); + // 4. Create destination SPL ATA (must exist before decompressing) + const splAta = await createAssociatedTokenAccount( + rpc, + payer, + mint, + owner.publicKey, + ); + console.log("SPL ATA:", splAta.toBase58()); - // 5. Decompress to SPL ATA - const signature = await decompress( - rpc, - payer, - mint, - bn(500), // amount to decompress - owner, // owner of compressed tokens (signer) - splAta // destination SPL token account - ); + // 5. Decompress to SPL ATA + const signature = await decompress( + rpc, + payer, + mint, + bn(500), // amount to decompress + owner, // owner of compressed tokens (signer) + splAta, // destination SPL token account + ); - console.log("Decompressed 500 tokens to SPL ATA"); - console.log("Transaction:", signature); + console.log("Decompressed 500 tokens to SPL ATA"); + console.log("Transaction:", signature); } main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); + console.error("Error:", err); + if (err.logs) console.error("Logs:", err.logs); + process.exit(1); }); diff --git a/cookbook/actions/delegate-approve.ts b/cookbook/actions/delegate-approve.ts index fb93dff..abd110c 100644 --- a/cookbook/actions/delegate-approve.ts +++ b/cookbook/actions/delegate-approve.ts @@ -1,66 +1,62 @@ import "dotenv/config"; import { Keypair } from "@solana/web3.js"; import { createRpc, bn } from "@lightprotocol/stateless.js"; -import { - createMint, - mintTo, - approve, -} from "@lightprotocol/compressed-token"; +import { createMint, mintTo, approve } from "@lightprotocol/compressed-token"; async function main() { - // 1. Setup RPC and fund accounts - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); - - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); - - // 2. Create mint and mint tokens to owner - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair - ); - console.log("Mint:", mint.toBase58()); - - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); - console.log("Minted 1000 compressed tokens to owner"); - - // 3. Create delegate - const delegate = Keypair.generate(); - console.log("Delegate:", delegate.publicKey.toBase58()); - - // 4. Approve delegation - const signature = await approve( - rpc, - payer, - mint, - bn(500), // amount to delegate - owner, // owner of tokens (signer) - delegate.publicKey // delegate address - ); - - console.log("Approved delegation of 500 tokens"); - console.log("Transaction:", signature); - - // 5. Verify delegation - const delegatedAccounts = await rpc.getCompressedTokenAccountsByDelegate( - delegate.publicKey, - { mint } - ); - console.log("Delegated accounts:", delegatedAccounts.items.length); + // 1. Setup RPC and fund accounts + const rpc = createRpc(); + const payer = Keypair.generate(); + const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); + await rpc.confirmTransaction(airdropSig, "confirmed"); + console.log("Payer:", payer.publicKey.toBase58()); + + const owner = Keypair.generate(); + const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); + await rpc.confirmTransaction(airdropSig2, "confirmed"); + + // 2. Create mint and mint tokens to owner + const mintAuthority = Keypair.generate(); + const mintKeypair = Keypair.generate(); + const { mint } = await createMint( + rpc, + payer, + mintAuthority.publicKey, + 9, + mintKeypair, + ); + console.log("Mint:", mint.toBase58()); + + await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); + console.log("Minted 1000 compressed tokens to owner"); + + // 3. Create delegate + const delegate = Keypair.generate(); + console.log("Delegate:", delegate.publicKey.toBase58()); + + // 4. Approve delegation + const signature = await approve( + rpc, + payer, + mint, + bn(500), // amount to delegate + owner, // owner of tokens (signer) + delegate.publicKey, // delegate address + ); + + console.log("Approved delegation of 500 tokens"); + console.log("Transaction:", signature); + + // 5. Verify delegation + const delegatedAccounts = await rpc.getCompressedTokenAccountsByDelegate( + delegate.publicKey, + { mint }, + ); + console.log("Delegated accounts:", delegatedAccounts.items.length); } main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); + console.error("Error:", err); + if (err.logs) console.error("Logs:", err.logs); + process.exit(1); }); diff --git a/cookbook/actions/delegate-revoke.ts b/cookbook/actions/delegate-revoke.ts index e1da000..f9622bd 100644 --- a/cookbook/actions/delegate-revoke.ts +++ b/cookbook/actions/delegate-revoke.ts @@ -2,73 +2,73 @@ import "dotenv/config"; import { Keypair } from "@solana/web3.js"; import { createRpc, bn } from "@lightprotocol/stateless.js"; import { - createMint, - mintTo, - approve, - revoke, + createMint, + mintTo, + approve, + revoke, } from "@lightprotocol/compressed-token"; async function main() { - // 1. Setup RPC and fund accounts - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); + // 1. Setup RPC and fund accounts + const rpc = createRpc(); + const payer = Keypair.generate(); + const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); + await rpc.confirmTransaction(airdropSig, "confirmed"); + console.log("Payer:", payer.publicKey.toBase58()); - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); + const owner = Keypair.generate(); + const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); + await rpc.confirmTransaction(airdropSig2, "confirmed"); - // 2. Create mint and mint tokens - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair - ); - console.log("Mint:", mint.toBase58()); + // 2. Create mint and mint tokens + const mintAuthority = Keypair.generate(); + const mintKeypair = Keypair.generate(); + const { mint } = await createMint( + rpc, + payer, + mintAuthority.publicKey, + 9, + mintKeypair, + ); + console.log("Mint:", mint.toBase58()); - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); - console.log("Minted 1000 compressed tokens to owner"); + await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); + console.log("Minted 1000 compressed tokens to owner"); - // 3. Approve delegation - const delegate = Keypair.generate(); - console.log("Delegate:", delegate.publicKey.toBase58()); - await approve(rpc, payer, mint, bn(500), owner, delegate.publicKey); - console.log("Approved delegation of 500 tokens"); + // 3. Approve delegation + const delegate = Keypair.generate(); + console.log("Delegate:", delegate.publicKey.toBase58()); + await approve(rpc, payer, mint, bn(500), owner, delegate.publicKey); + console.log("Approved delegation of 500 tokens"); - // 4. Get delegated accounts - const delegatedAccounts = await rpc.getCompressedTokenAccountsByDelegate( - delegate.publicKey, - { mint } - ); - console.log("Before revoke:", delegatedAccounts.items.length, "accounts"); + // 4. Get delegated accounts + const delegatedAccounts = await rpc.getCompressedTokenAccountsByDelegate( + delegate.publicKey, + { mint }, + ); + console.log("Before revoke:", delegatedAccounts.items.length, "accounts"); - // 5. Revoke delegation - const signature = await revoke( - rpc, - payer, - delegatedAccounts.items, // accounts to revoke - owner // owner (signer) - ); + // 5. Revoke delegation + const signature = await revoke( + rpc, + payer, + delegatedAccounts.items, // accounts to revoke + owner, // owner (signer) + ); - console.log("Revoked delegation"); - console.log("Transaction:", signature); + console.log("Revoked delegation"); + console.log("Transaction:", signature); - // 6. Verify revocation - const afterRevoke = await rpc.getCompressedTokenAccountsByDelegate( - delegate.publicKey, - { mint } - ); - console.log("After revoke:", afterRevoke.items.length, "accounts"); + // 6. Verify revocation + const afterRevoke = await rpc.getCompressedTokenAccountsByDelegate( + delegate.publicKey, + { mint }, + ); + console.log("After revoke:", afterRevoke.items.length, "accounts"); } main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); + console.error("Error:", err); + if (err.logs) console.error("Logs:", err.logs); + process.exit(1); }); diff --git a/cookbook/actions/load-ata.ts b/cookbook/actions/load-ata.ts index c288f95..bed425d 100644 --- a/cookbook/actions/load-ata.ts +++ b/cookbook/actions/load-ata.ts @@ -2,63 +2,63 @@ import "dotenv/config"; import { Keypair } from "@solana/web3.js"; import { createRpc, bn } from "@lightprotocol/stateless.js"; import { - createMint, - mintTo, - loadAta, - getAssociatedTokenAddressInterface, + createMint, + mintTo, + loadAta, + getAssociatedTokenAddressInterface, } from "@lightprotocol/compressed-token"; async function main() { - // 1. Setup RPC and fund accounts - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); + // 1. Setup RPC and fund accounts + const rpc = createRpc(); + const payer = Keypair.generate(); + const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); + await rpc.confirmTransaction(airdropSig, "confirmed"); + console.log("Payer:", payer.publicKey.toBase58()); - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); + const owner = Keypair.generate(); + const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); + await rpc.confirmTransaction(airdropSig2, "confirmed"); - // 2. Create mint and mint compressed tokens (cold) - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair - ); - console.log("Mint:", mint.toBase58()); + // 2. Create mint and mint compressed tokens (cold) + const mintAuthority = Keypair.generate(); + const mintKeypair = Keypair.generate(); + const { mint } = await createMint( + rpc, + payer, + mintAuthority.publicKey, + 9, + mintKeypair, + ); + console.log("Mint:", mint.toBase58()); - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); - console.log("Minted 1000 compressed tokens (cold)"); + await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); + console.log("Minted 1000 compressed tokens (cold)"); - // 3. Get c-token ATA address - const ctokenAta = getAssociatedTokenAddressInterface(mint, owner.publicKey); - console.log("c-token ATA:", ctokenAta.toBase58()); + // 3. Get c-token ATA address + const ctokenAta = getAssociatedTokenAddressInterface(mint, owner.publicKey); + console.log("c-token ATA:", ctokenAta.toBase58()); - // 4. Load compressed tokens to hot balance - // Creates ATA if needed, returns null if nothing to load - const signature = await loadAta( - rpc, - ctokenAta, // c-token ATA address - owner, // owner (signer) - mint, - payer // optional: fee payer - ); + // 4. Load compressed tokens to hot balance + // Creates ATA if needed, returns null if nothing to load + const signature = await loadAta( + rpc, + ctokenAta, // c-token ATA address + owner, // owner (signer) + mint, + payer, // optional: fee payer + ); - if (signature) { - console.log("Loaded tokens to hot balance"); - console.log("Transaction:", signature); - } else { - console.log("Nothing to load"); - } + if (signature) { + console.log("Loaded tokens to hot balance"); + console.log("Transaction:", signature); + } else { + console.log("Nothing to load"); + } } main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); + console.error("Error:", err); + if (err.logs) console.error("Logs:", err.logs); + process.exit(1); }); diff --git a/cookbook/actions/merge-token-accounts.ts b/cookbook/actions/merge-token-accounts.ts index 6800317..44bb1d6 100644 --- a/cookbook/actions/merge-token-accounts.ts +++ b/cookbook/actions/merge-token-accounts.ts @@ -2,86 +2,86 @@ import "dotenv/config"; import { Keypair } from "@solana/web3.js"; import { createRpc, bn } from "@lightprotocol/stateless.js"; import { - createMint, - mintTo, - mergeTokenAccounts, + createMint, + mintTo, + mergeTokenAccounts, } from "@lightprotocol/compressed-token"; async function main() { - // 1. Setup RPC and fund accounts - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); + // 1. Setup RPC and fund accounts + const rpc = createRpc(); + const payer = Keypair.generate(); + const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); + await rpc.confirmTransaction(airdropSig, "confirmed"); + console.log("Payer:", payer.publicKey.toBase58()); - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); + const owner = Keypair.generate(); + const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); + await rpc.confirmTransaction(airdropSig2, "confirmed"); - // 2. Create mint - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair - ); - console.log("Mint:", mint.toBase58()); + // 2. Create mint + const mintAuthority = Keypair.generate(); + const mintKeypair = Keypair.generate(); + const { mint } = await createMint( + rpc, + payer, + mintAuthority.publicKey, + 9, + mintKeypair, + ); + console.log("Mint:", mint.toBase58()); - // 3. Mint multiple times to create multiple compressed accounts - console.log("Minting 5 times to create multiple accounts..."); - for (let i = 0; i < 5; i++) { - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(100)); - } - console.log("Minted 500 total tokens across 5 accounts"); + // 3. Mint multiple times to create multiple compressed accounts + console.log("Minting 5 times to create multiple accounts..."); + for (let i = 0; i < 5; i++) { + await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(100)); + } + console.log("Minted 500 total tokens across 5 accounts"); - // 4. Check accounts before merge - const accountsBefore = await rpc.getCompressedTokenAccountsByOwner( - owner.publicKey, - { mint } - ); - console.log("Accounts before merge:", accountsBefore.items.length); + // 4. Check accounts before merge + const accountsBefore = await rpc.getCompressedTokenAccountsByOwner( + owner.publicKey, + { mint }, + ); + console.log("Accounts before merge:", accountsBefore.items.length); - // 5. Merge token accounts - const signature = await mergeTokenAccounts( - rpc, - payer, - mint, - owner // owner (signer) - ); + // 5. Merge token accounts + const signature = await mergeTokenAccounts( + rpc, + payer, + mint, + owner, // owner (signer) + ); - console.log("Merged token accounts"); - console.log("Transaction:", signature); + console.log("Merged token accounts"); + console.log("Transaction:", signature); - // 6. Check accounts after merge - const accountsAfter = await rpc.getCompressedTokenAccountsByOwner( - owner.publicKey, - { mint } - ); - console.log("Accounts after merge:", accountsAfter.items.length); + // 6. Check accounts after merge + const accountsAfter = await rpc.getCompressedTokenAccountsByOwner( + owner.publicKey, + { mint }, + ); + console.log("Accounts after merge:", accountsAfter.items.length); - // 7. Verify total balance unchanged - const totalBefore = accountsBefore.items.reduce( - (sum, acc) => sum.add(acc.parsed.amount), - bn(0) - ); - const totalAfter = accountsAfter.items.reduce( - (sum, acc) => sum.add(acc.parsed.amount), - bn(0) - ); - console.log("Total balance before:", totalBefore.toString()); - console.log("Total balance after:", totalAfter.toString()); - console.log( - "Balance preserved:", - totalBefore.toString() === totalAfter.toString() - ); + // 7. Verify total balance unchanged + const totalBefore = accountsBefore.items.reduce( + (sum, acc) => sum.add(acc.parsed.amount), + bn(0), + ); + const totalAfter = accountsAfter.items.reduce( + (sum, acc) => sum.add(acc.parsed.amount), + bn(0), + ); + console.log("Total balance before:", totalBefore.toString()); + console.log("Total balance after:", totalAfter.toString()); + console.log( + "Balance preserved:", + totalBefore.toString() === totalAfter.toString(), + ); } main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); + console.error("Error:", err); + if (err.logs) console.error("Logs:", err.logs); + process.exit(1); }); diff --git a/cookbook/actions/mint-to.ts b/cookbook/actions/mint-to.ts index 4fb100f..284a4e6 100644 --- a/cookbook/actions/mint-to.ts +++ b/cookbook/actions/mint-to.ts @@ -1,63 +1,62 @@ import "dotenv/config"; import { Keypair } from "@solana/web3.js"; +import { createRpc, featureFlags, VERSION } from "@lightprotocol/stateless.js"; import { - createRpc, - featureFlags, - VERSION, -} from "@lightprotocol/stateless.js"; -import { - createMintInterface, - createAtaInterface, - mintToInterface, - getAssociatedTokenAddressInterface, + createMintInterface, + createAtaInterface, + mintToInterface, + getAssociatedTokenAddressInterface, } from "@lightprotocol/compressed-token"; featureFlags.version = VERSION.V2; async function main() { - // 1. Setup RPC and fund payer - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); - - // 2. Create a light-mint (payer is mint authority) - const mintSigner = Keypair.generate(); - const { mint } = await createMintInterface( - rpc, - payer, - payer, // mintAuthority - null, // freezeAuthority - 9, // decimals - mintSigner, - ); - console.log("Mint created:", mint.toBase58()); - - // 3. Create associated token account for recipient - const recipient = Keypair.generate(); - await createAtaInterface(rpc, payer, mint, recipient.publicKey); - console.log("Recipient ATA created for:", recipient.publicKey.toBase58()); - - // 4. Mint tokens to the recipient's account - const destination = getAssociatedTokenAddressInterface(mint, recipient.publicKey); - const amount = 1_000_000_000; // 1 token with 9 decimals - - const txSignature = await mintToInterface( - rpc, - payer, - mint, - destination, - payer, // mintAuthority (must be Signer) - amount, - ); - - console.log("Minted tokens:", amount); - console.log("Transaction:", txSignature); + // 1. Setup RPC and fund payer + const rpc = createRpc(); + const payer = Keypair.generate(); + const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); + await rpc.confirmTransaction(airdropSig, "confirmed"); + console.log("Payer:", payer.publicKey.toBase58()); + + // 2. Create a light-mint (payer is mint authority) + const mintSigner = Keypair.generate(); + const { mint } = await createMintInterface( + rpc, + payer, + payer, // mintAuthority + null, // freezeAuthority + 9, // decimals + mintSigner, + ); + console.log("Mint created:", mint.toBase58()); + + // 3. Create associated token account for recipient + const recipient = Keypair.generate(); + await createAtaInterface(rpc, payer, mint, recipient.publicKey); + console.log("Recipient ATA created for:", recipient.publicKey.toBase58()); + + // 4. Mint tokens to the recipient's account + const destination = getAssociatedTokenAddressInterface( + mint, + recipient.publicKey, + ); + const amount = 1_000_000_000; // 1 token with 9 decimals + + const txSignature = await mintToInterface( + rpc, + payer, + mint, + destination, + payer, // mintAuthority (must be Signer) + amount, + ); + + console.log("Minted tokens:", amount); + console.log("Transaction:", txSignature); } main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); + console.error("Error:", err); + if (err.logs) console.error("Logs:", err.logs); + process.exit(1); }); diff --git a/cookbook/actions/transfer-interface.ts b/cookbook/actions/transfer-interface.ts index 13f8adf..6d97a08 100644 --- a/cookbook/actions/transfer-interface.ts +++ b/cookbook/actions/transfer-interface.ts @@ -1,73 +1,72 @@ import "dotenv/config"; import { Keypair } from "@solana/web3.js"; +import { createRpc, featureFlags, VERSION } from "@lightprotocol/stateless.js"; import { - createRpc, - featureFlags, - VERSION, -} from "@lightprotocol/stateless.js"; -import { - createMintInterface, - createAtaInterface, - mintToInterface, - transferInterface, - getAssociatedTokenAddressInterface, + createMintInterface, + createAtaInterface, + mintToInterface, + transferInterface, + getAssociatedTokenAddressInterface, } from "@lightprotocol/compressed-token"; featureFlags.version = VERSION.V2; async function main() { - // 1. Setup RPC and fund payer - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); + // 1. Setup RPC and fund payer + const rpc = createRpc(); + const payer = Keypair.generate(); + const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); + await rpc.confirmTransaction(airdropSig, "confirmed"); + console.log("Payer:", payer.publicKey.toBase58()); - // 2. Create a light-mint - const mintSigner = Keypair.generate(); - const { mint } = await createMintInterface( - rpc, - payer, - payer, - null, - 9, - mintSigner - ); - console.log("Mint:", mint.toBase58()); + // 2. Create a light-mint + const mintSigner = Keypair.generate(); + const { mint } = await createMintInterface( + rpc, + payer, + payer, + null, + 9, + mintSigner, + ); + console.log("Mint:", mint.toBase58()); - // 3. Create sender's ATA and mint tokens - const sender = Keypair.generate(); - await createAtaInterface(rpc, payer, mint, sender.publicKey); - const senderAta = getAssociatedTokenAddressInterface(mint, sender.publicKey); - await mintToInterface(rpc, payer, mint, senderAta, payer, 1_000_000_000); - console.log("Sender ATA:", senderAta.toBase58()); + // 3. Create sender's ATA and mint tokens + const sender = Keypair.generate(); + await createAtaInterface(rpc, payer, mint, sender.publicKey); + const senderAta = getAssociatedTokenAddressInterface( + mint, + sender.publicKey, + ); + await mintToInterface(rpc, payer, mint, senderAta, payer, 1_000_000_000); + console.log("Sender ATA:", senderAta.toBase58()); - // 4. Create recipient's ATA - const recipient = Keypair.generate(); - await createAtaInterface(rpc, payer, mint, recipient.publicKey); - const recipientAta = getAssociatedTokenAddressInterface( - mint, - recipient.publicKey - ); - console.log("Recipient ATA:", recipientAta.toBase58()); + // 4. Create recipient's ATA + const recipient = Keypair.generate(); + await createAtaInterface(rpc, payer, mint, recipient.publicKey); + const recipientAta = getAssociatedTokenAddressInterface( + mint, + recipient.publicKey, + ); + console.log("Recipient ATA:", recipientAta.toBase58()); - // 5. Transfer tokens - const txSignature = await transferInterface( - rpc, - payer, - senderAta, - mint, - recipientAta, - sender, // owner (must be Signer) - 500_000_000 // amount to transfer - ); + // 5. Transfer tokens + const txSignature = await transferInterface( + rpc, + payer, + senderAta, + mint, + recipientAta, + sender, // owner (must be Signer) + 500_000_000, // amount to transfer + ); - console.log("Transferred 0.5 tokens"); - console.log("Transaction:", txSignature); + console.log("Transferred 0.5 tokens"); + console.log("Transaction:", txSignature); } main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); + console.error("Error:", err); + if (err.logs) console.error("Logs:", err.logs); + process.exit(1); }); diff --git a/cookbook/actions/unwrap.ts b/cookbook/actions/unwrap.ts index 7a530c4..4a1bb2e 100644 --- a/cookbook/actions/unwrap.ts +++ b/cookbook/actions/unwrap.ts @@ -1,67 +1,64 @@ import "dotenv/config"; import { Keypair } from "@solana/web3.js"; import { createRpc, bn } from "@lightprotocol/stateless.js"; -import { - createMint, - mintTo, -} from "@lightprotocol/compressed-token"; +import { createMint, mintTo } from "@lightprotocol/compressed-token"; import { unwrap } from "@lightprotocol/compressed-token/unified"; import { createAssociatedTokenAccount } from "@solana/spl-token"; async function main() { - // 1. Setup RPC and fund accounts - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); + // 1. Setup RPC and fund accounts + const rpc = createRpc(); + const payer = Keypair.generate(); + const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); + await rpc.confirmTransaction(airdropSig, "confirmed"); + console.log("Payer:", payer.publicKey.toBase58()); - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); + const owner = Keypair.generate(); + const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); + await rpc.confirmTransaction(airdropSig2, "confirmed"); - // 2. Create SPL mint with token pool - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair - ); - console.log("Mint:", mint.toBase58()); + // 2. Create SPL mint with token pool + const mintAuthority = Keypair.generate(); + const mintKeypair = Keypair.generate(); + const { mint } = await createMint( + rpc, + payer, + mintAuthority.publicKey, + 9, + mintKeypair, + ); + console.log("Mint:", mint.toBase58()); - // 3. Mint compressed tokens to owner - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); - console.log("Minted 1000 compressed tokens"); + // 3. Mint compressed tokens to owner + await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); + console.log("Minted 1000 compressed tokens"); - // 4. Create destination SPL ATA (must exist before unwrap) - const splAta = await createAssociatedTokenAccount( - rpc, - payer, - mint, - owner.publicKey - ); - console.log("SPL ATA:", splAta.toBase58()); + // 4. Create destination SPL ATA (must exist before unwrap) + const splAta = await createAssociatedTokenAccount( + rpc, + payer, + mint, + owner.publicKey, + ); + console.log("SPL ATA:", splAta.toBase58()); - // 5. Unwrap c-tokens to SPL ATA - // This auto-loads compressed tokens to hot balance first - const signature = await unwrap( - rpc, - payer, - splAta, // destination: SPL token account - owner, // owner of c-tokens (signer) - mint, - bn(500) // amount to unwrap (omit for full balance) - ); + // 5. Unwrap c-tokens to SPL ATA + // This auto-loads compressed tokens to hot balance first + const signature = await unwrap( + rpc, + payer, + splAta, // destination: SPL token account + owner, // owner of c-tokens (signer) + mint, + bn(500), // amount to unwrap (omit for full balance) + ); - console.log("Unwrapped 500 tokens to SPL ATA"); - console.log("Transaction:", signature); + console.log("Unwrapped 500 tokens to SPL ATA"); + console.log("Transaction:", signature); } main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); + console.error("Error:", err); + if (err.logs) console.error("Logs:", err.logs); + process.exit(1); }); diff --git a/cookbook/actions/wrap.ts b/cookbook/actions/wrap.ts index 00ab676..e1a579d 100644 --- a/cookbook/actions/wrap.ts +++ b/cookbook/actions/wrap.ts @@ -2,75 +2,75 @@ import "dotenv/config"; import { Keypair } from "@solana/web3.js"; import { createRpc, bn } from "@lightprotocol/stateless.js"; import { - createMint, - mintTo, - decompress, - wrap, - getAssociatedTokenAddressInterface, - createAtaInterfaceIdempotent, + createMint, + mintTo, + decompress, + wrap, + getAssociatedTokenAddressInterface, + createAtaInterfaceIdempotent, } from "@lightprotocol/compressed-token"; import { createAssociatedTokenAccount } from "@solana/spl-token"; async function main() { - // 1. Setup RPC and fund accounts - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); + // 1. Setup RPC and fund accounts + const rpc = createRpc(); + const payer = Keypair.generate(); + const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); + await rpc.confirmTransaction(airdropSig, "confirmed"); + console.log("Payer:", payer.publicKey.toBase58()); - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); + const owner = Keypair.generate(); + const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); + await rpc.confirmTransaction(airdropSig2, "confirmed"); - // 2. Create SPL mint with token pool - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair - ); - console.log("Mint:", mint.toBase58()); + // 2. Create SPL mint with token pool + const mintAuthority = Keypair.generate(); + const mintKeypair = Keypair.generate(); + const { mint } = await createMint( + rpc, + payer, + mintAuthority.publicKey, + 9, + mintKeypair, + ); + console.log("Mint:", mint.toBase58()); - // 3. Create SPL ATA and fund it - const splAta = await createAssociatedTokenAccount( - rpc, - payer, - mint, - owner.publicKey - ); - console.log("SPL ATA:", splAta.toBase58()); + // 3. Create SPL ATA and fund it + const splAta = await createAssociatedTokenAccount( + rpc, + payer, + mint, + owner.publicKey, + ); + console.log("SPL ATA:", splAta.toBase58()); - // Mint compressed then decompress to SPL ATA - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); - await decompress(rpc, payer, mint, bn(1000), owner, splAta); - console.log("Funded SPL ATA with 1000 tokens"); + // Mint compressed then decompress to SPL ATA + await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); + await decompress(rpc, payer, mint, bn(1000), owner, splAta); + console.log("Funded SPL ATA with 1000 tokens"); - // 4. Create c-token ATA (destination) - const ctokenAta = getAssociatedTokenAddressInterface(mint, owner.publicKey); - await createAtaInterfaceIdempotent(rpc, payer, mint, owner.publicKey); - console.log("c-token ATA:", ctokenAta.toBase58()); + // 4. Create c-token ATA (destination) + const ctokenAta = getAssociatedTokenAddressInterface(mint, owner.publicKey); + await createAtaInterfaceIdempotent(rpc, payer, mint, owner.publicKey); + console.log("c-token ATA:", ctokenAta.toBase58()); - // 5. Wrap SPL tokens to c-token ATA - const signature = await wrap( - rpc, - payer, - splAta, // source: SPL token account - ctokenAta, // destination: c-token ATA - owner, // owner of source account (signer) - mint, - bn(500) // amount to wrap - ); + // 5. Wrap SPL tokens to c-token ATA + const signature = await wrap( + rpc, + payer, + splAta, // source: SPL token account + ctokenAta, // destination: c-token ATA + owner, // owner of source account (signer) + mint, + bn(500), // amount to wrap + ); - console.log("Wrapped 500 tokens to c-token ATA"); - console.log("Transaction:", signature); + console.log("Wrapped 500 tokens to c-token ATA"); + console.log("Transaction:", signature); } main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); + console.error("Error:", err); + if (err.logs) console.error("Logs:", err.logs); + process.exit(1); }); diff --git a/cookbook/instructions/create-ata.ts b/cookbook/instructions/create-ata.ts index 6c9bf37..b4d0863 100644 --- a/cookbook/instructions/create-ata.ts +++ b/cookbook/instructions/create-ata.ts @@ -1,71 +1,74 @@ import "dotenv/config"; import { Keypair, ComputeBudgetProgram } from "@solana/web3.js"; import { - createRpc, - buildAndSignTx, - sendAndConfirmTx, - featureFlags, - VERSION, - CTOKEN_PROGRAM_ID, + createRpc, + buildAndSignTx, + sendAndConfirmTx, + featureFlags, + VERSION, + CTOKEN_PROGRAM_ID, } from "@lightprotocol/stateless.js"; import { - createMintInterface, - createAssociatedTokenAccountInterfaceInstruction, - getAssociatedTokenAddressInterface, + createMintInterface, + createAssociatedTokenAccountInterfaceInstruction, + getAssociatedTokenAddressInterface, } from "@lightprotocol/compressed-token"; featureFlags.version = VERSION.V2; async function main() { - // 1. Setup RPC and fund payer - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); + // 1. Setup RPC and fund payer + const rpc = createRpc(); + const payer = Keypair.generate(); + const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); + await rpc.confirmTransaction(airdropSig, "confirmed"); + console.log("Payer:", payer.publicKey.toBase58()); - // 2. Create a light-mint - const mintSigner = Keypair.generate(); - const { mint } = await createMintInterface( - rpc, - payer, - payer, // mintAuthority - null, // freezeAuthority - 9, // decimals - mintSigner - ); - console.log("Mint:", mint.toBase58()); + // 2. Create a light-mint + const mintSigner = Keypair.generate(); + const { mint } = await createMintInterface( + rpc, + payer, + payer, // mintAuthority + null, // freezeAuthority + 9, // decimals + mintSigner, + ); + console.log("Mint:", mint.toBase58()); - // 3. Derive the ATA address - const owner = Keypair.generate(); - const associatedToken = getAssociatedTokenAddressInterface(mint, owner.publicKey); - console.log("Owner:", owner.publicKey.toBase58()); - console.log("ATA address:", associatedToken.toBase58()); + // 3. Derive the ATA address + const owner = Keypair.generate(); + const associatedToken = getAssociatedTokenAddressInterface( + mint, + owner.publicKey, + ); + console.log("Owner:", owner.publicKey.toBase58()); + console.log("ATA address:", associatedToken.toBase58()); - // 4. Create the instruction - const ix = createAssociatedTokenAccountInterfaceInstruction( - payer.publicKey, // payer - associatedToken, // associatedToken - owner.publicKey, // owner - mint, // mint - CTOKEN_PROGRAM_ID // programId (cToken) - ); + // 4. Create the instruction + const ix = createAssociatedTokenAccountInterfaceInstruction( + payer.publicKey, // payer + associatedToken, // associatedToken + owner.publicKey, // owner + mint, // mint + CTOKEN_PROGRAM_ID, // programId (cToken) + ); - // 5. Build, sign, and send transaction - const { blockhash } = await rpc.getLatestBlockhash(); - const tx = buildAndSignTx( - [ComputeBudgetProgram.setComputeUnitLimit({ units: 100_000 }), ix], - payer, - blockhash - ); - const signature = await sendAndConfirmTx(rpc, tx); + // 5. Build, sign, and send transaction + const { blockhash } = await rpc.getLatestBlockhash(); + const tx = buildAndSignTx( + [ComputeBudgetProgram.setComputeUnitLimit({ units: 100_000 }), ix], + payer, + blockhash, + ); + const signature = await sendAndConfirmTx(rpc, tx); - console.log("ATA created"); - console.log("Transaction:", signature); + console.log("ATA created"); + console.log("Transaction:", signature); } main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); + console.error("Error:", err); + if (err.logs) console.error("Logs:", err.logs); + process.exit(1); }); diff --git a/cookbook/instructions/create-mint.ts b/cookbook/instructions/create-mint.ts index 7cb9a91..8322d3c 100644 --- a/cookbook/instructions/create-mint.ts +++ b/cookbook/instructions/create-mint.ts @@ -1,19 +1,19 @@ import "dotenv/config"; import { Keypair, ComputeBudgetProgram, PublicKey } from "@solana/web3.js"; import { - createRpc, - buildAndSignTx, - sendAndConfirmTx, - getBatchAddressTreeInfo, - selectStateTreeInfo, - featureFlags, - VERSION, - CTOKEN_PROGRAM_ID, - DerivationMode, + createRpc, + buildAndSignTx, + sendAndConfirmTx, + getBatchAddressTreeInfo, + selectStateTreeInfo, + featureFlags, + VERSION, + CTOKEN_PROGRAM_ID, + DerivationMode, } from "@lightprotocol/stateless.js"; import { - createMintInstruction, - createTokenMetadata, + createMintInstruction, + createTokenMetadata, } from "@lightprotocol/compressed-token"; featureFlags.version = VERSION.V2; @@ -22,78 +22,76 @@ featureFlags.version = VERSION.V2; const COMPRESSED_MINT_SEED = Buffer.from("compressed_mint"); function findMintAddress(mintSigner: PublicKey): [PublicKey, number] { - return PublicKey.findProgramAddressSync( - [COMPRESSED_MINT_SEED, mintSigner.toBuffer()], - CTOKEN_PROGRAM_ID - ); + return PublicKey.findProgramAddressSync( + [COMPRESSED_MINT_SEED, mintSigner.toBuffer()], + CTOKEN_PROGRAM_ID, + ); } async function main() { - // 1. Setup RPC connection to local validator - const rpc = createRpc(); + // 1. Setup RPC connection to local validator + const rpc = createRpc(); - // 2. Create and fund payer - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); + // 2. Create and fund payer + const payer = Keypair.generate(); + const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); + await rpc.confirmTransaction(airdropSig, "confirmed"); + console.log("Payer:", payer.publicKey.toBase58()); - // 3. Prepare mint parameters - const mintSigner = Keypair.generate(); - const decimals = 9; + // 3. Prepare mint parameters + const mintSigner = Keypair.generate(); + const decimals = 9; - // 4. Get tree infos - // Address Merkle tree stores the mint address - // State Merkle tree stores the mint account data - const addressTreeInfo = getBatchAddressTreeInfo(); - const stateTreeInfo = selectStateTreeInfo( - await rpc.getStateTreeInfos() - ); + // 4. Get tree infos + // Address Merkle tree stores the mint address + // State Merkle tree stores the mint account data + const addressTreeInfo = getBatchAddressTreeInfo(); + const stateTreeInfo = selectStateTreeInfo(await rpc.getStateTreeInfos()); - // 5. Derive the mint PDA address - const [mintPda] = findMintAddress(mintSigner.publicKey); + // 5. Derive the mint PDA address + const [mintPda] = findMintAddress(mintSigner.publicKey); - // 6. Get validity proof for address creation - // Proves the mint address does not exist yet - const validityProof = await rpc.getValidityProofV2( - [], - [{ address: mintPda.toBytes(), treeInfo: addressTreeInfo }], - DerivationMode.compressible - ); + // 6. Get validity proof for address creation + // Proves the mint address does not exist yet + const validityProof = await rpc.getValidityProofV2( + [], + [{ address: mintPda.toBytes(), treeInfo: addressTreeInfo }], + DerivationMode.compressible, + ); - // 7. Create instruction - const ix = createMintInstruction( - mintSigner.publicKey, - decimals, - payer.publicKey, // mintAuthority - null, // freezeAuthority - payer.publicKey, // payer - validityProof, - addressTreeInfo, - stateTreeInfo, - createTokenMetadata( - "Example Token", - "EXT", - "https://example.com/metadata.json" - ) - ); + // 7. Create instruction + const ix = createMintInstruction( + mintSigner.publicKey, + decimals, + payer.publicKey, // mintAuthority + null, // freezeAuthority + payer.publicKey, // payer + validityProof, + addressTreeInfo, + stateTreeInfo, + createTokenMetadata( + "Example Token", + "EXT", + "https://example.com/metadata.json", + ), + ); - // 8. Build, sign, and send transaction - const { blockhash } = await rpc.getLatestBlockhash(); - const tx = buildAndSignTx( - [ComputeBudgetProgram.setComputeUnitLimit({ units: 500_000 }), ix], - payer, - blockhash, - [mintSigner] - ); - const signature = await sendAndConfirmTx(rpc, tx, { skipPreflight: true }); + // 8. Build, sign, and send transaction + const { blockhash } = await rpc.getLatestBlockhash(); + const tx = buildAndSignTx( + [ComputeBudgetProgram.setComputeUnitLimit({ units: 500_000 }), ix], + payer, + blockhash, + [mintSigner], + ); + const signature = await sendAndConfirmTx(rpc, tx, { skipPreflight: true }); - console.log("Mint created:", mintPda.toBase58()); - console.log("Transaction:", signature); + console.log("Mint created:", mintPda.toBase58()); + console.log("Transaction:", signature); } main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); + console.error("Error:", err); + if (err.logs) console.error("Logs:", err.logs); + process.exit(1); }); diff --git a/cookbook/instructions/load-ata.ts b/cookbook/instructions/load-ata.ts index 6575c6d..31100e5 100644 --- a/cookbook/instructions/load-ata.ts +++ b/cookbook/instructions/load-ata.ts @@ -1,84 +1,84 @@ import "dotenv/config"; import { Keypair, ComputeBudgetProgram } from "@solana/web3.js"; import { - createRpc, - bn, - buildAndSignTx, - sendAndConfirmTx, - dedupeSigner, + createRpc, + bn, + buildAndSignTx, + sendAndConfirmTx, + dedupeSigner, } from "@lightprotocol/stateless.js"; import { - createMint, - mintTo, - createLoadAtaInstructions, - getAssociatedTokenAddressInterface, + createMint, + mintTo, + createLoadAtaInstructions, + getAssociatedTokenAddressInterface, } from "@lightprotocol/compressed-token"; async function main() { - // 1. Setup RPC and fund accounts - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); + // 1. Setup RPC and fund accounts + const rpc = createRpc(); + const payer = Keypair.generate(); + const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); + await rpc.confirmTransaction(airdropSig, "confirmed"); + console.log("Payer:", payer.publicKey.toBase58()); - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); + const owner = Keypair.generate(); + const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); + await rpc.confirmTransaction(airdropSig2, "confirmed"); - // 2. Create mint and mint compressed tokens - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair - ); - console.log("Mint:", mint.toBase58()); + // 2. Create mint and mint compressed tokens + const mintAuthority = Keypair.generate(); + const mintKeypair = Keypair.generate(); + const { mint } = await createMint( + rpc, + payer, + mintAuthority.publicKey, + 9, + mintKeypair, + ); + console.log("Mint:", mint.toBase58()); - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); - console.log("Minted 1000 compressed tokens (cold)"); + await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); + console.log("Minted 1000 compressed tokens (cold)"); - // 3. Get c-token ATA address - const ctokenAta = getAssociatedTokenAddressInterface(mint, owner.publicKey); - console.log("c-token ATA:", ctokenAta.toBase58()); + // 3. Get c-token ATA address + const ctokenAta = getAssociatedTokenAddressInterface(mint, owner.publicKey); + console.log("c-token ATA:", ctokenAta.toBase58()); - // 4. Create load instructions - const ixs = await createLoadAtaInstructions( - rpc, - ctokenAta, - owner.publicKey, - mint, - payer.publicKey - ); + // 4. Create load instructions + const ixs = await createLoadAtaInstructions( + rpc, + ctokenAta, + owner.publicKey, + mint, + payer.publicKey, + ); - if (ixs.length === 0) { - console.log("Nothing to load"); - return; - } + if (ixs.length === 0) { + console.log("Nothing to load"); + return; + } - console.log("Created", ixs.length, "load instructions"); + console.log("Created", ixs.length, "load instructions"); - // 5. Build, sign, and send transaction - const { blockhash } = await rpc.getLatestBlockhash(); - const additionalSigners = dedupeSigner(payer, [owner]); + // 5. Build, sign, and send transaction + const { blockhash } = await rpc.getLatestBlockhash(); + const additionalSigners = dedupeSigner(payer, [owner]); - const tx = buildAndSignTx( - [ComputeBudgetProgram.setComputeUnitLimit({ units: 500_000 }), ...ixs], - payer, - blockhash, - additionalSigners - ); + const tx = buildAndSignTx( + [ComputeBudgetProgram.setComputeUnitLimit({ units: 500_000 }), ...ixs], + payer, + blockhash, + additionalSigners, + ); - const signature = await sendAndConfirmTx(rpc, tx); - console.log("Loaded tokens to hot balance"); - console.log("Transaction:", signature); + const signature = await sendAndConfirmTx(rpc, tx); + console.log("Loaded tokens to hot balance"); + console.log("Transaction:", signature); } main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); + console.error("Error:", err); + if (err.logs) console.error("Logs:", err.logs); + process.exit(1); }); diff --git a/cookbook/instructions/mint-to.ts b/cookbook/instructions/mint-to.ts index d52baa3..54035e9 100644 --- a/cookbook/instructions/mint-to.ts +++ b/cookbook/instructions/mint-to.ts @@ -1,92 +1,95 @@ import "dotenv/config"; import { Keypair, ComputeBudgetProgram } from "@solana/web3.js"; import { - createRpc, - buildAndSignTx, - sendAndConfirmTx, - bn, - DerivationMode, - featureFlags, - VERSION, + createRpc, + buildAndSignTx, + sendAndConfirmTx, + bn, + DerivationMode, + featureFlags, + VERSION, } from "@lightprotocol/stateless.js"; import { - createMintInterface, - createAtaInterface, - createMintToInterfaceInstruction, - getMintInterface, - getAssociatedTokenAddressInterface, + createMintInterface, + createAtaInterface, + createMintToInterfaceInstruction, + getMintInterface, + getAssociatedTokenAddressInterface, } from "@lightprotocol/compressed-token"; featureFlags.version = VERSION.V2; async function main() { - // 1. Setup RPC and fund payer - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); + // 1. Setup RPC and fund payer + const rpc = createRpc(); + const payer = Keypair.generate(); + const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); + await rpc.confirmTransaction(airdropSig, "confirmed"); + console.log("Payer:", payer.publicKey.toBase58()); - // 2. Create a light-mint (payer is mint authority) - const mintSigner = Keypair.generate(); - const { mint } = await createMintInterface( - rpc, - payer, - payer, - null, - 9, - mintSigner, - ); - console.log("Mint created:", mint.toBase58()); + // 2. Create a light-mint (payer is mint authority) + const mintSigner = Keypair.generate(); + const { mint } = await createMintInterface( + rpc, + payer, + payer, + null, + 9, + mintSigner, + ); + console.log("Mint created:", mint.toBase58()); - // 3. Create associated token account for recipient - const recipient = Keypair.generate(); - await createAtaInterface(rpc, payer, mint, recipient.publicKey); - const destination = getAssociatedTokenAddressInterface(mint, recipient.publicKey); - console.log("Recipient ATA created:", destination.toBase58()); + // 3. Create associated token account for recipient + const recipient = Keypair.generate(); + await createAtaInterface(rpc, payer, mint, recipient.publicKey); + const destination = getAssociatedTokenAddressInterface( + mint, + recipient.publicKey, + ); + console.log("Recipient ATA created:", destination.toBase58()); - // 4. Get mint interface (includes merkle context for c-tokens) - const mintInterface = await getMintInterface(rpc, mint); + // 4. Get mint interface (includes merkle context for c-tokens) + const mintInterface = await getMintInterface(rpc, mint); - // 5. Get validity proof for the mint (required for c-token mints) - let validityProof; - if (mintInterface.merkleContext) { - validityProof = await rpc.getValidityProofV2( - [ - { - hash: bn(mintInterface.merkleContext.hash), - leafIndex: mintInterface.merkleContext.leafIndex, - treeInfo: mintInterface.merkleContext.treeInfo, - proveByIndex: mintInterface.merkleContext.proveByIndex, - }, - ], - [], - DerivationMode.compressible, - ); - } + // 5. Get validity proof for the mint (required for c-token mints) + let validityProof; + if (mintInterface.merkleContext) { + validityProof = await rpc.getValidityProofV2( + [ + { + hash: bn(mintInterface.merkleContext.hash), + leafIndex: mintInterface.merkleContext.leafIndex, + treeInfo: mintInterface.merkleContext.treeInfo, + proveByIndex: mintInterface.merkleContext.proveByIndex, + }, + ], + [], + DerivationMode.compressible, + ); + } - // 6. Create instruction - const amount = 1_000_000_000; - const ix = createMintToInterfaceInstruction( - mintInterface, - destination, - payer.publicKey, // authority - payer.publicKey, // payer - amount, - validityProof, - ); + // 6. Create instruction + const amount = 1_000_000_000; + const ix = createMintToInterfaceInstruction( + mintInterface, + destination, + payer.publicKey, // authority + payer.publicKey, // payer + amount, + validityProof, + ); - // 7. Build, sign, and send transaction - const { blockhash } = await rpc.getLatestBlockhash(); - const tx = buildAndSignTx( - [ComputeBudgetProgram.setComputeUnitLimit({ units: 500_000 }), ix], - payer, - blockhash, - ); - const signature = await sendAndConfirmTx(rpc, tx); + // 7. Build, sign, and send transaction + const { blockhash } = await rpc.getLatestBlockhash(); + const tx = buildAndSignTx( + [ComputeBudgetProgram.setComputeUnitLimit({ units: 500_000 }), ix], + payer, + blockhash, + ); + const signature = await sendAndConfirmTx(rpc, tx); - console.log("Minted tokens:", amount); - console.log("Transaction:", signature); + console.log("Minted tokens:", amount); + console.log("Transaction:", signature); } main().catch(console.error); diff --git a/cookbook/instructions/transfer-interface.ts b/cookbook/instructions/transfer-interface.ts index 5217b53..709108a 100644 --- a/cookbook/instructions/transfer-interface.ts +++ b/cookbook/instructions/transfer-interface.ts @@ -1,83 +1,86 @@ import "dotenv/config"; import { Keypair, ComputeBudgetProgram } from "@solana/web3.js"; import { - createRpc, - buildAndSignTx, - sendAndConfirmTx, - featureFlags, - VERSION, + createRpc, + buildAndSignTx, + sendAndConfirmTx, + featureFlags, + VERSION, } from "@lightprotocol/stateless.js"; import { - createMintInterface, - createAtaInterface, - mintToInterface, - createTransferInterfaceInstruction, - getAssociatedTokenAddressInterface, + createMintInterface, + createAtaInterface, + mintToInterface, + createTransferInterfaceInstruction, + getAssociatedTokenAddressInterface, } from "@lightprotocol/compressed-token"; featureFlags.version = VERSION.V2; async function main() { - // 1. Setup RPC and fund payer - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); + // 1. Setup RPC and fund payer + const rpc = createRpc(); + const payer = Keypair.generate(); + const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); + await rpc.confirmTransaction(airdropSig, "confirmed"); + console.log("Payer:", payer.publicKey.toBase58()); - // 2. Create a light-mint - const mintSigner = Keypair.generate(); - const { mint } = await createMintInterface( - rpc, - payer, - payer, - null, - 9, - mintSigner - ); - console.log("Mint:", mint.toBase58()); + // 2. Create a light-mint + const mintSigner = Keypair.generate(); + const { mint } = await createMintInterface( + rpc, + payer, + payer, + null, + 9, + mintSigner, + ); + console.log("Mint:", mint.toBase58()); - // 3. Create sender's ATA and mint tokens - const sender = Keypair.generate(); - await createAtaInterface(rpc, payer, mint, sender.publicKey); - const senderAta = getAssociatedTokenAddressInterface(mint, sender.publicKey); - await mintToInterface(rpc, payer, mint, senderAta, payer, 1_000_000_000); - console.log("Sender ATA:", senderAta.toBase58()); + // 3. Create sender's ATA and mint tokens + const sender = Keypair.generate(); + await createAtaInterface(rpc, payer, mint, sender.publicKey); + const senderAta = getAssociatedTokenAddressInterface( + mint, + sender.publicKey, + ); + await mintToInterface(rpc, payer, mint, senderAta, payer, 1_000_000_000); + console.log("Sender ATA:", senderAta.toBase58()); - // 4. Create recipient's ATA - const recipient = Keypair.generate(); - await createAtaInterface(rpc, payer, mint, recipient.publicKey); - const recipientAta = getAssociatedTokenAddressInterface( - mint, - recipient.publicKey - ); - console.log("Recipient ATA:", recipientAta.toBase58()); + // 4. Create recipient's ATA + const recipient = Keypair.generate(); + await createAtaInterface(rpc, payer, mint, recipient.publicKey); + const recipientAta = getAssociatedTokenAddressInterface( + mint, + recipient.publicKey, + ); + console.log("Recipient ATA:", recipientAta.toBase58()); - // 5. Create transfer instruction - const amount = 500_000_000; - const ix = createTransferInterfaceInstruction( - senderAta, // source - recipientAta, // destination - sender.publicKey, // owner - amount - ); + // 5. Create transfer instruction + const amount = 500_000_000; + const ix = createTransferInterfaceInstruction( + senderAta, // source + recipientAta, // destination + sender.publicKey, // owner + amount, + ); - // 6. Build, sign, and send transaction - const { blockhash } = await rpc.getLatestBlockhash(); - const tx = buildAndSignTx( - [ComputeBudgetProgram.setComputeUnitLimit({ units: 10_000 }), ix], - payer, - blockhash, - [sender] - ); - const signature = await sendAndConfirmTx(rpc, tx); + // 6. Build, sign, and send transaction + const { blockhash } = await rpc.getLatestBlockhash(); + const tx = buildAndSignTx( + [ComputeBudgetProgram.setComputeUnitLimit({ units: 10_000 }), ix], + payer, + blockhash, + [sender], + ); + const signature = await sendAndConfirmTx(rpc, tx); - console.log("Transferred 0.5 tokens"); - console.log("Transaction:", signature); + console.log("Transferred 0.5 tokens"); + console.log("Transaction:", signature); } main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); + console.error("Error:", err); + if (err.logs) console.error("Logs:", err.logs); + process.exit(1); }); diff --git a/cookbook/instructions/unwrap.ts b/cookbook/instructions/unwrap.ts index ac689b9..8ab7359 100644 --- a/cookbook/instructions/unwrap.ts +++ b/cookbook/instructions/unwrap.ts @@ -1,101 +1,103 @@ import "dotenv/config"; import { Keypair, ComputeBudgetProgram } from "@solana/web3.js"; import { - createRpc, - buildAndSignTx, - sendAndConfirmTx, - dedupeSigner, - bn, + createRpc, + buildAndSignTx, + sendAndConfirmTx, + dedupeSigner, + bn, } from "@lightprotocol/stateless.js"; import { - createMint, - mintTo, - loadAta, - getAssociatedTokenAddressInterface, - getSplInterfaceInfos, + createMint, + mintTo, + loadAta, + getAssociatedTokenAddressInterface, + getSplInterfaceInfos, } from "@lightprotocol/compressed-token"; import { createUnwrapInstruction } from "@lightprotocol/compressed-token/unified"; import { createAssociatedTokenAccount } from "@solana/spl-token"; async function main() { - // 1. Setup RPC and fund accounts - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); + // 1. Setup RPC and fund accounts + const rpc = createRpc(); + const payer = Keypair.generate(); + const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); + await rpc.confirmTransaction(airdropSig, "confirmed"); + console.log("Payer:", payer.publicKey.toBase58()); - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); + const owner = Keypair.generate(); + const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); + await rpc.confirmTransaction(airdropSig2, "confirmed"); - // 2. Create SPL mint with token pool - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair - ); - console.log("Mint:", mint.toBase58()); + // 2. Create SPL mint with token pool + const mintAuthority = Keypair.generate(); + const mintKeypair = Keypair.generate(); + const { mint } = await createMint( + rpc, + payer, + mintAuthority.publicKey, + 9, + mintKeypair, + ); + console.log("Mint:", mint.toBase58()); - // 3. Mint compressed tokens to owner - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); - console.log("Minted 1000 compressed tokens"); + // 3. Mint compressed tokens to owner + await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); + console.log("Minted 1000 compressed tokens"); - // 4. Load compressed tokens to c-token ATA (hot balance) - const ctokenAta = getAssociatedTokenAddressInterface(mint, owner.publicKey); - await loadAta(rpc, ctokenAta, owner, mint, payer); - console.log("Loaded compressed tokens to c-token ATA"); + // 4. Load compressed tokens to c-token ATA (hot balance) + const ctokenAta = getAssociatedTokenAddressInterface(mint, owner.publicKey); + await loadAta(rpc, ctokenAta, owner, mint, payer); + console.log("Loaded compressed tokens to c-token ATA"); - // 5. Create destination SPL ATA - const splAta = await createAssociatedTokenAccount( - rpc, - payer, - mint, - owner.publicKey - ); - console.log("SPL ATA:", splAta.toBase58()); + // 5. Create destination SPL ATA + const splAta = await createAssociatedTokenAccount( + rpc, + payer, + mint, + owner.publicKey, + ); + console.log("SPL ATA:", splAta.toBase58()); - // 6. Get SPL interface info for the mint - const splInterfaceInfos = await getSplInterfaceInfos(rpc, mint); - const splInterfaceInfo = splInterfaceInfos.find((info) => info.isInitialized); + // 6. Get SPL interface info for the mint + const splInterfaceInfos = await getSplInterfaceInfos(rpc, mint); + const splInterfaceInfo = splInterfaceInfos.find( + (info) => info.isInitialized, + ); - if (!splInterfaceInfo) { - throw new Error("No SPL interface found"); - } + if (!splInterfaceInfo) { + throw new Error("No SPL interface found"); + } - // 7. Create unwrap instruction - const ix = createUnwrapInstruction( - ctokenAta, // source: c-token ATA - splAta, // destination: SPL token account - owner.publicKey, // owner of source account - mint, - bn(500), // amount to unwrap - splInterfaceInfo, // SPL interface info - payer.publicKey // fee payer - ); + // 7. Create unwrap instruction + const ix = createUnwrapInstruction( + ctokenAta, // source: c-token ATA + splAta, // destination: SPL token account + owner.publicKey, // owner of source account + mint, + bn(500), // amount to unwrap + splInterfaceInfo, // SPL interface info + payer.publicKey, // fee payer + ); - // 8. Build, sign, and send transaction - const { blockhash } = await rpc.getLatestBlockhash(); - const additionalSigners = dedupeSigner(payer, [owner]); + // 8. Build, sign, and send transaction + const { blockhash } = await rpc.getLatestBlockhash(); + const additionalSigners = dedupeSigner(payer, [owner]); - const tx = buildAndSignTx( - [ComputeBudgetProgram.setComputeUnitLimit({ units: 200_000 }), ix], - payer, - blockhash, - additionalSigners - ); + const tx = buildAndSignTx( + [ComputeBudgetProgram.setComputeUnitLimit({ units: 200_000 }), ix], + payer, + blockhash, + additionalSigners, + ); - const signature = await sendAndConfirmTx(rpc, tx); - console.log("Unwrapped 500 tokens to SPL ATA"); - console.log("Transaction:", signature); + const signature = await sendAndConfirmTx(rpc, tx); + console.log("Unwrapped 500 tokens to SPL ATA"); + console.log("Transaction:", signature); } main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); + console.error("Error:", err); + if (err.logs) console.error("Logs:", err.logs); + process.exit(1); }); diff --git a/cookbook/instructions/wrap.ts b/cookbook/instructions/wrap.ts index e37047c..7b5ed7b 100644 --- a/cookbook/instructions/wrap.ts +++ b/cookbook/instructions/wrap.ts @@ -1,102 +1,104 @@ import "dotenv/config"; import { Keypair, ComputeBudgetProgram } from "@solana/web3.js"; import { - createRpc, - buildAndSignTx, - sendAndConfirmTx, - dedupeSigner, - bn, + createRpc, + buildAndSignTx, + sendAndConfirmTx, + dedupeSigner, + bn, } from "@lightprotocol/stateless.js"; import { - createMint, - mintTo, - decompress, - createWrapInstruction, - getAssociatedTokenAddressInterface, - createAtaInterfaceIdempotent, - getSplInterfaceInfos, + createMint, + mintTo, + decompress, + createWrapInstruction, + getAssociatedTokenAddressInterface, + createAtaInterfaceIdempotent, + getSplInterfaceInfos, } from "@lightprotocol/compressed-token"; import { createAssociatedTokenAccount } from "@solana/spl-token"; async function main() { - // 1. Setup RPC and fund accounts - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); + // 1. Setup RPC and fund accounts + const rpc = createRpc(); + const payer = Keypair.generate(); + const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); + await rpc.confirmTransaction(airdropSig, "confirmed"); + console.log("Payer:", payer.publicKey.toBase58()); - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); + const owner = Keypair.generate(); + const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); + await rpc.confirmTransaction(airdropSig2, "confirmed"); - // 2. Create SPL mint with token pool - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair - ); - console.log("Mint:", mint.toBase58()); + // 2. Create SPL mint with token pool + const mintAuthority = Keypair.generate(); + const mintKeypair = Keypair.generate(); + const { mint } = await createMint( + rpc, + payer, + mintAuthority.publicKey, + 9, + mintKeypair, + ); + console.log("Mint:", mint.toBase58()); - // 3. Create SPL ATA and fund it - const splAta = await createAssociatedTokenAccount( - rpc, - payer, - mint, - owner.publicKey - ); - console.log("SPL ATA:", splAta.toBase58()); + // 3. Create SPL ATA and fund it + const splAta = await createAssociatedTokenAccount( + rpc, + payer, + mint, + owner.publicKey, + ); + console.log("SPL ATA:", splAta.toBase58()); - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); - await decompress(rpc, payer, mint, bn(1000), owner, splAta); - console.log("Funded SPL ATA with 1000 tokens"); + await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); + await decompress(rpc, payer, mint, bn(1000), owner, splAta); + console.log("Funded SPL ATA with 1000 tokens"); - // 4. Create c-token ATA (destination) - const ctokenAta = getAssociatedTokenAddressInterface(mint, owner.publicKey); - await createAtaInterfaceIdempotent(rpc, payer, mint, owner.publicKey); - console.log("c-token ATA:", ctokenAta.toBase58()); + // 4. Create c-token ATA (destination) + const ctokenAta = getAssociatedTokenAddressInterface(mint, owner.publicKey); + await createAtaInterfaceIdempotent(rpc, payer, mint, owner.publicKey); + console.log("c-token ATA:", ctokenAta.toBase58()); - // 5. Get SPL interface info for the mint - const splInterfaceInfos = await getSplInterfaceInfos(rpc, mint); - const splInterfaceInfo = splInterfaceInfos.find((info) => info.isInitialized); + // 5. Get SPL interface info for the mint + const splInterfaceInfos = await getSplInterfaceInfos(rpc, mint); + const splInterfaceInfo = splInterfaceInfos.find( + (info) => info.isInitialized, + ); - if (!splInterfaceInfo) { - throw new Error("No SPL interface found"); - } + if (!splInterfaceInfo) { + throw new Error("No SPL interface found"); + } - // 6. Create wrap instruction - const ix = createWrapInstruction( - splAta, // source: SPL token account - ctokenAta, // destination: c-token ATA - owner.publicKey, // owner of source account - mint, - bn(500), // amount to wrap - splInterfaceInfo, // SPL interface info - payer.publicKey // fee payer - ); + // 6. Create wrap instruction + const ix = createWrapInstruction( + splAta, // source: SPL token account + ctokenAta, // destination: c-token ATA + owner.publicKey, // owner of source account + mint, + bn(500), // amount to wrap + splInterfaceInfo, // SPL interface info + payer.publicKey, // fee payer + ); - // 7. Build, sign, and send transaction - const { blockhash } = await rpc.getLatestBlockhash(); - const additionalSigners = dedupeSigner(payer, [owner]); + // 7. Build, sign, and send transaction + const { blockhash } = await rpc.getLatestBlockhash(); + const additionalSigners = dedupeSigner(payer, [owner]); - const tx = buildAndSignTx( - [ComputeBudgetProgram.setComputeUnitLimit({ units: 200_000 }), ix], - payer, - blockhash, - additionalSigners - ); + const tx = buildAndSignTx( + [ComputeBudgetProgram.setComputeUnitLimit({ units: 200_000 }), ix], + payer, + blockhash, + additionalSigners, + ); - const signature = await sendAndConfirmTx(rpc, tx); - console.log("Wrapped 500 tokens to c-token ATA"); - console.log("Transaction:", signature); + const signature = await sendAndConfirmTx(rpc, tx); + console.log("Wrapped 500 tokens to c-token ATA"); + console.log("Transaction:", signature); } main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); + console.error("Error:", err); + if (err.logs) console.error("Logs:", err.logs); + process.exit(1); }); diff --git a/cookbook/package.json b/cookbook/package.json index 04fedc9..7afec3d 100644 --- a/cookbook/package.json +++ b/cookbook/package.json @@ -1,41 +1,41 @@ { - "name": "light-token-cookbook", - "version": "1.0.0", - "type": "module", - "description": "Working examples for light-token operations on Solana devnet", - "scripts": { - "create-mint:action": "node --loader ts-node/esm actions/create-mint.ts", - "create-mint:instruction": "node --loader ts-node/esm instructions/create-mint.ts", - "mint-to:action": "node --loader ts-node/esm actions/mint-to.ts", - "mint-to:instruction": "node --loader ts-node/esm instructions/mint-to.ts", - "transfer-interface:action": "node --loader ts-node/esm actions/transfer-interface.ts", - "transfer-interface:instruction": "node --loader ts-node/esm instructions/transfer-interface.ts", - "create-ata:action": "node --loader ts-node/esm actions/create-ata.ts", - "create-ata:instruction": "node --loader ts-node/esm instructions/create-ata.ts", - "compress:action": "node --loader ts-node/esm actions/compress.ts", - "compress:batch": "node --loader ts-node/esm actions/compress-batch.ts", - "decompress:action": "node --loader ts-node/esm actions/decompress.ts", - "decompress:with-token-pool": "node --loader ts-node/esm actions/decompress-with-token-pool.ts", - "wrap:action": "node --loader ts-node/esm actions/wrap.ts", - "wrap:instruction": "node --loader ts-node/esm instructions/wrap.ts", - "unwrap:action": "node --loader ts-node/esm actions/unwrap.ts", - "unwrap:instruction": "node --loader ts-node/esm instructions/unwrap.ts", - "load-ata:action": "node --loader ts-node/esm actions/load-ata.ts", - "load-ata:instruction": "node --loader ts-node/esm instructions/load-ata.ts", - "delegate:approve": "node --loader ts-node/esm actions/delegate-approve.ts", - "delegate:revoke": "node --loader ts-node/esm actions/delegate-revoke.ts", - "merge-accounts": "node --loader ts-node/esm actions/merge-token-accounts.ts" - }, - "dependencies": { - "@lightprotocol/compressed-token": "file:../light-protocol/js/compressed-token", - "@lightprotocol/stateless.js": "file:../light-protocol/js/stateless.js", - "@solana/spl-token": "^0.4.13", - "@solana/web3.js": "1.98.4", - "dotenv": "^16.5.0" - }, - "devDependencies": { - "@types/node": "^20.0.0", - "ts-node": "^10.9.2", - "typescript": "^5.0.0" - } + "name": "light-token-cookbook", + "version": "1.0.0", + "type": "module", + "description": "Working examples for light-token operations on Solana devnet", + "scripts": { + "create-mint:action": "ts-node-esm actions/create-mint.ts", + "create-mint:instruction": "ts-node-esm instructions/create-mint.ts", + "mint-to:action": "ts-node-esm actions/mint-to.ts", + "mint-to:instruction": "ts-node-esm instructions/mint-to.ts", + "transfer-interface:action": "ts-node-esm actions/transfer-interface.ts", + "transfer-interface:instruction": "ts-node-esm instructions/transfer-interface.ts", + "create-ata:action": "ts-node-esm actions/create-ata.ts", + "create-ata:instruction": "ts-node-esm instructions/create-ata.ts", + "compress:action": "ts-node-esm actions/compress.ts", + "compress:batch": "ts-node-esm actions/compress-batch.ts", + "decompress:action": "ts-node-esm actions/decompress.ts", + "decompress:with-token-pool": "ts-node-esm actions/decompress-with-token-pool.ts", + "wrap:action": "ts-node-esm actions/wrap.ts", + "wrap:instruction": "ts-node-esm instructions/wrap.ts", + "unwrap:action": "ts-node-esm actions/unwrap.ts", + "unwrap:instruction": "ts-node-esm instructions/unwrap.ts", + "load-ata:action": "ts-node-esm actions/load-ata.ts", + "load-ata:instruction": "ts-node-esm instructions/load-ata.ts", + "delegate:approve": "ts-node-esm actions/delegate-approve.ts", + "delegate:revoke": "ts-node-esm actions/delegate-revoke.ts", + "merge-accounts": "ts-node-esm actions/merge-token-accounts.ts" + }, + "dependencies": { + "@lightprotocol/compressed-token": "^0.22.1-alpha", + "@lightprotocol/stateless.js": "^0.22.1-alpha", + "@solana/spl-token": "^0.4.13", + "@solana/web3.js": "1.98.4", + "dotenv": "^16.5.0" + }, + "devDependencies": { + "@types/node": "^20.0.0", + "ts-node": "^10.9.2", + "typescript": "^5.0.0" + } } diff --git a/cookbook/tsconfig.json b/cookbook/tsconfig.json index c2c463d..de8ab73 100644 --- a/cookbook/tsconfig.json +++ b/cookbook/tsconfig.json @@ -1,15 +1,15 @@ { - "compilerOptions": { - "target": "ES2020", - "module": "Node16", - "moduleResolution": "Node16", - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "outDir": "./dist" - }, - "include": ["**/*.ts"], - "exclude": ["node_modules", "dist"] + "compilerOptions": { + "target": "ES2020", + "module": "Node16", + "moduleResolution": "Node16", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "outDir": "./dist" + }, + "include": ["**/*.ts"], + "exclude": ["node_modules", "dist"] } diff --git a/devnet-quickstart/.env.example b/devnet-quickstart/.env.example deleted file mode 100644 index 490c20c..0000000 --- a/devnet-quickstart/.env.example +++ /dev/null @@ -1,2 +0,0 @@ -api_key=your-helius-api-key-here -KEYPAIR_PATH=~/.config/solana/id.json diff --git a/devnet-quickstart/.gitignore b/devnet-quickstart/.gitignore deleted file mode 100644 index 87ae5ea..0000000 --- a/devnet-quickstart/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -node_modules/ -dist/ -.env -*.json.bak diff --git a/devnet-quickstart/index.ts b/devnet-quickstart/index.ts index d7d14d5..f2ce095 100644 --- a/devnet-quickstart/index.ts +++ b/devnet-quickstart/index.ts @@ -1,73 +1,81 @@ -import "dotenv/config"; +import dotenv from "dotenv"; import { Keypair } from "@solana/web3.js"; -import { readFileSync } from "fs"; -import { homedir } from "os"; import { - createRpc, - featureFlags, - VERSION, + bn, + createRpc, + selectStateTreeInfo, } from "@lightprotocol/stateless.js"; -import { - createMintInterface, - createAtaInterface, - mintToInterface, - getAssociatedTokenAddressInterface, -} from "@lightprotocol/compressed-token"; - -featureFlags.version = VERSION.V2; +import { createMint, mintTo } from "@lightprotocol/compressed-token"; +import { getOrCreateAtaInterface } from "@lightprotocol/compressed-token/unified"; +import { homedir } from "os"; +import { readFileSync } from "fs"; -// Load wallet from filesystem -const keypairPath = - process.env.KEYPAIR_PATH?.replace("~", homedir()) || - `${homedir()}/.config/solana/id.json`; +// Load wallet +const keypairPath = `${homedir()}/.config/solana/id.json`; const payer = Keypair.fromSecretKey( - new Uint8Array(JSON.parse(readFileSync(keypairPath, "utf8"))) + new Uint8Array(JSON.parse(readFileSync(keypairPath, "utf8"))) ); -// Helius exposes Solana and compression RPC endpoints through a single URL -const RPC_ENDPOINT = `https://devnet.helius-rpc.com?api-key=${process.env.api_key}`; +// You can use any compatible RPC endpoint +dotenv.config(); +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; async function main() { - // 1. Setup RPC connection - const rpc = createRpc(RPC_ENDPOINT, RPC_ENDPOINT, RPC_ENDPOINT); - console.log("Payer:", payer.publicKey.toBase58()); - - // 2. Create a light-mint (payer is mint authority) - const mintSigner = Keypair.generate(); - const { mint } = await createMintInterface( - rpc, - payer, - payer, // mintAuthority - null, // freezeAuthority - 9, // decimals - mintSigner, - ); - console.log("Mint created:", mint.toBase58()); + const rpc = createRpc(RPC_URL); + const infos = await rpc.getStateTreeInfos(); + const treeInfo = selectStateTreeInfo(infos); + console.log(treeInfo); - // 3. Create associated token account for recipient - const recipient = Keypair.generate(); - await createAtaInterface(rpc, payer, mint, recipient.publicKey); - console.log("Recipient ATA created for:", recipient.publicKey.toBase58()); + // Create an SPL mint + enable compression. + const mintAuthority = Keypair.generate(); + const mintSigner = Keypair.generate(); + const { mint, transactionSignature: createMintSig } = await createMint( + rpc, + payer, + mintAuthority.publicKey, + 9, + mintSigner + ); - // 4. Mint tokens to the recipient's account - const destination = getAssociatedTokenAddressInterface(mint, recipient.publicKey); - const amount = 1_000_000_000; // 1 token with 9 decimals + // Mint compressed tokens to a recipient (owner pubkey). + const recipient = Keypair.generate(); + const amount = bn(1_000_000_000); + const mintToSig = await mintTo( + rpc, + payer, + mint, + recipient.publicKey, + mintAuthority, + amount, + treeInfo + ); - const txSignature = await mintToInterface( - rpc, - payer, - mint, - destination, - payer, // mintAuthority (must be Signer) - amount, - ); + // Create/load the recipient's c-token ATA interface (loads cold balance to hot). + const recipientAccount = await getOrCreateAtaInterface( + rpc, + payer, + mint, + recipient + ); - console.log("Minted tokens:", amount); - console.log(`Transaction: https://explorer.solana.com/tx/${txSignature}?cluster=devnet`); + console.log( + JSON.stringify( + { + payer: payer.publicKey.toBase58(), + mint: mint.toBase58(), + recipient: recipient.publicKey.toBase58(), + recipientAta: recipientAccount.parsed.address.toBase58(), + recipientBalance: recipientAccount.parsed.amount.toString(), + createMintTx: createMintSig, + mintTx: mintToSig, + }, + null, + 2 + ) + ); } main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); + console.error(err); + process.exit(1); }); diff --git a/devnet-quickstart/package.json b/devnet-quickstart/package.json index 21bbb6d..f3f69de 100644 --- a/devnet-quickstart/package.json +++ b/devnet-quickstart/package.json @@ -1,18 +1,18 @@ { - "name": "devnet-quickstart", - "type": "module", - "scripts": { - "test": "node --loader ts-node/esm index.ts" - }, - "dependencies": { - "@lightprotocol/compressed-token": "0.22.1-alpha.3", - "@lightprotocol/stateless.js": "0.22.1-alpha.2", - "@solana/web3.js": "1.98.4", - "dotenv": "^16.5.0" - }, - "devDependencies": { - "@types/node": "^20.0.0", - "ts-node": "^10.9.2", - "typescript": "^5.0.0" - } + "name": "devnet-quickstart", + "type": "module", + "scripts": { + "start": "cd .. && ts-node-esm devnet-quickstart/index.ts" + }, + "dependencies": { + "@lightprotocol/compressed-token": "^0.22.1-alpha", + "@lightprotocol/stateless.js": "^0.22.1-alpha", + "@solana/web3.js": "1.98.4", + "dotenv": "^16.5.0" + }, + "devDependencies": { + "@types/node": "^20.0.0", + "ts-node": "^10.9.2", + "typescript": "^5.0.0" + } } diff --git a/devnet-quickstart/tsconfig.json b/devnet-quickstart/tsconfig.json index c2c463d..de8ab73 100644 --- a/devnet-quickstart/tsconfig.json +++ b/devnet-quickstart/tsconfig.json @@ -1,15 +1,15 @@ { - "compilerOptions": { - "target": "ES2020", - "module": "Node16", - "moduleResolution": "Node16", - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "outDir": "./dist" - }, - "include": ["**/*.ts"], - "exclude": ["node_modules", "dist"] + "compilerOptions": { + "target": "ES2020", + "module": "Node16", + "moduleResolution": "Node16", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "outDir": "./dist" + }, + "include": ["**/*.ts"], + "exclude": ["node_modules", "dist"] } diff --git a/package.json b/package.json new file mode 100644 index 0000000..8d3195f --- /dev/null +++ b/package.json @@ -0,0 +1,14 @@ +{ + "name": "examples-light-token", + "private": true, + "workspaces": [ + "devnet-quickstart", + "cookbook", + "toolkits/payments-and-wallets" + ], + "scripts": { + "quickstart": "npm run -w devnet-quickstart start", + "cookbook": "npm run -w cookbook", + "toolkit:payments": "npm run -w toolkits/payments-and-wallets" + } +} diff --git a/toolkits/payments-and-wallets/README.md b/toolkits/payments-and-wallets/README.md index ba54a6e..028d2c5 100644 --- a/toolkits/payments-and-wallets/README.md +++ b/toolkits/payments-and-wallets/README.md @@ -2,25 +2,24 @@ ## SPL vs Light -| Operation | SPL | Light | -|-----------|-----|-------| -| Get/Create ATA | `getOrCreateAssociatedTokenAccount()` | `getOrCreateAtaInterface()` | -| Derive ATA | `getAssociatedTokenAddress()` | `getAssociatedTokenAddressInterface()` | -| Transfer | `transferChecked()` | `transferInterface()` | -| Get Balance | `getAccount()` | `getAtaInterface()` | -| Tx History | `getSignaturesForAddress()` | `rpc.getSignaturesForOwnerInterface()` | -| Exit to SPL | N/A | `unwrap()` | +| Operation | SPL | Light | +| -------------- | ------------------------------------- | -------------------------------------- | +| Get/Create ATA | `getOrCreateAssociatedTokenAccount()` | `getOrCreateAtaInterface()` | +| Derive ATA | `getAssociatedTokenAddress()` | `getAssociatedTokenAddressInterface()` | +| Transfer | `transferChecked()` | `transferInterface()` | +| Get Balance | `getAccount()` | `getAtaInterface()` | +| Tx History | `getSignaturesForAddress()` | `rpc.getSignaturesForOwnerInterface()` | +| Exit to SPL | N/A | `unwrap()` | ## Scripts -| File | Description | Key Function | -|------|-------------|--------------| -| `send-and-receive.ts` | Send/receive payments | `getOrCreateAtaInterface`, `transferInterface` | -| `get-balance.ts` | Check token balance | `getAtaInterface` | -| `get-history.ts` | Transaction history | `getSignaturesForOwnerInterface` | -| `wrap-from-spl.ts` | On-ramp from CEX (SPL → light-token) | `wrap` | -| `unwrap-to-spl.ts` | Off-ramp to CEX (light-token → SPL) | `unwrap` | - +| File | Description | Key Function | +| --------------------- | ------------------------------------ | ---------------------------------------------- | +| `send-and-receive.ts` | Send/receive payments | `getOrCreateAtaInterface`, `transferInterface` | +| `get-balance.ts` | Check token balance | `getAtaInterface` | +| `get-history.ts` | Transaction history | `getSignaturesForOwnerInterface` | +| `wrap.ts` | On-ramp from CEX (SPL → light-token) | `wrap` | +| `unwrap.ts` | Off-ramp to CEX (light-token → SPL) | `unwrap` | ## Get Started @@ -38,6 +37,6 @@ light test-validator pnpm run send-and-receive pnpm run get-balance pnpm run get-history -pnpm run wrap-from-spl -pnpm run unwrap-to-spl -``` \ No newline at end of file +pnpm run wrap +pnpm run unwrap +``` diff --git a/toolkits/payments-and-wallets/comparison-spl-light.md b/toolkits/payments-and-wallets/comparison-spl-light.md index a9f450a..ad35418 100644 --- a/toolkits/payments-and-wallets/comparison-spl-light.md +++ b/toolkits/payments-and-wallets/comparison-spl-light.md @@ -6,7 +6,7 @@ ## Quick Reference -| Operation | SPL | Light | +| Operation | SPL | Light | | -------------- | ------------------------------------- | -------------------------------------- | | Get/Create ATA | `getOrCreateAssociatedTokenAccount()` | `getOrCreateAtaInterface()` | | Derive ATA | `getAssociatedTokenAddress()` | `getAssociatedTokenAddressInterface()` | @@ -21,11 +21,11 @@ import { createRpc } from "@lightprotocol/stateless.js"; import { - getOrCreateAtaInterface, - getAtaInterface, - getAssociatedTokenAddressInterface, - transferInterface, - unwrap, + getOrCreateAtaInterface, + getAtaInterface, + getAssociatedTokenAddressInterface, + transferInterface, + unwrap, } from "@lightprotocol/compressed-token/unified"; const rpc = createRpc(RPC_ENDPOINT); @@ -43,10 +43,10 @@ const rpc = createRpc(RPC_ENDPOINT); import { getOrCreateAssociatedTokenAccount } from "@solana/spl-token"; const ata = await getOrCreateAssociatedTokenAccount( - connection, - payer, - mint, - recipient + connection, + payer, + mint, + recipient, ); // Share ata.address with sender @@ -59,19 +59,19 @@ console.log(ata.amount); ```typescript import { - getAssociatedTokenAddressSync, - createAssociatedTokenAccountIdempotentInstruction, + getAssociatedTokenAddressSync, + createAssociatedTokenAccountIdempotentInstruction, } from "@solana/spl-token"; const ata = getAssociatedTokenAddressSync(mint, recipient); const tx = new Transaction().add( - createAssociatedTokenAccountIdempotentInstruction( - payer.publicKey, - ata, - recipient, - mint - ) + createAssociatedTokenAccountIdempotentInstruction( + payer.publicKey, + ata, + recipient, + mint, + ), ); ``` @@ -88,29 +88,29 @@ console.log(ata.parsed.amount); ```typescript import { - createAssociatedTokenAccountInterfaceIdempotentInstruction, - createLoadAtaInstructions, - getAssociatedTokenAddressInterface, + createAssociatedTokenAccountInterfaceIdempotentInstruction, + createLoadAtaInstructions, + getAssociatedTokenAddressInterface, } from "@lightprotocol/compressed-token/unified"; import { CTOKEN_PROGRAM_ID } from "@lightprotocol/stateless.js"; const ata = getAssociatedTokenAddressInterface(mint, recipient); const tx = new Transaction().add( - createAssociatedTokenAccountInterfaceIdempotentInstruction( - payer.publicKey, - ata, - recipient, - mint, - CTOKEN_PROGRAM_ID - ), - ...(await createLoadAtaInstructions( - rpc, - ata, - recipient, - mint, - payer.publicKey - )) + createAssociatedTokenAccountInterfaceIdempotentInstruction( + payer.publicKey, + ata, + recipient, + mint, + CTOKEN_PROGRAM_ID, + ), + ...(await createLoadAtaInstructions( + rpc, + ata, + recipient, + mint, + payer.publicKey, + )), ); ``` @@ -128,13 +128,13 @@ const sourceAta = getAssociatedTokenAddressSync(mint, owner.publicKey); const destinationAta = getAssociatedTokenAddressSync(mint, recipient); await transfer( - connection, - payer, - sourceAta, - destinationAta, - owner, - amount, - decimals + connection, + payer, + sourceAta, + destinationAta, + owner, + amount, + decimals, ); ``` @@ -144,15 +144,20 @@ await transfer( ```typescript import { - getAssociatedTokenAddressSync, - createTransferInstruction, + getAssociatedTokenAddressSync, + createTransferInstruction, } from "@solana/spl-token"; const sourceAta = getAssociatedTokenAddressSync(mint, owner.publicKey); const destinationAta = getAssociatedTokenAddressSync(mint, recipient); const tx = new Transaction().add( - createTransferInstruction(sourceAta, destinationAta, owner.publicKey, amount) + createTransferInstruction( + sourceAta, + destinationAta, + owner.publicKey, + amount, + ), ); ``` @@ -163,13 +168,13 @@ const sourceAta = getAssociatedTokenAddressInterface(mint, owner.publicKey); const destinationAta = getAssociatedTokenAddressInterface(mint, recipient); await transferInterface( - rpc, - payer, - sourceAta, - mint, - destinationAta, - owner, - amount + rpc, + payer, + sourceAta, + mint, + destinationAta, + owner, + amount, ); ``` @@ -177,28 +182,28 @@ await transferInterface( ```typescript import { - createLoadAtaInstructions, - createTransferInterfaceInstruction, - getAssociatedTokenAddressInterface, + createLoadAtaInstructions, + createTransferInterfaceInstruction, + getAssociatedTokenAddressInterface, } from "@lightprotocol/compressed-token/unified"; const sourceAta = getAssociatedTokenAddressInterface(mint, owner.publicKey); const destinationAta = getAssociatedTokenAddressInterface(mint, recipient); const tx = new Transaction().add( - ...(await createLoadAtaInstructions( - rpc, - sourceAta, - owner.publicKey, - mint, - payer.publicKey - )), - createTransferInterfaceInstruction( - sourceAta, - destinationAta, - owner.publicKey, - amount - ) + ...(await createLoadAtaInstructions( + rpc, + sourceAta, + owner.publicKey, + mint, + payer.publicKey, + )), + createTransferInterfaceInstruction( + sourceAta, + destinationAta, + owner.publicKey, + amount, + ), ); ``` @@ -208,16 +213,16 @@ To ensure your recipient's ATA exists you can prepend an idempotent creation ins ```typescript import { - getAssociatedTokenAddressSync, - createAssociatedTokenAccountIdempotentInstruction, + getAssociatedTokenAddressSync, + createAssociatedTokenAccountIdempotentInstruction, } from "@solana/spl-token"; const destinationAta = getAssociatedTokenAddressSync(mint, recipient); const createAtaIx = createAssociatedTokenAccountIdempotentInstruction( - payer.publicKey, - destinationAta, - recipient, - mint + payer.publicKey, + destinationAta, + recipient, + mint, ); new Transaction().add(createAtaIx, transferIx); @@ -227,18 +232,18 @@ new Transaction().add(createAtaIx, transferIx); ```typescript import { - getAssociatedTokenAddressInterface, - createAssociatedTokenAccountInterfaceIdempotentInstruction, + getAssociatedTokenAddressInterface, + createAssociatedTokenAccountInterfaceIdempotentInstruction, } from "@lightprotocol/compressed-token/unified"; import { CTOKEN_PROGRAM_ID } from "@lightprotocol/stateless.js"; const destinationAta = getAssociatedTokenAddressInterface(mint, recipient); const createAtaIx = createAssociatedTokenAccountInterfaceIdempotentInstruction( - payer.publicKey, - destinationAta, - recipient, - mint, - CTOKEN_PROGRAM_ID + payer.publicKey, + destinationAta, + recipient, + mint, + CTOKEN_PROGRAM_ID, ); new Transaction().add(createAtaIx, transferIx); @@ -319,9 +324,9 @@ await unwrap(rpc, payer, owner, mint, splAta, amount); ```typescript import { getAssociatedTokenAddressSync } from "@solana/spl-token"; import { - createLoadAtaInstructions, - createUnwrapInstruction, - getAssociatedTokenAddressInterface, + createLoadAtaInstructions, + createUnwrapInstruction, + getAssociatedTokenAddressInterface, } from "@lightprotocol/compressed-token/unified"; import { getSplInterfaceInfos } from "@lightprotocol/compressed-token"; @@ -332,20 +337,20 @@ const splInterfaceInfos = await getSplInterfaceInfos(rpc, mint); const splInterfaceInfo = splInterfaceInfos.find((i) => i.isInitialized); const tx = new Transaction().add( - ...(await createLoadAtaInstructions( - rpc, - ctokenAta, - owner.publicKey, - mint, - payer.publicKey - )), - createUnwrapInstruction( - ctokenAta, - splAta, - owner.publicKey, - mint, - amount, - splInterfaceInfo - ) + ...(await createLoadAtaInstructions( + rpc, + ctokenAta, + owner.publicKey, + mint, + payer.publicKey, + )), + createUnwrapInstruction( + ctokenAta, + splAta, + owner.publicKey, + mint, + amount, + splInterfaceInfo, + ), ); ``` diff --git a/toolkits/payments-and-wallets/get-balance.ts b/toolkits/payments-and-wallets/get-balance.ts index 4d223a9..fc7b3a2 100644 --- a/toolkits/payments-and-wallets/get-balance.ts +++ b/toolkits/payments-and-wallets/get-balance.ts @@ -1,53 +1,54 @@ +import "dotenv/config"; import { Keypair } from "@solana/web3.js"; import { createRpc, bn } from "@lightprotocol/stateless.js"; import { createMint, mintTo } from "@lightprotocol/compressed-token"; import { - getAtaInterface, - getAssociatedTokenAddressInterface, - getOrCreateAtaInterface, + getAtaInterface, + getAssociatedTokenAddressInterface, + getOrCreateAtaInterface, } from "@lightprotocol/compressed-token/unified"; async function main() { - const rpc = createRpc(); - - // Setup - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); - - // Create test mint and tokens - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair - ); - - // Mint tokens (creates cold balance) - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); - - // Create ATA and load cold to hot - await getOrCreateAtaInterface(rpc, payer, mint, owner); - - // === GET BALANCE === - const ata = getAssociatedTokenAddressInterface(mint, owner.publicKey); - const account = await getAtaInterface(rpc, ata, owner.publicKey, mint); - - console.log("ATA:", ata.toBase58()); - console.log("Balance:", account.parsed.amount.toString()); - - // Show balance breakdown by source - console.log("\n=== Balance Sources ==="); - for (const source of account._sources ?? []) { - console.log(`${source.type}: ${source.amount.toString()}`); - } + const rpc = createRpc(); + + // Setup + const payer = Keypair.generate(); + const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); + await rpc.confirmTransaction(airdropSig, "confirmed"); + + const owner = Keypair.generate(); + const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); + await rpc.confirmTransaction(airdropSig2, "confirmed"); + + // Create test mint and tokens + const mintAuthority = Keypair.generate(); + const mintKeypair = Keypair.generate(); + const { mint } = await createMint( + rpc, + payer, + mintAuthority.publicKey, + 9, + mintKeypair + ); + + // Mint tokens (creates cold balance) + await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); + + // Create ATA and load cold to hot + await getOrCreateAtaInterface(rpc, payer, mint, owner); + + // === GET BALANCE === + const ata = getAssociatedTokenAddressInterface(mint, owner.publicKey); + const account = await getAtaInterface(rpc, ata, owner.publicKey, mint); + + console.log("ATA:", ata.toBase58()); + console.log("Balance:", account.parsed.amount.toString()); + + // Show balance breakdown by source + console.log("\n=== Balance Sources ==="); + for (const source of account._sources ?? []) { + console.log(`${source.type}: ${source.amount.toString()}`); + } } main().catch(console.error); diff --git a/toolkits/payments-and-wallets/get-history.ts b/toolkits/payments-and-wallets/get-history.ts index 2c11b34..7b15c05 100644 --- a/toolkits/payments-and-wallets/get-history.ts +++ b/toolkits/payments-and-wallets/get-history.ts @@ -1,63 +1,83 @@ +import "dotenv/config"; import { Keypair } from "@solana/web3.js"; import { createRpc, bn } from "@lightprotocol/stateless.js"; import { createMint, mintTo } from "@lightprotocol/compressed-token"; import { - getOrCreateAtaInterface, - getAssociatedTokenAddressInterface, - transferInterface, + getOrCreateAtaInterface, + getAssociatedTokenAddressInterface, + transferInterface, } from "@lightprotocol/compressed-token/unified"; async function main() { - const rpc = createRpc(); - - // Setup - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); - - const recipient = Keypair.generate(); - const airdropSig3 = await rpc.requestAirdrop(recipient.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig3, "confirmed"); - - // Create test mint and tokens - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair - ); - - // Mint and create ATAs - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); - await getOrCreateAtaInterface(rpc, payer, mint, owner); - await getOrCreateAtaInterface(rpc, payer, mint, recipient); - - // Make a transfer to create transaction history - const sourceAta = getAssociatedTokenAddressInterface(mint, owner.publicKey); - const destAta = getAssociatedTokenAddressInterface(mint, recipient.publicKey); - - await transferInterface(rpc, payer, sourceAta, mint, destAta, owner, bn(100)); - await transferInterface(rpc, payer, sourceAta, mint, destAta, owner, bn(200)); - - // === GET TRANSACTION HISTORY === - const result = await rpc.getSignaturesForOwnerInterface(owner.publicKey); - - console.log("=== Transaction History ==="); - console.log("Total signatures:", result.signatures.length); - console.log("On-chain txs:", result.solana.length); - console.log("Compressed txs:", result.compressed.length); - - console.log("\n=== Recent Transactions ==="); - for (const sig of result.signatures.slice(0, 5)) { - console.log(sig.signature); - } + const rpc = createRpc(); + + // Setup + const payer = Keypair.generate(); + const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); + await rpc.confirmTransaction(airdropSig, "confirmed"); + + const owner = Keypair.generate(); + const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); + await rpc.confirmTransaction(airdropSig2, "confirmed"); + + const recipient = Keypair.generate(); + const airdropSig3 = await rpc.requestAirdrop(recipient.publicKey, 1e9); + await rpc.confirmTransaction(airdropSig3, "confirmed"); + + // Create test mint and tokens + const mintAuthority = Keypair.generate(); + const mintKeypair = Keypair.generate(); + const { mint } = await createMint( + rpc, + payer, + mintAuthority.publicKey, + 9, + mintKeypair + ); + + // Mint and create ATAs + await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); + await getOrCreateAtaInterface(rpc, payer, mint, owner); + await getOrCreateAtaInterface(rpc, payer, mint, recipient); + + // Make a transfer to create transaction history + const sourceAta = getAssociatedTokenAddressInterface(mint, owner.publicKey); + const destAta = getAssociatedTokenAddressInterface( + mint, + recipient.publicKey + ); + + await transferInterface( + rpc, + payer, + sourceAta, + mint, + destAta, + owner, + bn(100) + ); + await transferInterface( + rpc, + payer, + sourceAta, + mint, + destAta, + owner, + bn(200) + ); + + // === GET TRANSACTION HISTORY === + const result = await rpc.getSignaturesForOwnerInterface(owner.publicKey); + + console.log("=== Transaction History ==="); + console.log("Total signatures:", result.signatures.length); + console.log("On-chain txs:", result.solana.length); + console.log("Compressed txs:", result.compressed.length); + + console.log("\n=== Recent Transactions ==="); + for (const sig of result.signatures.slice(0, 5)) { + console.log(sig.signature); + } } main().catch(console.error); diff --git a/toolkits/payments-and-wallets/package.json b/toolkits/payments-and-wallets/package.json index 21a46dd..1d4c25f 100644 --- a/toolkits/payments-and-wallets/package.json +++ b/toolkits/payments-and-wallets/package.json @@ -1,23 +1,24 @@ { - "name": "light-token-toolkit-payments", - "version": "1.0.0", - "description": "Light Token Payments Toolkit Examples", - "type": "module", - "scripts": { - "send-and-receive": "node --loader ts-node/esm send-and-receive.ts", - "get-balance": "node --loader ts-node/esm get-balance.ts", - "get-history": "node --loader ts-node/esm get-history.ts", - "wrap-from-spl": "node --loader ts-node/esm wrap-from-spl.ts", - "unwrap-to-spl": "node --loader ts-node/esm unwrap-to-spl.ts" - }, - "dependencies": { - "@lightprotocol/compressed-token": "file:../../light-protocol/js/compressed-token", - "@lightprotocol/stateless.js": "file:../../light-protocol/js/stateless.js", - "@solana/spl-token": "^0.4.13", - "@solana/web3.js": "1.98.4" - }, - "devDependencies": { - "ts-node": "^10.9.2", - "typescript": "^5.7.2" - } + "name": "light-token-toolkit-payments", + "version": "1.0.0", + "description": "Light Token Payments Toolkit Examples", + "type": "module", + "scripts": { + "send-and-receive": "ts-node-esm send-and-receive.ts", + "get-balance": "ts-node-esm get-balance.ts", + "get-history": "ts-node-esm get-history.ts", + "wrap": "ts-node-esm wrap.ts", + "unwrap": "ts-node-esm unwrap.ts" + }, + "dependencies": { + "@lightprotocol/compressed-token": "^0.22.1-alpha", + "@lightprotocol/stateless.js": "^0.22.1-alpha", + "@solana/spl-token": "^0.4.13", + "@solana/web3.js": "1.98.4", + "dotenv": "^16.5.0" + }, + "devDependencies": { + "ts-node": "^10.9.2", + "typescript": "^5.7.2" + } } diff --git a/toolkits/payments-and-wallets/send-and-receive.ts b/toolkits/payments-and-wallets/send-and-receive.ts index 8392a41..0b2123a 100644 --- a/toolkits/payments-and-wallets/send-and-receive.ts +++ b/toolkits/payments-and-wallets/send-and-receive.ts @@ -1,95 +1,112 @@ +import "dotenv/config"; import { Keypair } from "@solana/web3.js"; import { createRpc, bn } from "@lightprotocol/stateless.js"; +import { createMint, mintTo } from "@lightprotocol/compressed-token"; import { - createMint, - mintTo, -} from "@lightprotocol/compressed-token"; -import { - getOrCreateAtaInterface, - getAssociatedTokenAddressInterface, - transferInterface, + getOrCreateAtaInterface, + getAssociatedTokenAddressInterface, + transferInterface, } from "@lightprotocol/compressed-token/unified"; async function main() { - const rpc = createRpc(); + const rpc = createRpc(); - // Setup wallets - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); + // Setup wallets + const payer = Keypair.generate(); + const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); + await rpc.confirmTransaction(airdropSig, "confirmed"); - const sender = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(sender.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); + const sender = Keypair.generate(); + const airdropSig2 = await rpc.requestAirdrop(sender.publicKey, 1e9); + await rpc.confirmTransaction(airdropSig2, "confirmed"); - const recipient = Keypair.generate(); - const airdropSig3 = await rpc.requestAirdrop(recipient.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig3, "confirmed"); + const recipient = Keypair.generate(); + const airdropSig3 = await rpc.requestAirdrop(recipient.publicKey, 1e9); + await rpc.confirmTransaction(airdropSig3, "confirmed"); - console.log("Sender:", sender.publicKey.toBase58()); - console.log("Recipient:", recipient.publicKey.toBase58()); + console.log("Sender:", sender.publicKey.toBase58()); + console.log("Recipient:", recipient.publicKey.toBase58()); - // Create a test mint (in production, use existing stablecoin mint) - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair - ); - console.log("Mint:", mint.toBase58()); + // Create a test mint (in production, use existing stablecoin mint) + const mintAuthority = Keypair.generate(); + const mintKeypair = Keypair.generate(); + const { mint } = await createMint( + rpc, + payer, + mintAuthority.publicKey, + 9, + mintKeypair, + ); + console.log("Mint:", mint.toBase58()); - // Mint tokens to sender - await mintTo(rpc, payer, mint, sender.publicKey, mintAuthority, bn(1000)); - console.log("Minted 1000 tokens to sender"); + // Mint tokens to sender + await mintTo(rpc, payer, mint, sender.publicKey, mintAuthority, bn(1000)); + console.log("Minted 1000 tokens to sender"); - // === RECEIVE: Get/create sender's ATA === - // This creates the ATA and loads any cold balance to hot - const senderAccount = await getOrCreateAtaInterface( - rpc, - payer, - mint, - sender // Signer enables auto-load - ); - console.log("\nSender ATA:", senderAccount.parsed.address.toBase58()); - console.log("Sender balance:", senderAccount.parsed.amount.toString()); + // === RECEIVE: Get/create sender's ATA === + // This creates the ATA and loads any cold balance to hot + const senderAccount = await getOrCreateAtaInterface( + rpc, + payer, + mint, + sender, // Signer enables auto-load + ); + console.log("\nSender ATA:", senderAccount.parsed.address.toBase58()); + console.log("Sender balance:", senderAccount.parsed.amount.toString()); - // === RECEIVE: Get/create recipient's ATA === - const recipientAccount = await getOrCreateAtaInterface( - rpc, - payer, - mint, - recipient - ); - console.log("\nRecipient ATA:", recipientAccount.parsed.address.toBase58()); - console.log("Recipient balance before:", recipientAccount.parsed.amount.toString()); + // === RECEIVE: Get/create recipient's ATA === + const recipientAccount = await getOrCreateAtaInterface( + rpc, + payer, + mint, + recipient, + ); + console.log("\nRecipient ATA:", recipientAccount.parsed.address.toBase58()); + console.log( + "Recipient balance before:", + recipientAccount.parsed.amount.toString(), + ); - // === SEND: Transfer tokens === - const sourceAta = getAssociatedTokenAddressInterface(mint, sender.publicKey); - const destinationAta = getAssociatedTokenAddressInterface(mint, recipient.publicKey); + // === SEND: Transfer tokens === + const sourceAta = getAssociatedTokenAddressInterface( + mint, + sender.publicKey, + ); + const destinationAta = getAssociatedTokenAddressInterface( + mint, + recipient.publicKey, + ); - const signature = await transferInterface( - rpc, - payer, - sourceAta, - mint, - destinationAta, - sender, - bn(500) - ); + const signature = await transferInterface( + rpc, + payer, + sourceAta, + mint, + destinationAta, + sender, + bn(500), + ); - console.log("\nTransferred 500 tokens"); - console.log("Transaction:", signature); + console.log("\nTransferred 500 tokens"); + console.log("Transaction:", signature); - // Check final balances - const senderFinal = await getOrCreateAtaInterface(rpc, payer, mint, sender.publicKey); - const recipientFinal = await getOrCreateAtaInterface(rpc, payer, mint, recipient.publicKey); + // Check final balances + const senderFinal = await getOrCreateAtaInterface( + rpc, + payer, + mint, + sender.publicKey, + ); + const recipientFinal = await getOrCreateAtaInterface( + rpc, + payer, + mint, + recipient.publicKey, + ); - console.log("\n=== Final Balances ==="); - console.log("Sender:", senderFinal.parsed.amount.toString()); - console.log("Recipient:", recipientFinal.parsed.amount.toString()); + console.log("\n=== Final Balances ==="); + console.log("Sender:", senderFinal.parsed.amount.toString()); + console.log("Recipient:", recipientFinal.parsed.amount.toString()); } main().catch(console.error); diff --git a/toolkits/payments-and-wallets/tsconfig.json b/toolkits/payments-and-wallets/tsconfig.json index c2c463d..de8ab73 100644 --- a/toolkits/payments-and-wallets/tsconfig.json +++ b/toolkits/payments-and-wallets/tsconfig.json @@ -1,15 +1,15 @@ { - "compilerOptions": { - "target": "ES2020", - "module": "Node16", - "moduleResolution": "Node16", - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "outDir": "./dist" - }, - "include": ["**/*.ts"], - "exclude": ["node_modules", "dist"] + "compilerOptions": { + "target": "ES2020", + "module": "Node16", + "moduleResolution": "Node16", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "outDir": "./dist" + }, + "include": ["**/*.ts"], + "exclude": ["node_modules", "dist"] } diff --git a/toolkits/payments-and-wallets/unwrap-to-spl.ts b/toolkits/payments-and-wallets/unwrap-to-spl.ts deleted file mode 100644 index 9fb1f40..0000000 --- a/toolkits/payments-and-wallets/unwrap-to-spl.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { Keypair } from "@solana/web3.js"; -import { createRpc, bn } from "@lightprotocol/stateless.js"; -import { createMint, mintTo } from "@lightprotocol/compressed-token"; -import { - getOrCreateAtaInterface, - unwrap, -} from "@lightprotocol/compressed-token/unified"; -import { - createAssociatedTokenAccount, - getAccount, -} from "@solana/spl-token"; - -async function main() { - const rpc = createRpc(); - - // Setup - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); - - // Create test mint - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair - ); - console.log("Mint:", mint.toBase58()); - - // Mint and load to c-token ATA - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); - const ctokenAccount = await getOrCreateAtaInterface(rpc, payer, mint, owner); - console.log("C-token ATA:", ctokenAccount.parsed.address.toBase58()); - console.log("C-token balance:", ctokenAccount.parsed.amount.toString()); - - // Create destination SPL ATA (must exist before unwrap) - const splAta = await createAssociatedTokenAccount( - rpc, - payer, - mint, - owner.publicKey - ); - console.log("\nSPL ATA:", splAta.toBase58()); - - // === UNWRAP: c-token → SPL === - // Off-ramp for CEX withdrawal - const signature = await unwrap( - rpc, - payer, - splAta, - owner, - mint, - bn(500) - ); - - console.log("\n=== Unwrapped 500 tokens ==="); - console.log("Transaction:", signature); - - // Check SPL balance - const splBalance = await getAccount(rpc, splAta); - console.log("\nSPL balance (ready for CEX):", splBalance.amount.toString()); -} - -main().catch(console.error); diff --git a/toolkits/payments-and-wallets/unwrap.ts b/toolkits/payments-and-wallets/unwrap.ts new file mode 100644 index 0000000..e1026a0 --- /dev/null +++ b/toolkits/payments-and-wallets/unwrap.ts @@ -0,0 +1,67 @@ +import "dotenv/config"; +import { Keypair } from "@solana/web3.js"; +import { createRpc, bn } from "@lightprotocol/stateless.js"; +import { createMint, mintTo } from "@lightprotocol/compressed-token"; +import { + getOrCreateAtaInterface, + unwrap, +} from "@lightprotocol/compressed-token/unified"; +import { createAssociatedTokenAccount, getAccount } from "@solana/spl-token"; + +async function main() { + const rpc = createRpc(); + + // Setup + const payer = Keypair.generate(); + const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); + await rpc.confirmTransaction(airdropSig, "confirmed"); + + const owner = Keypair.generate(); + const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); + await rpc.confirmTransaction(airdropSig2, "confirmed"); + + // Create test mint + const mintAuthority = Keypair.generate(); + const mintKeypair = Keypair.generate(); + const { mint } = await createMint( + rpc, + payer, + mintAuthority.publicKey, + 9, + mintKeypair, + ); + console.log("Mint:", mint.toBase58()); + + // Mint and load to c-token ATA + await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); + const ctokenAccount = await getOrCreateAtaInterface( + rpc, + payer, + mint, + owner, + ); + console.log("C-token ATA:", ctokenAccount.parsed.address.toBase58()); + console.log("C-token balance:", ctokenAccount.parsed.amount.toString()); + + // Create destination SPL ATA (must exist before unwrap) + const splAta = await createAssociatedTokenAccount( + rpc, + payer, + mint, + owner.publicKey, + ); + console.log("\nSPL ATA:", splAta.toBase58()); + + // === UNWRAP: c-token → SPL === + // Off-ramp for CEX withdrawal + const signature = await unwrap(rpc, payer, splAta, owner, mint, bn(500)); + + console.log("\n=== Unwrapped 500 tokens ==="); + console.log("Transaction:", signature); + + // Check SPL balance + const splBalance = await getAccount(rpc, splAta); + console.log("\nSPL balance (ready for CEX):", splBalance.amount.toString()); +} + +main().catch(console.error); diff --git a/toolkits/payments-and-wallets/wrap-from-spl.ts b/toolkits/payments-and-wallets/wrap-from-spl.ts deleted file mode 100644 index 6830ecc..0000000 --- a/toolkits/payments-and-wallets/wrap-from-spl.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { Keypair } from "@solana/web3.js"; -import { createRpc, bn } from "@lightprotocol/stateless.js"; -import { - createMint, - mintTo, - decompress, - wrap, - getAssociatedTokenAddressInterface, - createAtaInterfaceIdempotent, -} from "@lightprotocol/compressed-token"; -import { createAssociatedTokenAccount, getAccount } from "@solana/spl-token"; - -async function main() { - const rpc = createRpc(); - - // Setup - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); - - // Create test mint - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair - ); - console.log("Mint:", mint.toBase58()); - - // Create SPL ATA and fund it - // (Simulates receiving tokens from CEX) - const splAta = await createAssociatedTokenAccount( - rpc, - payer, - mint, - owner.publicKey - ); - console.log("SPL ATA:", splAta.toBase58()); - - // Mint compressed, then decompress to SPL (simulates CEX deposit) - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); - await decompress(rpc, payer, mint, bn(1000), owner, splAta); - - const splBalanceBefore = await getAccount(rpc, splAta); - console.log("SPL balance before wrap:", splBalanceBefore.amount.toString()); - - // Create c-token ATA (destination) - const ctokenAta = getAssociatedTokenAddressInterface(mint, owner.publicKey); - await createAtaInterfaceIdempotent(rpc, payer, mint, owner.publicKey); - console.log("C-token ATA:", ctokenAta.toBase58()); - - // === WRAP: SPL → c-token === - // On-ramp from CEX - const signature = await wrap( - rpc, - payer, - splAta, - ctokenAta, - owner, - mint, - bn(500) - ); - - console.log("\n=== Wrapped 500 tokens ==="); - console.log("Transaction:", signature); - - // Check balances after - const splBalanceAfter = await getAccount(rpc, splAta); - console.log("\nSPL balance after:", splBalanceAfter.amount.toString()); - console.log("C-token ATA now has 500 tokens ready for payments"); -} - -main().catch(console.error); diff --git a/toolkits/payments-and-wallets/wrap.ts b/toolkits/payments-and-wallets/wrap.ts new file mode 100644 index 0000000..fd9f090 --- /dev/null +++ b/toolkits/payments-and-wallets/wrap.ts @@ -0,0 +1,81 @@ +import "dotenv/config"; +import { Keypair } from "@solana/web3.js"; +import { createRpc, bn } from "@lightprotocol/stateless.js"; +import { + createMint, + mintTo, + decompress, + wrap, + getAssociatedTokenAddressInterface, + createAtaInterfaceIdempotent, +} from "@lightprotocol/compressed-token"; +import { createAssociatedTokenAccount, getAccount } from "@solana/spl-token"; + +async function main() { + const rpc = createRpc(); + + // Setup + const payer = Keypair.generate(); + const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); + await rpc.confirmTransaction(airdropSig, "confirmed"); + + const owner = Keypair.generate(); + const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); + await rpc.confirmTransaction(airdropSig2, "confirmed"); + + // Create test mint + const mintAuthority = Keypair.generate(); + const mintKeypair = Keypair.generate(); + const { mint } = await createMint( + rpc, + payer, + mintAuthority.publicKey, + 9, + mintKeypair, + ); + console.log("Mint:", mint.toBase58()); + + // Create SPL ATA and fund it + // (Simulates receiving tokens from CEX) + const splAta = await createAssociatedTokenAccount( + rpc, + payer, + mint, + owner.publicKey, + ); + console.log("SPL ATA:", splAta.toBase58()); + + // Mint compressed, then decompress to SPL (simulates CEX deposit) + await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); + await decompress(rpc, payer, mint, bn(1000), owner, splAta); + + const splBalanceBefore = await getAccount(rpc, splAta); + console.log("SPL balance before wrap:", splBalanceBefore.amount.toString()); + + // Create c-token ATA (destination) + const ctokenAta = getAssociatedTokenAddressInterface(mint, owner.publicKey); + await createAtaInterfaceIdempotent(rpc, payer, mint, owner.publicKey); + console.log("C-token ATA:", ctokenAta.toBase58()); + + // === WRAP: SPL → c-token === + // On-ramp from CEX + const signature = await wrap( + rpc, + payer, + splAta, + ctokenAta, + owner, + mint, + bn(500), + ); + + console.log("\n=== Wrapped 500 tokens ==="); + console.log("Transaction:", signature); + + // Check balances after + const splBalanceAfter = await getAccount(rpc, splAta); + console.log("\nSPL balance after:", splBalanceAfter.amount.toString()); + console.log("C-token ATA now has 500 tokens ready for payments"); +} + +main().catch(console.error); diff --git a/toolkits/streaming-tokens/README.mdx b/toolkits/streaming-tokens/README.mdx index 7166adc..5d2bbdc 100644 --- a/toolkits/streaming-tokens/README.mdx +++ b/toolkits/streaming-tokens/README.mdx @@ -18,7 +18,7 @@ const LIGHT_SYSTEM_PROGRAM: &str = "SySTEM1eSU2p4BGQfQpimFEWWSC1XDFeun3Nqzz3rT7" #[tokio::main] async fn main() -> anyhow::Result<()> { let config = LaserstreamConfig { - api_key: std::env::var("HELIUS_API_KEY")?, + api_key: std::env::var("API_KEY")?, endpoint: "https://laserstream-mainnet-ewr.helius-rpc.com".to_string(), }; diff --git a/toolkits/streaming-tokens/src/main.rs b/toolkits/streaming-tokens/src/main.rs index 346df8c..c696f84 100644 --- a/toolkits/streaming-tokens/src/main.rs +++ b/toolkits/streaming-tokens/src/main.rs @@ -7,7 +7,7 @@ const CTOKEN_PROGRAM_ID: &str = "cTokenmWW8bLPjZEBAUgYy3zKxQZW6VKi7bqNFEVv3m"; async fn main() -> anyhow::Result<()> { dotenvy::dotenv().ok(); - let api_key = std::env::var("HELIUS_API_KEY")?; + let api_key = std::env::var("API_KEY")?; let endpoint = "https://laserstream-devnet-ewr.helius-rpc.com".to_string(); let config = LaserstreamConfig::new(endpoint, api_key); From fc82f8306dd89dd4166c47c7c3723d5c807ce059 Mon Sep 17 00:00:00 2001 From: Swenschaeferjohann Date: Mon, 22 Dec 2025 13:41:36 +0100 Subject: [PATCH 2/9] quickstart works on local --- .gitignore | 1 + devnet-quickstart/index.ts | 51 ++++++++++++++++---------------------- 2 files changed, 22 insertions(+), 30 deletions(-) diff --git a/.gitignore b/.gitignore index d78cbc9..d57540e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ **/pnpm-lock.yaml **/package-lock.json **/*.json.bak +**/test-ledger \ No newline at end of file diff --git a/devnet-quickstart/index.ts b/devnet-quickstart/index.ts index f2ce095..eb34b65 100644 --- a/devnet-quickstart/index.ts +++ b/devnet-quickstart/index.ts @@ -1,11 +1,10 @@ import dotenv from "dotenv"; import { Keypair } from "@solana/web3.js"; +import { createRpc } from "@lightprotocol/stateless.js"; import { - bn, - createRpc, - selectStateTreeInfo, -} from "@lightprotocol/stateless.js"; -import { createMint, mintTo } from "@lightprotocol/compressed-token"; + mintToInterface, + createMintInterface, +} from "@lightprotocol/compressed-token"; import { getOrCreateAtaInterface } from "@lightprotocol/compressed-token/unified"; import { homedir } from "os"; import { readFileSync } from "fs"; @@ -21,41 +20,33 @@ dotenv.config(); const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; async function main() { - const rpc = createRpc(RPC_URL); - const infos = await rpc.getStateTreeInfos(); - const treeInfo = selectStateTreeInfo(infos); - console.log(treeInfo); + const rpc = createRpc(); - // Create an SPL mint + enable compression. - const mintAuthority = Keypair.generate(); - const mintSigner = Keypair.generate(); - const { mint, transactionSignature: createMintSig } = await createMint( + const mintAuthority = payer; + const { mint, transactionSignature } = await createMintInterface( rpc, payer, - mintAuthority.publicKey, - 9, - mintSigner + mintAuthority, + null, + 9 ); - // Mint compressed tokens to a recipient (owner pubkey). + // Mint compressed tokens to a recipient token account. const recipient = Keypair.generate(); - const amount = bn(1_000_000_000); - const mintToSig = await mintTo( + const recipientAta = await getOrCreateAtaInterface( rpc, payer, mint, - recipient.publicKey, - mintAuthority, - amount, - treeInfo + recipient ); - // Create/load the recipient's c-token ATA interface (loads cold balance to hot). - const recipientAccount = await getOrCreateAtaInterface( + const txId = await mintToInterface( rpc, payer, mint, - recipient + recipientAta.parsed.address, + payer, + 1e9 ); console.log( @@ -64,10 +55,10 @@ async function main() { payer: payer.publicKey.toBase58(), mint: mint.toBase58(), recipient: recipient.publicKey.toBase58(), - recipientAta: recipientAccount.parsed.address.toBase58(), - recipientBalance: recipientAccount.parsed.amount.toString(), - createMintTx: createMintSig, - mintTx: mintToSig, + recipientAta: recipientAta.parsed.address.toBase58(), + recipientBalance: recipientAta.parsed.amount.toString(), + createMintTx: transactionSignature, + mintTx: txId, }, null, 2 From 6e83b95ecdf29aac85d104587d21391096db9a06 Mon Sep 17 00:00:00 2001 From: Swenschaeferjohann Date: Mon, 22 Dec 2025 13:48:22 +0100 Subject: [PATCH 3/9] quickstart --- devnet-quickstart/index.ts | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/devnet-quickstart/index.ts b/devnet-quickstart/index.ts index eb34b65..2da5e2b 100644 --- a/devnet-quickstart/index.ts +++ b/devnet-quickstart/index.ts @@ -10,18 +10,21 @@ import { homedir } from "os"; import { readFileSync } from "fs"; // Load wallet -const keypairPath = `${homedir()}/.config/solana/id.json`; const payer = Keypair.fromSecretKey( - new Uint8Array(JSON.parse(readFileSync(keypairPath, "utf8"))) + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) ); -// You can use any compatible RPC endpoint -dotenv.config(); -const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +// Use a compatible RPC provider, such as Helius and Triton. +// Enable to use Devnet: +// dotenv.config(); +// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -async function main() { +(async function () { const rpc = createRpc(); + // 1. create mint const mintAuthority = payer; const { mint, transactionSignature } = await createMintInterface( rpc, @@ -31,7 +34,7 @@ async function main() { 9 ); - // Mint compressed tokens to a recipient token account. + // 2. get recipient const recipient = Keypair.generate(); const recipientAta = await getOrCreateAtaInterface( rpc, @@ -40,6 +43,7 @@ async function main() { recipient ); + // 3. mint to recipient const txId = await mintToInterface( rpc, payer, @@ -64,9 +68,4 @@ async function main() { 2 ) ); -} - -main().catch((err) => { - console.error(err); - process.exit(1); -}); +})(); From 948fb2bbea4aa82dab83f57fdb998116b9727abb Mon Sep 17 00:00:00 2001 From: Swenschaeferjohann Date: Mon, 22 Dec 2025 17:49:38 +0100 Subject: [PATCH 4/9] fix for devnet --- package.json | 4 ++-- {devnet-quickstart => quickstart}/index.ts | 8 ++++---- {devnet-quickstart => quickstart}/package.json | 8 ++++---- {devnet-quickstart => quickstart}/tsconfig.json | 0 4 files changed, 10 insertions(+), 10 deletions(-) rename {devnet-quickstart => quickstart}/index.ts (91%) rename {devnet-quickstart => quickstart}/package.json (55%) rename {devnet-quickstart => quickstart}/tsconfig.json (100%) diff --git a/package.json b/package.json index 8d3195f..da09447 100644 --- a/package.json +++ b/package.json @@ -2,12 +2,12 @@ "name": "examples-light-token", "private": true, "workspaces": [ - "devnet-quickstart", + "quickstart", "cookbook", "toolkits/payments-and-wallets" ], "scripts": { - "quickstart": "npm run -w devnet-quickstart start", + "quickstart": "npm run -w quickstart start", "cookbook": "npm run -w cookbook", "toolkit:payments": "npm run -w toolkits/payments-and-wallets" } diff --git a/devnet-quickstart/index.ts b/quickstart/index.ts similarity index 91% rename from devnet-quickstart/index.ts rename to quickstart/index.ts index 2da5e2b..cb4c76a 100644 --- a/devnet-quickstart/index.ts +++ b/quickstart/index.ts @@ -18,11 +18,11 @@ const payer = Keypair.fromSecretKey( // Use a compatible RPC provider, such as Helius and Triton. // Enable to use Devnet: -// dotenv.config(); -// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; - +dotenv.config(); +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +console.log("RPC_URL: ", RPC_URL); (async function () { - const rpc = createRpc(); + const rpc = createRpc(RPC_URL); // 1. create mint const mintAuthority = payer; diff --git a/devnet-quickstart/package.json b/quickstart/package.json similarity index 55% rename from devnet-quickstart/package.json rename to quickstart/package.json index f3f69de..1f1137e 100644 --- a/devnet-quickstart/package.json +++ b/quickstart/package.json @@ -1,12 +1,12 @@ { - "name": "devnet-quickstart", + "name": "quickstart", "type": "module", "scripts": { - "start": "cd .. && ts-node-esm devnet-quickstart/index.ts" + "start": "cd .. && ts-node-esm quickstart/index.ts" }, "dependencies": { - "@lightprotocol/compressed-token": "^0.22.1-alpha", - "@lightprotocol/stateless.js": "^0.22.1-alpha", + "@lightprotocol/compressed-token": "^0.22.1-alpha.6", + "@lightprotocol/stateless.js": "^0.22.1-alpha.5", "@solana/web3.js": "1.98.4", "dotenv": "^16.5.0" }, diff --git a/devnet-quickstart/tsconfig.json b/quickstart/tsconfig.json similarity index 100% rename from devnet-quickstart/tsconfig.json rename to quickstart/tsconfig.json From 2771869ee289266747101cdf81baada1313e2cf1 Mon Sep 17 00:00:00 2001 From: Swenschaeferjohann Date: Tue, 23 Dec 2025 12:21:51 +0100 Subject: [PATCH 5/9] quickstart works for devnet and localnet --- quickstart/index.ts | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/quickstart/index.ts b/quickstart/index.ts index cb4c76a..43ac7e4 100644 --- a/quickstart/index.ts +++ b/quickstart/index.ts @@ -4,8 +4,10 @@ import { createRpc } from "@lightprotocol/stateless.js"; import { mintToInterface, createMintInterface, + getOrCreateAtaInterface, + getAccountInterface, + getAtaInterface, } from "@lightprotocol/compressed-token"; -import { getOrCreateAtaInterface } from "@lightprotocol/compressed-token/unified"; import { homedir } from "os"; import { readFileSync } from "fs"; @@ -20,11 +22,11 @@ const payer = Keypair.fromSecretKey( // Enable to use Devnet: dotenv.config(); const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -console.log("RPC_URL: ", RPC_URL); + (async function () { const rpc = createRpc(RPC_URL); - // 1. create mint + // 1. create test mint const mintAuthority = payer; const { mint, transactionSignature } = await createMintInterface( rpc, @@ -34,9 +36,9 @@ console.log("RPC_URL: ", RPC_URL); 9 ); - // 2. get recipient + // 2. get recipient's associated token account const recipient = Keypair.generate(); - const recipientAta = await getOrCreateAtaInterface( + let recipientAta = await getOrCreateAtaInterface( rpc, payer, mint, @@ -53,6 +55,14 @@ console.log("RPC_URL: ", RPC_URL); 1e9 ); + // 4. fetch state + recipientAta = await getAtaInterface( + rpc, + recipientAta.parsed.address, + recipient.publicKey, + mint + ); + console.log( JSON.stringify( { From 44ec10a41e761180161cb8f8da34693c232f7e9e Mon Sep 17 00:00:00 2001 From: Swenschaeferjohann Date: Tue, 23 Dec 2025 20:06:17 +0100 Subject: [PATCH 6/9] wip --- cookbook/actions/compress-batch.ts | 60 +++++-------- cookbook/actions/compress.ts | 63 +++++-------- cookbook/actions/create-ata.ts | 51 +++-------- cookbook/actions/create-mint.ts | 50 ++++------- .../actions/decompress-with-interface-pda.ts | 60 +++++++++++++ .../actions/decompress-with-token-pool.ts | 79 ----------------- cookbook/actions/decompress.ts | 54 ++++-------- cookbook/actions/delegate-approve.ts | 69 +++++---------- cookbook/actions/delegate-revoke.ts | 77 +++++----------- cookbook/actions/load-ata.ts | 57 ++++-------- cookbook/actions/merge-token-accounts.ts | 88 ++++--------------- cookbook/actions/mint-to.ts | 54 +++++------- cookbook/actions/transfer-interface.ts | 50 ++++------- cookbook/actions/unwrap.ts | 64 ++++---------- cookbook/actions/wrap.ts | 74 +++++----------- cookbook/instructions/create-ata.ts | 61 +++++-------- cookbook/instructions/create-mint.ts | 65 +++++--------- cookbook/instructions/load-ata.ts | 62 ++++--------- cookbook/instructions/mint-to.ts | 56 ++++-------- cookbook/instructions/transfer-interface.ts | 63 ++++--------- cookbook/instructions/unwrap.ts | 83 ++++++----------- cookbook/instructions/wrap.ts | 85 ++++++------------ cookbook/package.json | 2 +- quickstart/index.ts | 1 - 24 files changed, 457 insertions(+), 971 deletions(-) create mode 100644 cookbook/actions/decompress-with-interface-pda.ts delete mode 100644 cookbook/actions/decompress-with-token-pool.ts diff --git a/cookbook/actions/compress-batch.ts b/cookbook/actions/compress-batch.ts index 219b2bc..e0ab6f0 100644 --- a/cookbook/actions/compress-batch.ts +++ b/cookbook/actions/compress-batch.ts @@ -8,48 +8,37 @@ import { compress, } from "@lightprotocol/compressed-token"; import { createAssociatedTokenAccount } from "@solana/spl-token"; +import { homedir } from "os"; +import { readFileSync } from "fs"; -async function main() { - // 1. Setup RPC and fund accounts - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); +async function main() { + const rpc = createRpc(RPC_URL); - // 2. Create SPL mint with token pool - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair, - ); + const { mint } = await createMint(rpc, payer, payer.publicKey, 9); console.log("Mint:", mint.toBase58()); - // 3. Create SPL ATA and fund it const splAta = await createAssociatedTokenAccount( rpc, payer, mint, - owner.publicKey, + payer.publicKey ); - console.log("SPL ATA:", splAta.toBase58()); - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(10000)); - await decompress(rpc, payer, mint, bn(10000), owner, splAta); - console.log("Funded SPL ATA with 10000 tokens"); + // Fund SPL ATA: mint compressed, then decompress + await mintTo(rpc, payer, mint, payer.publicKey, payer, bn(10000)); + await decompress(rpc, payer, mint, bn(10000), payer, splAta); - // 4. Batch compress to multiple recipients (max 10 for V2 trees) + // Batch compress to multiple recipients const recipients = Array.from( { length: 5 }, - () => Keypair.generate().publicKey, + () => Keypair.generate().publicKey ); const amounts = [bn(100), bn(200), bn(300), bn(400), bn(500)]; @@ -57,19 +46,14 @@ async function main() { rpc, payer, mint, - amounts, // array of amounts - owner, + amounts, + payer, splAta, - recipients, // array of recipients (same length as amounts) + recipients ); console.log("Batch compressed to 5 recipients"); - console.log("Amounts:", amounts.map((a) => a.toString()).join(", ")); - console.log("Transaction:", signature); + console.log("Tx:", signature); } -main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); -}); +main().catch(console.error); diff --git a/cookbook/actions/compress.ts b/cookbook/actions/compress.ts index f511689..9791a1a 100644 --- a/cookbook/actions/compress.ts +++ b/cookbook/actions/compress.ts @@ -8,65 +8,46 @@ import { compress, } from "@lightprotocol/compressed-token"; import { createAssociatedTokenAccount } from "@solana/spl-token"; +import { homedir } from "os"; +import { readFileSync } from "fs"; -async function main() { - // 1. Setup RPC and fund accounts - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); +async function main() { + const rpc = createRpc(RPC_URL); - // 2. Create SPL mint with token pool - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair, - ); + const { mint } = await createMint(rpc, payer, payer.publicKey, 9); console.log("Mint:", mint.toBase58()); - // 3. Create SPL ATA and fund it with SPL tokens const splAta = await createAssociatedTokenAccount( rpc, payer, mint, - owner.publicKey, + payer.publicKey ); - console.log("SPL ATA:", splAta.toBase58()); - // Mint compressed then decompress to get SPL tokens - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); - await decompress(rpc, payer, mint, bn(1000), owner, splAta); - console.log("Funded SPL ATA with 1000 tokens"); + // Fund SPL ATA: mint compressed, then decompress + await mintTo(rpc, payer, mint, payer.publicKey, payer, bn(1000)); + await decompress(rpc, payer, mint, bn(1000), payer, splAta); - // 4. Compress SPL tokens to cold storage const recipient = Keypair.generate(); - const signature = await compress( rpc, payer, mint, - bn(500), // amount to compress - owner, // owner of SPL account (signer) - splAta, // source SPL token account - recipient.publicKey, // recipient of compressed tokens + bn(500), + payer, + splAta, + recipient.publicKey ); - console.log("Compressed 500 tokens to cold storage"); - console.log("Recipient:", recipient.publicKey.toBase58()); - console.log("Transaction:", signature); + console.log("Compressed 500 tokens to:", recipient.publicKey.toBase58()); + console.log("Tx:", signature); } -main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); -}); +main().catch(console.error); diff --git a/cookbook/actions/create-ata.ts b/cookbook/actions/create-ata.ts index 9e0f52d..95a347f 100644 --- a/cookbook/actions/create-ata.ts +++ b/cookbook/actions/create-ata.ts @@ -1,52 +1,29 @@ import "dotenv/config"; import { Keypair } from "@solana/web3.js"; -import { createRpc, featureFlags, VERSION } from "@lightprotocol/stateless.js"; +import { createRpc } from "@lightprotocol/stateless.js"; import { createMintInterface, createAtaInterface, - getAssociatedTokenAddressInterface, } from "@lightprotocol/compressed-token"; +import { homedir } from "os"; +import { readFileSync } from "fs"; -featureFlags.version = VERSION.V2; +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); async function main() { - // 1. Setup RPC and fund payer - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); + const rpc = createRpc(RPC_URL); - // 2. Create a light-mint - const mintSigner = Keypair.generate(); - const { mint } = await createMintInterface( - rpc, - payer, - payer, // mintAuthority - null, // freezeAuthority - 9, // decimals - mintSigner, - ); + const { mint } = await createMintInterface(rpc, payer, payer, null, 9); console.log("Mint:", mint.toBase58()); - // 3. Create associated token account for owner const owner = Keypair.generate(); - const txSignature = await createAtaInterface( - rpc, - payer, - mint, - owner.publicKey, - ); - console.log("ATA created for:", owner.publicKey.toBase58()); - console.log("Transaction:", txSignature); - - // 4. Derive the ATA address - const ata = getAssociatedTokenAddressInterface(mint, owner.publicKey); - console.log("ATA address:", ata.toBase58()); + const ata = await createAtaInterface(rpc, payer, mint, owner.publicKey); + console.log("ATA:", ata.toBase58()); } -main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); -}); +main().catch(console.error); diff --git a/cookbook/actions/create-mint.ts b/cookbook/actions/create-mint.ts index ab2a77b..3faf198 100644 --- a/cookbook/actions/create-mint.ts +++ b/cookbook/actions/create-mint.ts @@ -1,53 +1,41 @@ import "dotenv/config"; import { Keypair } from "@solana/web3.js"; -import { createRpc, featureFlags, VERSION } from "@lightprotocol/stateless.js"; +import { createRpc } from "@lightprotocol/stateless.js"; import { createMintInterface, createTokenMetadata, } from "@lightprotocol/compressed-token"; +import { homedir } from "os"; +import { readFileSync } from "fs"; -featureFlags.version = VERSION.V2; +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); async function main() { - // 1. Connect to local test-validator (default: localhost:8899) - // Start with: light test-validator - const rpc = createRpc(); + const rpc = createRpc(RPC_URL); - // 2. Load payer keypair from local Solana config - // For localnet, use the test keypair or airdrop SOL - const payer = Keypair.generate(); - - // Airdrop SOL to payer for localnet - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); - - // 3. Generate a new mint signer keypair - const mintSigner = Keypair.generate(); - - // 4. Generate mint authority keypair - const mintAuthority = Keypair.generate(); - - // 5. Create compressed mint with token metadata - // The SDK auto-fetches V2 tree info from local validator const { mint, transactionSignature } = await createMintInterface( rpc, payer, - mintAuthority, // mintAuthority (must be Signer for compressed mints) + payer, // mintAuthority null, // freezeAuthority - 9, // decimals - mintSigner, - { skipPreflight: true }, // confirmOptions - undefined, // programId (defaults to CTOKEN_PROGRAM_ID) + 9, + undefined, // mintSigner + undefined, // confirmOptions + undefined, // programId createTokenMetadata( "Example Token", "EXT", - "https://example.com/metadata.json", - ), + "https://example.com/metadata.json" + ) ); - console.log("Mint created:", mint.toBase58()); - console.log(`Transaction: ${transactionSignature}`); + console.log("Mint:", mint.toBase58()); + console.log("Tx:", transactionSignature); } main().catch(console.error); diff --git a/cookbook/actions/decompress-with-interface-pda.ts b/cookbook/actions/decompress-with-interface-pda.ts new file mode 100644 index 0000000..e48024a --- /dev/null +++ b/cookbook/actions/decompress-with-interface-pda.ts @@ -0,0 +1,60 @@ +import "dotenv/config"; +import { Keypair } from "@solana/web3.js"; +import { createRpc, bn } from "@lightprotocol/stateless.js"; +import { + createMint, + mintTo, + decompress, + getTokenPoolInfos, + selectTokenPoolInfosForDecompression, + selectSplInterfaceInfosForDecompression, + getSplInterfaceInfos, +} from "@lightprotocol/compressed-token"; +import { createAssociatedTokenAccount } from "@solana/spl-token"; +import { homedir } from "os"; +import { readFileSync } from "fs"; + +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); + +async function main() { + const rpc = createRpc(RPC_URL); + + const { mint } = await createMint(rpc, payer, payer.publicKey, 9); + + await mintTo(rpc, payer, mint, payer.publicKey, payer, bn(1000)); + + const splAta = await createAssociatedTokenAccount( + rpc, + payer, + mint, + payer.publicKey + ); + + // Get and select Interface Info for decompression + const amount = bn(500); + const splInterfaceInfos = await getSplInterfaceInfos(rpc, mint); + const splInterfaceInfo = selectSplInterfaceInfosForDecompression( + splInterfaceInfos, + amount + ); + + const signature = await decompress( + rpc, + payer, + mint, + amount, + payer, + splAta, + splInterfaceInfo + ); + + console.log(`Decompressed ${amount.toString()} tokens`); + console.log("Tx:", signature); +} + +main().catch(console.error); diff --git a/cookbook/actions/decompress-with-token-pool.ts b/cookbook/actions/decompress-with-token-pool.ts deleted file mode 100644 index 22df6d7..0000000 --- a/cookbook/actions/decompress-with-token-pool.ts +++ /dev/null @@ -1,79 +0,0 @@ -import "dotenv/config"; -import { Keypair } from "@solana/web3.js"; -import { createRpc, bn } from "@lightprotocol/stateless.js"; -import { - createMint, - mintTo, - decompress, - getTokenPoolInfos, - selectTokenPoolInfosForDecompression, -} from "@lightprotocol/compressed-token"; -import { createAssociatedTokenAccount } from "@solana/spl-token"; - -async function main() { - // 1. Setup RPC and fund accounts - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); - - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); - - // 2. Create SPL mint with token pool - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair, - ); - console.log("Mint:", mint.toBase58()); - - // 3. Mint compressed tokens (cold storage) - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); - console.log("Minted 1000 compressed tokens"); - - // 4. Create destination SPL ATA - const splAta = await createAssociatedTokenAccount( - rpc, - payer, - mint, - owner.publicKey, - ); - console.log("SPL ATA:", splAta.toBase58()); - - // 5. Get token pool infos and select for decompression - const tokenPoolInfos = await getTokenPoolInfos(rpc, mint); - console.log("Token pools found:", tokenPoolInfos.length); - - const selectedPools = selectTokenPoolInfosForDecompression( - tokenPoolInfos, - bn(500), // amount to decompress - ); - console.log("Selected pools:", selectedPools.length); - - // 6. Decompress with explicit token pool selection - const signature = await decompress( - rpc, - payer, - mint, - bn(500), - owner, - splAta, - selectedPools, // optional: explicitly pass token pools - ); - - console.log("Decompressed 500 tokens to SPL ATA"); - console.log("Transaction:", signature); -} - -main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); -}); diff --git a/cookbook/actions/decompress.ts b/cookbook/actions/decompress.ts index 97c9b40..3b619ec 100644 --- a/cookbook/actions/decompress.ts +++ b/cookbook/actions/decompress.ts @@ -7,60 +7,42 @@ import { decompress, } from "@lightprotocol/compressed-token"; import { createAssociatedTokenAccount } from "@solana/spl-token"; +import { homedir } from "os"; +import { readFileSync } from "fs"; -async function main() { - // 1. Setup RPC and fund accounts - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); +async function main() { + const rpc = createRpc(RPC_URL); - // 2. Create SPL mint with token pool - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair, - ); + const { mint } = await createMint(rpc, payer, payer.publicKey, 9); console.log("Mint:", mint.toBase58()); - // 3. Mint compressed tokens (cold storage) - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); - console.log("Minted 1000 compressed tokens"); + await mintTo(rpc, payer, mint, payer.publicKey, payer, bn(1000)); - // 4. Create destination SPL ATA (must exist before decompressing) const splAta = await createAssociatedTokenAccount( rpc, payer, mint, - owner.publicKey, + payer.publicKey ); - console.log("SPL ATA:", splAta.toBase58()); - // 5. Decompress to SPL ATA const signature = await decompress( rpc, payer, mint, - bn(500), // amount to decompress - owner, // owner of compressed tokens (signer) - splAta, // destination SPL token account + bn(500), + payer, + splAta ); console.log("Decompressed 500 tokens to SPL ATA"); - console.log("Transaction:", signature); + console.log("Tx:", signature); } -main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); -}); +main().catch(console.error); diff --git a/cookbook/actions/delegate-approve.ts b/cookbook/actions/delegate-approve.ts index abd110c..1055c11 100644 --- a/cookbook/actions/delegate-approve.ts +++ b/cookbook/actions/delegate-approve.ts @@ -2,61 +2,32 @@ import "dotenv/config"; import { Keypair } from "@solana/web3.js"; import { createRpc, bn } from "@lightprotocol/stateless.js"; import { createMint, mintTo, approve } from "@lightprotocol/compressed-token"; +import { homedir } from "os"; +import { readFileSync } from "fs"; + +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); async function main() { - // 1. Setup RPC and fund accounts - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); - - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); - - // 2. Create mint and mint tokens to owner - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair, - ); + const rpc = createRpc(RPC_URL); + + const { mint } = await createMint(rpc, payer, payer.publicKey, 9); console.log("Mint:", mint.toBase58()); - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); - console.log("Minted 1000 compressed tokens to owner"); + await mintTo(rpc, payer, mint, payer.publicKey, payer, bn(1000)); - // 3. Create delegate const delegate = Keypair.generate(); - console.log("Delegate:", delegate.publicKey.toBase58()); - - // 4. Approve delegation - const signature = await approve( - rpc, - payer, - mint, - bn(500), // amount to delegate - owner, // owner of tokens (signer) - delegate.publicKey, // delegate address - ); - - console.log("Approved delegation of 500 tokens"); - console.log("Transaction:", signature); - - // 5. Verify delegation - const delegatedAccounts = await rpc.getCompressedTokenAccountsByDelegate( - delegate.publicKey, - { mint }, - ); + const signature = await approve(rpc, payer, mint, bn(500), payer, delegate.publicKey); + + console.log("Approved delegation of 500 tokens to:", delegate.publicKey.toBase58()); + console.log("Tx:", signature); + + const delegatedAccounts = await rpc.getCompressedTokenAccountsByDelegate(delegate.publicKey, { mint }); console.log("Delegated accounts:", delegatedAccounts.items.length); } -main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); -}); +main().catch(console.error); diff --git a/cookbook/actions/delegate-revoke.ts b/cookbook/actions/delegate-revoke.ts index f9622bd..f7e7e17 100644 --- a/cookbook/actions/delegate-revoke.ts +++ b/cookbook/actions/delegate-revoke.ts @@ -1,74 +1,39 @@ import "dotenv/config"; import { Keypair } from "@solana/web3.js"; import { createRpc, bn } from "@lightprotocol/stateless.js"; -import { - createMint, - mintTo, - approve, - revoke, -} from "@lightprotocol/compressed-token"; +import { createMint, mintTo, approve, revoke } from "@lightprotocol/compressed-token"; +import { homedir } from "os"; +import { readFileSync } from "fs"; -async function main() { - // 1. Setup RPC and fund accounts - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); +async function main() { + const rpc = createRpc(RPC_URL); - // 2. Create mint and mint tokens - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair, - ); + const { mint } = await createMint(rpc, payer, payer.publicKey, 9); console.log("Mint:", mint.toBase58()); - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); - console.log("Minted 1000 compressed tokens to owner"); + await mintTo(rpc, payer, mint, payer.publicKey, payer, bn(1000)); - // 3. Approve delegation const delegate = Keypair.generate(); - console.log("Delegate:", delegate.publicKey.toBase58()); - await approve(rpc, payer, mint, bn(500), owner, delegate.publicKey); - console.log("Approved delegation of 500 tokens"); + await approve(rpc, payer, mint, bn(500), payer, delegate.publicKey); + console.log("Approved delegation to:", delegate.publicKey.toBase58()); - // 4. Get delegated accounts - const delegatedAccounts = await rpc.getCompressedTokenAccountsByDelegate( - delegate.publicKey, - { mint }, - ); - console.log("Before revoke:", delegatedAccounts.items.length, "accounts"); + const delegatedAccounts = await rpc.getCompressedTokenAccountsByDelegate(delegate.publicKey, { mint }); + console.log("Delegated accounts:", delegatedAccounts.items.length); - // 5. Revoke delegation - const signature = await revoke( - rpc, - payer, - delegatedAccounts.items, // accounts to revoke - owner, // owner (signer) - ); + const signature = await revoke(rpc, payer, delegatedAccounts.items, payer); console.log("Revoked delegation"); - console.log("Transaction:", signature); + console.log("Tx:", signature); - // 6. Verify revocation - const afterRevoke = await rpc.getCompressedTokenAccountsByDelegate( - delegate.publicKey, - { mint }, - ); + const afterRevoke = await rpc.getCompressedTokenAccountsByDelegate(delegate.publicKey, { mint }); console.log("After revoke:", afterRevoke.items.length, "accounts"); } -main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); -}); +main().catch(console.error); diff --git a/cookbook/actions/load-ata.ts b/cookbook/actions/load-ata.ts index bed425d..6675333 100644 --- a/cookbook/actions/load-ata.ts +++ b/cookbook/actions/load-ata.ts @@ -7,58 +7,35 @@ import { loadAta, getAssociatedTokenAddressInterface, } from "@lightprotocol/compressed-token"; +import { homedir } from "os"; +import { readFileSync } from "fs"; -async function main() { - // 1. Setup RPC and fund accounts - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); +async function main() { + const rpc = createRpc(RPC_URL); - // 2. Create mint and mint compressed tokens (cold) - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair, - ); + const { mint } = await createMint(rpc, payer, payer.publicKey, 9); console.log("Mint:", mint.toBase58()); - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); - console.log("Minted 1000 compressed tokens (cold)"); + await mintTo(rpc, payer, mint, payer.publicKey, payer, bn(1000)); - // 3. Get c-token ATA address - const ctokenAta = getAssociatedTokenAddressInterface(mint, owner.publicKey); - console.log("c-token ATA:", ctokenAta.toBase58()); + const ctokenAta = getAssociatedTokenAddressInterface(mint, payer.publicKey); - // 4. Load compressed tokens to hot balance - // Creates ATA if needed, returns null if nothing to load - const signature = await loadAta( - rpc, - ctokenAta, // c-token ATA address - owner, // owner (signer) - mint, - payer, // optional: fee payer - ); + // Load compressed tokens (cold) to hot balance, creates ATA if needed + const signature = await loadAta(rpc, ctokenAta, payer, mint, payer); if (signature) { console.log("Loaded tokens to hot balance"); - console.log("Transaction:", signature); + console.log("Tx:", signature); } else { console.log("Nothing to load"); } } -main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); -}); +main().catch(console.error); diff --git a/cookbook/actions/merge-token-accounts.ts b/cookbook/actions/merge-token-accounts.ts index 44bb1d6..cc9042c 100644 --- a/cookbook/actions/merge-token-accounts.ts +++ b/cookbook/actions/merge-token-accounts.ts @@ -1,87 +1,37 @@ import "dotenv/config"; import { Keypair } from "@solana/web3.js"; import { createRpc, bn } from "@lightprotocol/stateless.js"; -import { - createMint, - mintTo, - mergeTokenAccounts, -} from "@lightprotocol/compressed-token"; +import { createMint, mintTo, mergeTokenAccounts } from "@lightprotocol/compressed-token"; +import { homedir } from "os"; +import { readFileSync } from "fs"; -async function main() { - // 1. Setup RPC and fund accounts - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); +async function main() { + const rpc = createRpc(RPC_URL); - // 2. Create mint - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair, - ); + const { mint } = await createMint(rpc, payer, payer.publicKey, 9); console.log("Mint:", mint.toBase58()); - // 3. Mint multiple times to create multiple compressed accounts - console.log("Minting 5 times to create multiple accounts..."); + // Mint multiple times to create multiple compressed accounts for (let i = 0; i < 5; i++) { - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(100)); + await mintTo(rpc, payer, mint, payer.publicKey, payer, bn(100)); } - console.log("Minted 500 total tokens across 5 accounts"); - // 4. Check accounts before merge - const accountsBefore = await rpc.getCompressedTokenAccountsByOwner( - owner.publicKey, - { mint }, - ); + const accountsBefore = await rpc.getCompressedTokenAccountsByOwner(payer.publicKey, { mint }); console.log("Accounts before merge:", accountsBefore.items.length); - // 5. Merge token accounts - const signature = await mergeTokenAccounts( - rpc, - payer, - mint, - owner, // owner (signer) - ); + const signature = await mergeTokenAccounts(rpc, payer, mint, payer); - console.log("Merged token accounts"); - console.log("Transaction:", signature); + console.log("Tx:", signature); - // 6. Check accounts after merge - const accountsAfter = await rpc.getCompressedTokenAccountsByOwner( - owner.publicKey, - { mint }, - ); + const accountsAfter = await rpc.getCompressedTokenAccountsByOwner(payer.publicKey, { mint }); console.log("Accounts after merge:", accountsAfter.items.length); - - // 7. Verify total balance unchanged - const totalBefore = accountsBefore.items.reduce( - (sum, acc) => sum.add(acc.parsed.amount), - bn(0), - ); - const totalAfter = accountsAfter.items.reduce( - (sum, acc) => sum.add(acc.parsed.amount), - bn(0), - ); - console.log("Total balance before:", totalBefore.toString()); - console.log("Total balance after:", totalAfter.toString()); - console.log( - "Balance preserved:", - totalBefore.toString() === totalAfter.toString(), - ); } -main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); -}); +main().catch(console.error); diff --git a/cookbook/actions/mint-to.ts b/cookbook/actions/mint-to.ts index 284a4e6..c8ac7da 100644 --- a/cookbook/actions/mint-to.ts +++ b/cookbook/actions/mint-to.ts @@ -1,62 +1,48 @@ import "dotenv/config"; import { Keypair } from "@solana/web3.js"; -import { createRpc, featureFlags, VERSION } from "@lightprotocol/stateless.js"; +import { createRpc } from "@lightprotocol/stateless.js"; import { createMintInterface, createAtaInterface, mintToInterface, getAssociatedTokenAddressInterface, } from "@lightprotocol/compressed-token"; +import { homedir } from "os"; +import { readFileSync } from "fs"; -featureFlags.version = VERSION.V2; +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); async function main() { - // 1. Setup RPC and fund payer - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); - - // 2. Create a light-mint (payer is mint authority) - const mintSigner = Keypair.generate(); - const { mint } = await createMintInterface( - rpc, - payer, - payer, // mintAuthority - null, // freezeAuthority - 9, // decimals - mintSigner, - ); - console.log("Mint created:", mint.toBase58()); + const rpc = createRpc(RPC_URL); + + const { mint } = await createMintInterface(rpc, payer, payer, null, 9); + console.log("Mint:", mint.toBase58()); - // 3. Create associated token account for recipient const recipient = Keypair.generate(); await createAtaInterface(rpc, payer, mint, recipient.publicKey); - console.log("Recipient ATA created for:", recipient.publicKey.toBase58()); - // 4. Mint tokens to the recipient's account const destination = getAssociatedTokenAddressInterface( mint, - recipient.publicKey, + recipient.publicKey ); - const amount = 1_000_000_000; // 1 token with 9 decimals + const amount = 1_000_000_000; const txSignature = await mintToInterface( rpc, payer, mint, destination, - payer, // mintAuthority (must be Signer) - amount, + payer, + amount ); - console.log("Minted tokens:", amount); - console.log("Transaction:", txSignature); + console.log("Minted:", amount); + console.log("Tx:", txSignature); } -main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); -}); +main().catch(console.error); diff --git a/cookbook/actions/transfer-interface.ts b/cookbook/actions/transfer-interface.ts index 6d97a08..a85d419 100644 --- a/cookbook/actions/transfer-interface.ts +++ b/cookbook/actions/transfer-interface.ts @@ -1,6 +1,6 @@ import "dotenv/config"; import { Keypair } from "@solana/web3.js"; -import { createRpc, featureFlags, VERSION } from "@lightprotocol/stateless.js"; +import { createRpc } from "@lightprotocol/stateless.js"; import { createMintInterface, createAtaInterface, @@ -8,65 +8,49 @@ import { transferInterface, getAssociatedTokenAddressInterface, } from "@lightprotocol/compressed-token"; +import { homedir } from "os"; +import { readFileSync } from "fs"; -featureFlags.version = VERSION.V2; +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); async function main() { - // 1. Setup RPC and fund payer - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); + const rpc = createRpc(RPC_URL); - // 2. Create a light-mint - const mintSigner = Keypair.generate(); - const { mint } = await createMintInterface( - rpc, - payer, - payer, - null, - 9, - mintSigner, - ); + const { mint } = await createMintInterface(rpc, payer, payer, null, 9); console.log("Mint:", mint.toBase58()); - // 3. Create sender's ATA and mint tokens const sender = Keypair.generate(); await createAtaInterface(rpc, payer, mint, sender.publicKey); const senderAta = getAssociatedTokenAddressInterface( mint, - sender.publicKey, + sender.publicKey ); await mintToInterface(rpc, payer, mint, senderAta, payer, 1_000_000_000); - console.log("Sender ATA:", senderAta.toBase58()); - // 4. Create recipient's ATA const recipient = Keypair.generate(); await createAtaInterface(rpc, payer, mint, recipient.publicKey); const recipientAta = getAssociatedTokenAddressInterface( mint, - recipient.publicKey, + recipient.publicKey ); - console.log("Recipient ATA:", recipientAta.toBase58()); - // 5. Transfer tokens const txSignature = await transferInterface( rpc, payer, senderAta, mint, recipientAta, - sender, // owner (must be Signer) - 500_000_000, // amount to transfer + sender, + 500_000_000 ); console.log("Transferred 0.5 tokens"); - console.log("Transaction:", txSignature); + console.log("Tx:", txSignature); } -main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); -}); +main().catch(console.error); diff --git a/cookbook/actions/unwrap.ts b/cookbook/actions/unwrap.ts index 4a1bb2e..09d76b0 100644 --- a/cookbook/actions/unwrap.ts +++ b/cookbook/actions/unwrap.ts @@ -4,61 +4,31 @@ import { createRpc, bn } from "@lightprotocol/stateless.js"; import { createMint, mintTo } from "@lightprotocol/compressed-token"; import { unwrap } from "@lightprotocol/compressed-token/unified"; import { createAssociatedTokenAccount } from "@solana/spl-token"; +import { homedir } from "os"; +import { readFileSync } from "fs"; -async function main() { - // 1. Setup RPC and fund accounts - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); +async function main() { + const rpc = createRpc(RPC_URL); - // 2. Create SPL mint with token pool - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair, - ); + const { mint } = await createMint(rpc, payer, payer.publicKey, 9); console.log("Mint:", mint.toBase58()); - // 3. Mint compressed tokens to owner - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); - console.log("Minted 1000 compressed tokens"); + await mintTo(rpc, payer, mint, payer.publicKey, payer, bn(1000)); - // 4. Create destination SPL ATA (must exist before unwrap) - const splAta = await createAssociatedTokenAccount( - rpc, - payer, - mint, - owner.publicKey, - ); - console.log("SPL ATA:", splAta.toBase58()); + const splAta = await createAssociatedTokenAccount(rpc, payer, mint, payer.publicKey); - // 5. Unwrap c-tokens to SPL ATA - // This auto-loads compressed tokens to hot balance first - const signature = await unwrap( - rpc, - payer, - splAta, // destination: SPL token account - owner, // owner of c-tokens (signer) - mint, - bn(500), // amount to unwrap (omit for full balance) - ); + // Unwrap auto-loads compressed tokens to hot balance first + const signature = await unwrap(rpc, payer, splAta, payer, mint, bn(500)); console.log("Unwrapped 500 tokens to SPL ATA"); - console.log("Transaction:", signature); + console.log("Tx:", signature); } -main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); -}); +main().catch(console.error); diff --git a/cookbook/actions/wrap.ts b/cookbook/actions/wrap.ts index e1a579d..de1454e 100644 --- a/cookbook/actions/wrap.ts +++ b/cookbook/actions/wrap.ts @@ -10,67 +10,35 @@ import { createAtaInterfaceIdempotent, } from "@lightprotocol/compressed-token"; import { createAssociatedTokenAccount } from "@solana/spl-token"; +import { homedir } from "os"; +import { readFileSync } from "fs"; -async function main() { - // 1. Setup RPC and fund accounts - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); +async function main() { + const rpc = createRpc(RPC_URL); - // 2. Create SPL mint with token pool - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair, - ); + const { mint } = await createMint(rpc, payer, payer.publicKey, 9); console.log("Mint:", mint.toBase58()); - // 3. Create SPL ATA and fund it - const splAta = await createAssociatedTokenAccount( - rpc, - payer, - mint, - owner.publicKey, - ); - console.log("SPL ATA:", splAta.toBase58()); + const splAta = await createAssociatedTokenAccount(rpc, payer, mint, payer.publicKey); - // Mint compressed then decompress to SPL ATA - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); - await decompress(rpc, payer, mint, bn(1000), owner, splAta); - console.log("Funded SPL ATA with 1000 tokens"); + // Fund SPL ATA: mint compressed, then decompress + await mintTo(rpc, payer, mint, payer.publicKey, payer, bn(1000)); + await decompress(rpc, payer, mint, bn(1000), payer, splAta); - // 4. Create c-token ATA (destination) - const ctokenAta = getAssociatedTokenAddressInterface(mint, owner.publicKey); - await createAtaInterfaceIdempotent(rpc, payer, mint, owner.publicKey); - console.log("c-token ATA:", ctokenAta.toBase58()); + const ctokenAta = getAssociatedTokenAddressInterface(mint, payer.publicKey); + await createAtaInterfaceIdempotent(rpc, payer, mint, payer.publicKey); - // 5. Wrap SPL tokens to c-token ATA - const signature = await wrap( - rpc, - payer, - splAta, // source: SPL token account - ctokenAta, // destination: c-token ATA - owner, // owner of source account (signer) - mint, - bn(500), // amount to wrap - ); + const signature = await wrap(rpc, payer, splAta, ctokenAta, payer, mint, bn(500)); - console.log("Wrapped 500 tokens to c-token ATA"); - console.log("Transaction:", signature); + console.log("Wrapped 500 tokens to c-token ATA:", ctokenAta.toBase58()); + console.log("Tx:", signature); } -main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); -}); +main().catch(console.error); diff --git a/cookbook/instructions/create-ata.ts b/cookbook/instructions/create-ata.ts index b4d0863..5334f83 100644 --- a/cookbook/instructions/create-ata.ts +++ b/cookbook/instructions/create-ata.ts @@ -4,8 +4,6 @@ import { createRpc, buildAndSignTx, sendAndConfirmTx, - featureFlags, - VERSION, CTOKEN_PROGRAM_ID, } from "@lightprotocol/stateless.js"; import { @@ -13,62 +11,43 @@ import { createAssociatedTokenAccountInterfaceInstruction, getAssociatedTokenAddressInterface, } from "@lightprotocol/compressed-token"; +import { homedir } from "os"; +import { readFileSync } from "fs"; -featureFlags.version = VERSION.V2; +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); async function main() { - // 1. Setup RPC and fund payer - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); + const rpc = createRpc(RPC_URL); - // 2. Create a light-mint - const mintSigner = Keypair.generate(); - const { mint } = await createMintInterface( - rpc, - payer, - payer, // mintAuthority - null, // freezeAuthority - 9, // decimals - mintSigner, - ); + const { mint } = await createMintInterface(rpc, payer, payer, null, 9); console.log("Mint:", mint.toBase58()); - // 3. Derive the ATA address const owner = Keypair.generate(); - const associatedToken = getAssociatedTokenAddressInterface( - mint, - owner.publicKey, - ); - console.log("Owner:", owner.publicKey.toBase58()); - console.log("ATA address:", associatedToken.toBase58()); + const associatedToken = getAssociatedTokenAddressInterface(mint, owner.publicKey); - // 4. Create the instruction const ix = createAssociatedTokenAccountInterfaceInstruction( - payer.publicKey, // payer - associatedToken, // associatedToken - owner.publicKey, // owner - mint, // mint - CTOKEN_PROGRAM_ID, // programId (cToken) + payer.publicKey, + associatedToken, + owner.publicKey, + mint, + CTOKEN_PROGRAM_ID ); - // 5. Build, sign, and send transaction const { blockhash } = await rpc.getLatestBlockhash(); const tx = buildAndSignTx( [ComputeBudgetProgram.setComputeUnitLimit({ units: 100_000 }), ix], payer, - blockhash, + blockhash ); const signature = await sendAndConfirmTx(rpc, tx); - console.log("ATA created"); - console.log("Transaction:", signature); + console.log("ATA:", associatedToken.toBase58()); + console.log("Tx:", signature); } -main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); -}); +main().catch(console.error); diff --git a/cookbook/instructions/create-mint.ts b/cookbook/instructions/create-mint.ts index 8322d3c..eab10be 100644 --- a/cookbook/instructions/create-mint.ts +++ b/cookbook/instructions/create-mint.ts @@ -6,92 +6,67 @@ import { sendAndConfirmTx, getBatchAddressTreeInfo, selectStateTreeInfo, - featureFlags, - VERSION, CTOKEN_PROGRAM_ID, DerivationMode, } from "@lightprotocol/stateless.js"; -import { - createMintInstruction, - createTokenMetadata, -} from "@lightprotocol/compressed-token"; - -featureFlags.version = VERSION.V2; +import { createMintInstruction, createTokenMetadata } from "@lightprotocol/compressed-token"; +import { homedir } from "os"; +import { readFileSync } from "fs"; -// Inline findMintAddress since it's not exported from the package const COMPRESSED_MINT_SEED = Buffer.from("compressed_mint"); function findMintAddress(mintSigner: PublicKey): [PublicKey, number] { return PublicKey.findProgramAddressSync( [COMPRESSED_MINT_SEED, mintSigner.toBuffer()], - CTOKEN_PROGRAM_ID, + CTOKEN_PROGRAM_ID ); } -async function main() { - // 1. Setup RPC connection to local validator - const rpc = createRpc(); +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); - // 2. Create and fund payer - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); +async function main() { + const rpc = createRpc(RPC_URL); - // 3. Prepare mint parameters const mintSigner = Keypair.generate(); - const decimals = 9; - - // 4. Get tree infos - // Address Merkle tree stores the mint address - // State Merkle tree stores the mint account data const addressTreeInfo = getBatchAddressTreeInfo(); const stateTreeInfo = selectStateTreeInfo(await rpc.getStateTreeInfos()); - // 5. Derive the mint PDA address const [mintPda] = findMintAddress(mintSigner.publicKey); - // 6. Get validity proof for address creation - // Proves the mint address does not exist yet const validityProof = await rpc.getValidityProofV2( [], [{ address: mintPda.toBytes(), treeInfo: addressTreeInfo }], - DerivationMode.compressible, + DerivationMode.compressible ); - // 7. Create instruction const ix = createMintInstruction( mintSigner.publicKey, - decimals, + 9, payer.publicKey, // mintAuthority null, // freezeAuthority - payer.publicKey, // payer + payer.publicKey, validityProof, addressTreeInfo, stateTreeInfo, - createTokenMetadata( - "Example Token", - "EXT", - "https://example.com/metadata.json", - ), + createTokenMetadata("Example Token", "EXT", "https://example.com/metadata.json") ); - // 8. Build, sign, and send transaction const { blockhash } = await rpc.getLatestBlockhash(); const tx = buildAndSignTx( [ComputeBudgetProgram.setComputeUnitLimit({ units: 500_000 }), ix], payer, blockhash, - [mintSigner], + [mintSigner] ); const signature = await sendAndConfirmTx(rpc, tx, { skipPreflight: true }); - console.log("Mint created:", mintPda.toBase58()); - console.log("Transaction:", signature); + console.log("Mint:", mintPda.toBase58()); + console.log("Tx:", signature); } -main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); -}); +main().catch(console.error); diff --git a/cookbook/instructions/load-ata.ts b/cookbook/instructions/load-ata.ts index 31100e5..28724a3 100644 --- a/cookbook/instructions/load-ata.ts +++ b/cookbook/instructions/load-ata.ts @@ -13,72 +13,46 @@ import { createLoadAtaInstructions, getAssociatedTokenAddressInterface, } from "@lightprotocol/compressed-token"; +import { homedir } from "os"; +import { readFileSync } from "fs"; -async function main() { - // 1. Setup RPC and fund accounts - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); +async function main() { + const rpc = createRpc(RPC_URL); - // 2. Create mint and mint compressed tokens - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair, - ); + const { mint } = await createMint(rpc, payer, payer.publicKey, 9); console.log("Mint:", mint.toBase58()); - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); - console.log("Minted 1000 compressed tokens (cold)"); + await mintTo(rpc, payer, mint, payer.publicKey, payer, bn(1000)); - // 3. Get c-token ATA address - const ctokenAta = getAssociatedTokenAddressInterface(mint, owner.publicKey); - console.log("c-token ATA:", ctokenAta.toBase58()); + const ctokenAta = getAssociatedTokenAddressInterface(mint, payer.publicKey); - // 4. Create load instructions - const ixs = await createLoadAtaInstructions( - rpc, - ctokenAta, - owner.publicKey, - mint, - payer.publicKey, - ); + const ixs = await createLoadAtaInstructions(rpc, ctokenAta, payer.publicKey, mint, payer.publicKey); if (ixs.length === 0) { console.log("Nothing to load"); return; } - console.log("Created", ixs.length, "load instructions"); - - // 5. Build, sign, and send transaction const { blockhash } = await rpc.getLatestBlockhash(); - const additionalSigners = dedupeSigner(payer, [owner]); + const additionalSigners = dedupeSigner(payer, [payer]); const tx = buildAndSignTx( [ComputeBudgetProgram.setComputeUnitLimit({ units: 500_000 }), ...ixs], payer, blockhash, - additionalSigners, + additionalSigners ); const signature = await sendAndConfirmTx(rpc, tx); console.log("Loaded tokens to hot balance"); - console.log("Transaction:", signature); + console.log("Tx:", signature); } -main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); -}); +main().catch(console.error); diff --git a/cookbook/instructions/mint-to.ts b/cookbook/instructions/mint-to.ts index 54035e9..7bb9884 100644 --- a/cookbook/instructions/mint-to.ts +++ b/cookbook/instructions/mint-to.ts @@ -6,8 +6,6 @@ import { sendAndConfirmTx, bn, DerivationMode, - featureFlags, - VERSION, } from "@lightprotocol/stateless.js"; import { createMintInterface, @@ -16,42 +14,28 @@ import { getMintInterface, getAssociatedTokenAddressInterface, } from "@lightprotocol/compressed-token"; +import { homedir } from "os"; +import { readFileSync } from "fs"; -featureFlags.version = VERSION.V2; +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); async function main() { - // 1. Setup RPC and fund payer - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); + const rpc = createRpc(RPC_URL); - // 2. Create a light-mint (payer is mint authority) - const mintSigner = Keypair.generate(); - const { mint } = await createMintInterface( - rpc, - payer, - payer, - null, - 9, - mintSigner, - ); - console.log("Mint created:", mint.toBase58()); + const { mint } = await createMintInterface(rpc, payer, payer, null, 9); + console.log("Mint:", mint.toBase58()); - // 3. Create associated token account for recipient const recipient = Keypair.generate(); await createAtaInterface(rpc, payer, mint, recipient.publicKey); - const destination = getAssociatedTokenAddressInterface( - mint, - recipient.publicKey, - ); - console.log("Recipient ATA created:", destination.toBase58()); + const destination = getAssociatedTokenAddressInterface(mint, recipient.publicKey); - // 4. Get mint interface (includes merkle context for c-tokens) const mintInterface = await getMintInterface(rpc, mint); - // 5. Get validity proof for the mint (required for c-token mints) let validityProof; if (mintInterface.merkleContext) { validityProof = await rpc.getValidityProofV2( @@ -64,32 +48,30 @@ async function main() { }, ], [], - DerivationMode.compressible, + DerivationMode.compressible ); } - // 6. Create instruction const amount = 1_000_000_000; const ix = createMintToInterfaceInstruction( mintInterface, destination, - payer.publicKey, // authority - payer.publicKey, // payer + payer.publicKey, + payer.publicKey, amount, - validityProof, + validityProof ); - // 7. Build, sign, and send transaction const { blockhash } = await rpc.getLatestBlockhash(); const tx = buildAndSignTx( [ComputeBudgetProgram.setComputeUnitLimit({ units: 500_000 }), ix], payer, - blockhash, + blockhash ); const signature = await sendAndConfirmTx(rpc, tx); - console.log("Minted tokens:", amount); - console.log("Transaction:", signature); + console.log("Minted:", amount); + console.log("Tx:", signature); } main().catch(console.error); diff --git a/cookbook/instructions/transfer-interface.ts b/cookbook/instructions/transfer-interface.ts index 709108a..d6d2c38 100644 --- a/cookbook/instructions/transfer-interface.ts +++ b/cookbook/instructions/transfer-interface.ts @@ -4,8 +4,6 @@ import { createRpc, buildAndSignTx, sendAndConfirmTx, - featureFlags, - VERSION, } from "@lightprotocol/stateless.js"; import { createMintInterface, @@ -14,73 +12,44 @@ import { createTransferInterfaceInstruction, getAssociatedTokenAddressInterface, } from "@lightprotocol/compressed-token"; +import { homedir } from "os"; +import { readFileSync } from "fs"; -featureFlags.version = VERSION.V2; +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); async function main() { - // 1. Setup RPC and fund payer - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); + const rpc = createRpc(RPC_URL); - // 2. Create a light-mint - const mintSigner = Keypair.generate(); - const { mint } = await createMintInterface( - rpc, - payer, - payer, - null, - 9, - mintSigner, - ); + const { mint } = await createMintInterface(rpc, payer, payer, null, 9); console.log("Mint:", mint.toBase58()); - // 3. Create sender's ATA and mint tokens const sender = Keypair.generate(); await createAtaInterface(rpc, payer, mint, sender.publicKey); - const senderAta = getAssociatedTokenAddressInterface( - mint, - sender.publicKey, - ); + const senderAta = getAssociatedTokenAddressInterface(mint, sender.publicKey); await mintToInterface(rpc, payer, mint, senderAta, payer, 1_000_000_000); - console.log("Sender ATA:", senderAta.toBase58()); - // 4. Create recipient's ATA const recipient = Keypair.generate(); await createAtaInterface(rpc, payer, mint, recipient.publicKey); - const recipientAta = getAssociatedTokenAddressInterface( - mint, - recipient.publicKey, - ); - console.log("Recipient ATA:", recipientAta.toBase58()); + const recipientAta = getAssociatedTokenAddressInterface(mint, recipient.publicKey); - // 5. Create transfer instruction - const amount = 500_000_000; - const ix = createTransferInterfaceInstruction( - senderAta, // source - recipientAta, // destination - sender.publicKey, // owner - amount, - ); + const ix = createTransferInterfaceInstruction(senderAta, recipientAta, sender.publicKey, 500_000_000); - // 6. Build, sign, and send transaction const { blockhash } = await rpc.getLatestBlockhash(); const tx = buildAndSignTx( [ComputeBudgetProgram.setComputeUnitLimit({ units: 10_000 }), ix], payer, blockhash, - [sender], + [sender] ); const signature = await sendAndConfirmTx(rpc, tx); console.log("Transferred 0.5 tokens"); - console.log("Transaction:", signature); + console.log("Tx:", signature); } -main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); -}); +main().catch(console.error); diff --git a/cookbook/instructions/unwrap.ts b/cookbook/instructions/unwrap.ts index 8ab7359..303ce9e 100644 --- a/cookbook/instructions/unwrap.ts +++ b/cookbook/instructions/unwrap.ts @@ -16,88 +16,59 @@ import { } from "@lightprotocol/compressed-token"; import { createUnwrapInstruction } from "@lightprotocol/compressed-token/unified"; import { createAssociatedTokenAccount } from "@solana/spl-token"; +import { homedir } from "os"; +import { readFileSync } from "fs"; -async function main() { - // 1. Setup RPC and fund accounts - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); +async function main() { + const rpc = createRpc(RPC_URL); - // 2. Create SPL mint with token pool - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair, - ); + const { mint } = await createMint(rpc, payer, payer.publicKey, 9); console.log("Mint:", mint.toBase58()); - // 3. Mint compressed tokens to owner - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); - console.log("Minted 1000 compressed tokens"); + await mintTo(rpc, payer, mint, payer.publicKey, payer, bn(1000)); - // 4. Load compressed tokens to c-token ATA (hot balance) - const ctokenAta = getAssociatedTokenAddressInterface(mint, owner.publicKey); - await loadAta(rpc, ctokenAta, owner, mint, payer); - console.log("Loaded compressed tokens to c-token ATA"); + const ctokenAta = getAssociatedTokenAddressInterface(mint, payer.publicKey); + await loadAta(rpc, ctokenAta, payer, mint, payer); - // 5. Create destination SPL ATA - const splAta = await createAssociatedTokenAccount( - rpc, - payer, - mint, - owner.publicKey, - ); - console.log("SPL ATA:", splAta.toBase58()); + const splAta = await createAssociatedTokenAccount(rpc, payer, mint, payer.publicKey); - // 6. Get SPL interface info for the mint const splInterfaceInfos = await getSplInterfaceInfos(rpc, mint); - const splInterfaceInfo = splInterfaceInfos.find( - (info) => info.isInitialized, - ); + const splInterfaceInfo = splInterfaceInfos.find((info) => info.isInitialized); if (!splInterfaceInfo) { throw new Error("No SPL interface found"); } - // 7. Create unwrap instruction const ix = createUnwrapInstruction( - ctokenAta, // source: c-token ATA - splAta, // destination: SPL token account - owner.publicKey, // owner of source account + ctokenAta, + splAta, + payer.publicKey, mint, - bn(500), // amount to unwrap - splInterfaceInfo, // SPL interface info - payer.publicKey, // fee payer + bn(500), + splInterfaceInfo, + payer.publicKey ); - // 8. Build, sign, and send transaction const { blockhash } = await rpc.getLatestBlockhash(); - const additionalSigners = dedupeSigner(payer, [owner]); + const additionalSigners = dedupeSigner(payer, [payer]); const tx = buildAndSignTx( [ComputeBudgetProgram.setComputeUnitLimit({ units: 200_000 }), ix], payer, blockhash, - additionalSigners, + additionalSigners ); const signature = await sendAndConfirmTx(rpc, tx); - console.log("Unwrapped 500 tokens to SPL ATA"); - console.log("Transaction:", signature); + console.log("Unwrapped 500 tokens"); + console.log("Tx:", signature); } -main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); -}); +main().catch(console.error); diff --git a/cookbook/instructions/wrap.ts b/cookbook/instructions/wrap.ts index 7b5ed7b..5df0564 100644 --- a/cookbook/instructions/wrap.ts +++ b/cookbook/instructions/wrap.ts @@ -17,88 +17,61 @@ import { getSplInterfaceInfos, } from "@lightprotocol/compressed-token"; import { createAssociatedTokenAccount } from "@solana/spl-token"; +import { homedir } from "os"; +import { readFileSync } from "fs"; -async function main() { - // 1. Setup RPC and fund accounts - const rpc = createRpc(); - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - console.log("Payer:", payer.publicKey.toBase58()); +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); +async function main() { + const rpc = createRpc(RPC_URL); - // 2. Create SPL mint with token pool - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair, - ); + const { mint } = await createMint(rpc, payer, payer.publicKey, 9); console.log("Mint:", mint.toBase58()); - // 3. Create SPL ATA and fund it - const splAta = await createAssociatedTokenAccount( - rpc, - payer, - mint, - owner.publicKey, - ); - console.log("SPL ATA:", splAta.toBase58()); + const splAta = await createAssociatedTokenAccount(rpc, payer, mint, payer.publicKey); - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); - await decompress(rpc, payer, mint, bn(1000), owner, splAta); - console.log("Funded SPL ATA with 1000 tokens"); + // Fund SPL ATA: mint compressed, then decompress + await mintTo(rpc, payer, mint, payer.publicKey, payer, bn(1000)); + await decompress(rpc, payer, mint, bn(1000), payer, splAta); - // 4. Create c-token ATA (destination) - const ctokenAta = getAssociatedTokenAddressInterface(mint, owner.publicKey); - await createAtaInterfaceIdempotent(rpc, payer, mint, owner.publicKey); - console.log("c-token ATA:", ctokenAta.toBase58()); + const ctokenAta = getAssociatedTokenAddressInterface(mint, payer.publicKey); + await createAtaInterfaceIdempotent(rpc, payer, mint, payer.publicKey); - // 5. Get SPL interface info for the mint const splInterfaceInfos = await getSplInterfaceInfos(rpc, mint); - const splInterfaceInfo = splInterfaceInfos.find( - (info) => info.isInitialized, - ); + const splInterfaceInfo = splInterfaceInfos.find((info) => info.isInitialized); if (!splInterfaceInfo) { throw new Error("No SPL interface found"); } - // 6. Create wrap instruction const ix = createWrapInstruction( - splAta, // source: SPL token account - ctokenAta, // destination: c-token ATA - owner.publicKey, // owner of source account + splAta, + ctokenAta, + payer.publicKey, mint, - bn(500), // amount to wrap - splInterfaceInfo, // SPL interface info - payer.publicKey, // fee payer + bn(500), + splInterfaceInfo, + payer.publicKey ); - // 7. Build, sign, and send transaction const { blockhash } = await rpc.getLatestBlockhash(); - const additionalSigners = dedupeSigner(payer, [owner]); + const additionalSigners = dedupeSigner(payer, [payer]); const tx = buildAndSignTx( [ComputeBudgetProgram.setComputeUnitLimit({ units: 200_000 }), ix], payer, blockhash, - additionalSigners, + additionalSigners ); const signature = await sendAndConfirmTx(rpc, tx); - console.log("Wrapped 500 tokens to c-token ATA"); - console.log("Transaction:", signature); + console.log("Wrapped 500 tokens"); + console.log("Tx:", signature); } -main().catch((err) => { - console.error("Error:", err); - if (err.logs) console.error("Logs:", err.logs); - process.exit(1); -}); +main().catch(console.error); diff --git a/cookbook/package.json b/cookbook/package.json index 7afec3d..e5dabe3 100644 --- a/cookbook/package.json +++ b/cookbook/package.json @@ -15,7 +15,7 @@ "compress:action": "ts-node-esm actions/compress.ts", "compress:batch": "ts-node-esm actions/compress-batch.ts", "decompress:action": "ts-node-esm actions/decompress.ts", - "decompress:with-token-pool": "ts-node-esm actions/decompress-with-token-pool.ts", + "decompress:with-token-pool": "ts-node-esm actions/decompress-with-interface-pda.ts", "wrap:action": "ts-node-esm actions/wrap.ts", "wrap:instruction": "ts-node-esm instructions/wrap.ts", "unwrap:action": "ts-node-esm actions/unwrap.ts", diff --git a/quickstart/index.ts b/quickstart/index.ts index 43ac7e4..97ad3dc 100644 --- a/quickstart/index.ts +++ b/quickstart/index.ts @@ -5,7 +5,6 @@ import { mintToInterface, createMintInterface, getOrCreateAtaInterface, - getAccountInterface, getAtaInterface, } from "@lightprotocol/compressed-token"; import { homedir } from "os"; From ac2cb796b8720a2de97ec94769a00c099e2fc166 Mon Sep 17 00:00:00 2001 From: Swenschaeferjohann Date: Wed, 24 Dec 2025 00:28:25 +0100 Subject: [PATCH 7/9] refactor --- cookbook/actions/compress-batch.ts | 43 ++----- cookbook/actions/compress.ts | 39 ++---- cookbook/actions/create-ata.ts | 8 +- cookbook/actions/create-mint.ts | 27 ++--- cookbook/actions/decompress.ts | 23 +--- cookbook/actions/delegate-approve.ts | 27 +++-- cookbook/actions/delegate-revoke.ts | 33 +++-- cookbook/actions/load-ata.ts | 21 +--- cookbook/actions/merge-token-accounts.ts | 27 ++--- cookbook/actions/mint-to.ts | 26 +--- cookbook/actions/transfer-interface.ts | 30 +---- cookbook/actions/unwrap.ts | 26 ++-- cookbook/actions/wrap.ts | 24 ++-- cookbook/instructions/create-ata.ts | 14 +-- cookbook/instructions/create-mint.ts | 11 +- cookbook/instructions/load-ata.ts | 33 ++--- cookbook/instructions/mint-to.ts | 16 ++- cookbook/instructions/transfer-interface.ts | 14 +-- cookbook/instructions/unwrap.ts | 34 +++--- cookbook/instructions/wrap.ts | 36 +++--- cookbook/package.json | 1 - toolkits/payments-and-wallets/get-balance.ts | 91 ++++++++------ toolkits/payments-and-wallets/get-history.ts | 92 ++++++-------- .../payments-and-wallets/send-and-receive.ts | 114 +++++------------- toolkits/payments-and-wallets/unwrap.ts | 68 +++-------- toolkits/payments-and-wallets/wrap.ts | 89 ++++---------- 26 files changed, 340 insertions(+), 627 deletions(-) diff --git a/cookbook/actions/compress-batch.ts b/cookbook/actions/compress-batch.ts index e0ab6f0..9034b1c 100644 --- a/cookbook/actions/compress-batch.ts +++ b/cookbook/actions/compress-batch.ts @@ -1,12 +1,7 @@ import "dotenv/config"; import { Keypair } from "@solana/web3.js"; import { createRpc, bn } from "@lightprotocol/stateless.js"; -import { - createMint, - mintTo, - decompress, - compress, -} from "@lightprotocol/compressed-token"; +import { createMint, mintTo, decompress, compress } from "@lightprotocol/compressed-token"; import { createAssociatedTokenAccount } from "@solana/spl-token"; import { homedir } from "os"; import { readFileSync } from "fs"; @@ -18,42 +13,20 @@ const payer = Keypair.fromSecretKey( ) ); -async function main() { +(async function () { const rpc = createRpc(RPC_URL); + // Setup: Get SPL tokens (needed to compress) const { mint } = await createMint(rpc, payer, payer.publicKey, 9); - console.log("Mint:", mint.toBase58()); - - const splAta = await createAssociatedTokenAccount( - rpc, - payer, - mint, - payer.publicKey - ); - - // Fund SPL ATA: mint compressed, then decompress + const splAta = await createAssociatedTokenAccount(rpc, payer, mint, payer.publicKey); await mintTo(rpc, payer, mint, payer.publicKey, payer, bn(10000)); await decompress(rpc, payer, mint, bn(10000), payer, splAta); // Batch compress to multiple recipients - const recipients = Array.from( - { length: 5 }, - () => Keypair.generate().publicKey - ); + const recipients = Array.from({ length: 5 }, () => Keypair.generate().publicKey); const amounts = [bn(100), bn(200), bn(300), bn(400), bn(500)]; - const signature = await compress( - rpc, - payer, - mint, - amounts, - payer, - splAta, - recipients - ); - - console.log("Batch compressed to 5 recipients"); - console.log("Tx:", signature); -} + const tx = await compress(rpc, payer, mint, amounts, payer, splAta, recipients); -main().catch(console.error); + console.log("Tx:", tx); +})(); diff --git a/cookbook/actions/compress.ts b/cookbook/actions/compress.ts index 9791a1a..f29ceb0 100644 --- a/cookbook/actions/compress.ts +++ b/cookbook/actions/compress.ts @@ -1,12 +1,7 @@ import "dotenv/config"; import { Keypair } from "@solana/web3.js"; import { createRpc, bn } from "@lightprotocol/stateless.js"; -import { - createMint, - mintTo, - decompress, - compress, -} from "@lightprotocol/compressed-token"; +import { createMint, mintTo, decompress, compress } from "@lightprotocol/compressed-token"; import { createAssociatedTokenAccount } from "@solana/spl-token"; import { homedir } from "os"; import { readFileSync } from "fs"; @@ -18,36 +13,18 @@ const payer = Keypair.fromSecretKey( ) ); -async function main() { +(async function () { const rpc = createRpc(RPC_URL); + // Setup: Get SPL tokens (needed to compress) const { mint } = await createMint(rpc, payer, payer.publicKey, 9); - console.log("Mint:", mint.toBase58()); - - const splAta = await createAssociatedTokenAccount( - rpc, - payer, - mint, - payer.publicKey - ); - - // Fund SPL ATA: mint compressed, then decompress + const splAta = await createAssociatedTokenAccount(rpc, payer, mint, payer.publicKey); await mintTo(rpc, payer, mint, payer.publicKey, payer, bn(1000)); await decompress(rpc, payer, mint, bn(1000), payer, splAta); + // Compress SPL tokens to cold storage const recipient = Keypair.generate(); - const signature = await compress( - rpc, - payer, - mint, - bn(500), - payer, - splAta, - recipient.publicKey - ); - - console.log("Compressed 500 tokens to:", recipient.publicKey.toBase58()); - console.log("Tx:", signature); -} + const tx = await compress(rpc, payer, mint, bn(500), payer, splAta, recipient.publicKey); -main().catch(console.error); + console.log("Tx:", tx); +})(); diff --git a/cookbook/actions/create-ata.ts b/cookbook/actions/create-ata.ts index 95a347f..d10aa55 100644 --- a/cookbook/actions/create-ata.ts +++ b/cookbook/actions/create-ata.ts @@ -15,15 +15,13 @@ const payer = Keypair.fromSecretKey( ) ); -async function main() { +(async function () { const rpc = createRpc(RPC_URL); const { mint } = await createMintInterface(rpc, payer, payer, null, 9); - console.log("Mint:", mint.toBase58()); const owner = Keypair.generate(); const ata = await createAtaInterface(rpc, payer, mint, owner.publicKey); - console.log("ATA:", ata.toBase58()); -} -main().catch(console.error); + console.log("ATA:", ata.toBase58()); +})(); diff --git a/cookbook/actions/create-mint.ts b/cookbook/actions/create-mint.ts index 3faf198..42fe9e2 100644 --- a/cookbook/actions/create-mint.ts +++ b/cookbook/actions/create-mint.ts @@ -1,10 +1,7 @@ import "dotenv/config"; import { Keypair } from "@solana/web3.js"; import { createRpc } from "@lightprotocol/stateless.js"; -import { - createMintInterface, - createTokenMetadata, -} from "@lightprotocol/compressed-token"; +import { createMintInterface, createTokenMetadata } from "@lightprotocol/compressed-token"; import { homedir } from "os"; import { readFileSync } from "fs"; @@ -15,27 +12,21 @@ const payer = Keypair.fromSecretKey( ) ); -async function main() { +(async function () { const rpc = createRpc(RPC_URL); const { mint, transactionSignature } = await createMintInterface( rpc, payer, - payer, // mintAuthority - null, // freezeAuthority + payer, + null, 9, - undefined, // mintSigner - undefined, // confirmOptions - undefined, // programId - createTokenMetadata( - "Example Token", - "EXT", - "https://example.com/metadata.json" - ) + undefined, + undefined, + undefined, + createTokenMetadata("Example Token", "EXT", "https://example.com/metadata.json") ); console.log("Mint:", mint.toBase58()); console.log("Tx:", transactionSignature); -} - -main().catch(console.error); +})(); diff --git a/cookbook/actions/decompress.ts b/cookbook/actions/decompress.ts index 3b619ec..e6f2e03 100644 --- a/cookbook/actions/decompress.ts +++ b/cookbook/actions/decompress.ts @@ -17,32 +17,21 @@ const payer = Keypair.fromSecretKey( ) ); -async function main() { +(async function () { const rpc = createRpc(RPC_URL); + // Setup: Get compressed tokens (cold storage) const { mint } = await createMint(rpc, payer, payer.publicKey, 9); - console.log("Mint:", mint.toBase58()); - await mintTo(rpc, payer, mint, payer.publicKey, payer, bn(1000)); + // Decompress to SPL ATA const splAta = await createAssociatedTokenAccount( rpc, payer, mint, payer.publicKey ); + const tx = await decompress(rpc, payer, mint, bn(500), payer, splAta); - const signature = await decompress( - rpc, - payer, - mint, - bn(500), - payer, - splAta - ); - - console.log("Decompressed 500 tokens to SPL ATA"); - console.log("Tx:", signature); -} - -main().catch(console.error); + console.log("Tx:", tx); +})(); diff --git a/cookbook/actions/delegate-approve.ts b/cookbook/actions/delegate-approve.ts index 1055c11..130ecaa 100644 --- a/cookbook/actions/delegate-approve.ts +++ b/cookbook/actions/delegate-approve.ts @@ -12,22 +12,23 @@ const payer = Keypair.fromSecretKey( ) ); -async function main() { +(async function () { const rpc = createRpc(RPC_URL); + // Setup: Get compressed tokens const { mint } = await createMint(rpc, payer, payer.publicKey, 9); - console.log("Mint:", mint.toBase58()); - await mintTo(rpc, payer, mint, payer.publicKey, payer, bn(1000)); + // Approve delegation const delegate = Keypair.generate(); - const signature = await approve(rpc, payer, mint, bn(500), payer, delegate.publicKey); - - console.log("Approved delegation of 500 tokens to:", delegate.publicKey.toBase58()); - console.log("Tx:", signature); - - const delegatedAccounts = await rpc.getCompressedTokenAccountsByDelegate(delegate.publicKey, { mint }); - console.log("Delegated accounts:", delegatedAccounts.items.length); -} - -main().catch(console.error); + const tx = await approve( + rpc, + payer, + mint, + bn(500), + payer, + delegate.publicKey + ); + + console.log("Tx:", tx); +})(); diff --git a/cookbook/actions/delegate-revoke.ts b/cookbook/actions/delegate-revoke.ts index f7e7e17..bb135d8 100644 --- a/cookbook/actions/delegate-revoke.ts +++ b/cookbook/actions/delegate-revoke.ts @@ -1,7 +1,12 @@ import "dotenv/config"; import { Keypair } from "@solana/web3.js"; import { createRpc, bn } from "@lightprotocol/stateless.js"; -import { createMint, mintTo, approve, revoke } from "@lightprotocol/compressed-token"; +import { + createMint, + mintTo, + approve, + revoke, +} from "@lightprotocol/compressed-token"; import { homedir } from "os"; import { readFileSync } from "fs"; @@ -12,28 +17,22 @@ const payer = Keypair.fromSecretKey( ) ); -async function main() { +(async function () { const rpc = createRpc(RPC_URL); + // Setup: Get compressed tokens const { mint } = await createMint(rpc, payer, payer.publicKey, 9); - console.log("Mint:", mint.toBase58()); - await mintTo(rpc, payer, mint, payer.publicKey, payer, bn(1000)); + // Approve then revoke delegation const delegate = Keypair.generate(); await approve(rpc, payer, mint, bn(500), payer, delegate.publicKey); - console.log("Approved delegation to:", delegate.publicKey.toBase58()); - - const delegatedAccounts = await rpc.getCompressedTokenAccountsByDelegate(delegate.publicKey, { mint }); - console.log("Delegated accounts:", delegatedAccounts.items.length); - - const signature = await revoke(rpc, payer, delegatedAccounts.items, payer); - - console.log("Revoked delegation"); - console.log("Tx:", signature); - const afterRevoke = await rpc.getCompressedTokenAccountsByDelegate(delegate.publicKey, { mint }); - console.log("After revoke:", afterRevoke.items.length, "accounts"); -} + const delegatedAccounts = await rpc.getCompressedTokenAccountsByDelegate( + delegate.publicKey, + { mint } + ); + const tx = await revoke(rpc, payer, delegatedAccounts.items, payer); -main().catch(console.error); + console.log("Tx:", tx); +})(); diff --git a/cookbook/actions/load-ata.ts b/cookbook/actions/load-ata.ts index 6675333..b06e84b 100644 --- a/cookbook/actions/load-ata.ts +++ b/cookbook/actions/load-ata.ts @@ -17,25 +17,16 @@ const payer = Keypair.fromSecretKey( ) ); -async function main() { +(async function () { const rpc = createRpc(RPC_URL); + // Setup: Get compressed tokens (cold storage) const { mint } = await createMint(rpc, payer, payer.publicKey, 9); - console.log("Mint:", mint.toBase58()); - await mintTo(rpc, payer, mint, payer.publicKey, payer, bn(1000)); + // Load compressed tokens to hot balance const ctokenAta = getAssociatedTokenAddressInterface(mint, payer.publicKey); + const tx = await loadAta(rpc, ctokenAta, payer, mint, payer); - // Load compressed tokens (cold) to hot balance, creates ATA if needed - const signature = await loadAta(rpc, ctokenAta, payer, mint, payer); - - if (signature) { - console.log("Loaded tokens to hot balance"); - console.log("Tx:", signature); - } else { - console.log("Nothing to load"); - } -} - -main().catch(console.error); + console.log("Tx:", tx); +})(); diff --git a/cookbook/actions/merge-token-accounts.ts b/cookbook/actions/merge-token-accounts.ts index cc9042c..40fab14 100644 --- a/cookbook/actions/merge-token-accounts.ts +++ b/cookbook/actions/merge-token-accounts.ts @@ -1,7 +1,11 @@ import "dotenv/config"; import { Keypair } from "@solana/web3.js"; import { createRpc, bn } from "@lightprotocol/stateless.js"; -import { createMint, mintTo, mergeTokenAccounts } from "@lightprotocol/compressed-token"; +import { + createMint, + mintTo, + mergeTokenAccounts, +} from "@lightprotocol/compressed-token"; import { homedir } from "os"; import { readFileSync } from "fs"; @@ -12,26 +16,17 @@ const payer = Keypair.fromSecretKey( ) ); -async function main() { +(async function () { const rpc = createRpc(RPC_URL); + // Setup: Create multiple compressed token accounts const { mint } = await createMint(rpc, payer, payer.publicKey, 9); - console.log("Mint:", mint.toBase58()); - - // Mint multiple times to create multiple compressed accounts for (let i = 0; i < 5; i++) { await mintTo(rpc, payer, mint, payer.publicKey, payer, bn(100)); } - const accountsBefore = await rpc.getCompressedTokenAccountsByOwner(payer.publicKey, { mint }); - console.log("Accounts before merge:", accountsBefore.items.length); - - const signature = await mergeTokenAccounts(rpc, payer, mint, payer); - - console.log("Tx:", signature); - - const accountsAfter = await rpc.getCompressedTokenAccountsByOwner(payer.publicKey, { mint }); - console.log("Accounts after merge:", accountsAfter.items.length); -} + // Merge multiple accounts into one + const tx = await mergeTokenAccounts(rpc, payer, mint, payer); -main().catch(console.error); + console.log("Tx:", tx); +})(); diff --git a/cookbook/actions/mint-to.ts b/cookbook/actions/mint-to.ts index c8ac7da..174143a 100644 --- a/cookbook/actions/mint-to.ts +++ b/cookbook/actions/mint-to.ts @@ -17,32 +17,16 @@ const payer = Keypair.fromSecretKey( ) ); -async function main() { +(async function () { const rpc = createRpc(RPC_URL); const { mint } = await createMintInterface(rpc, payer, payer, null, 9); - console.log("Mint:", mint.toBase58()); const recipient = Keypair.generate(); await createAtaInterface(rpc, payer, mint, recipient.publicKey); - const destination = getAssociatedTokenAddressInterface( - mint, - recipient.publicKey - ); - const amount = 1_000_000_000; + const destination = getAssociatedTokenAddressInterface(mint, recipient.publicKey); + const tx = await mintToInterface(rpc, payer, mint, destination, payer, 1_000_000_000); - const txSignature = await mintToInterface( - rpc, - payer, - mint, - destination, - payer, - amount - ); - - console.log("Minted:", amount); - console.log("Tx:", txSignature); -} - -main().catch(console.error); + console.log("Tx:", tx); +})(); diff --git a/cookbook/actions/transfer-interface.ts b/cookbook/actions/transfer-interface.ts index a85d419..05447a0 100644 --- a/cookbook/actions/transfer-interface.ts +++ b/cookbook/actions/transfer-interface.ts @@ -18,39 +18,21 @@ const payer = Keypair.fromSecretKey( ) ); -async function main() { +(async function () { const rpc = createRpc(RPC_URL); const { mint } = await createMintInterface(rpc, payer, payer, null, 9); - console.log("Mint:", mint.toBase58()); const sender = Keypair.generate(); await createAtaInterface(rpc, payer, mint, sender.publicKey); - const senderAta = getAssociatedTokenAddressInterface( - mint, - sender.publicKey - ); + const senderAta = getAssociatedTokenAddressInterface(mint, sender.publicKey); await mintToInterface(rpc, payer, mint, senderAta, payer, 1_000_000_000); const recipient = Keypair.generate(); await createAtaInterface(rpc, payer, mint, recipient.publicKey); - const recipientAta = getAssociatedTokenAddressInterface( - mint, - recipient.publicKey - ); + const recipientAta = getAssociatedTokenAddressInterface(mint, recipient.publicKey); - const txSignature = await transferInterface( - rpc, - payer, - senderAta, - mint, - recipientAta, - sender, - 500_000_000 - ); + const tx = await transferInterface(rpc, payer, senderAta, mint, recipientAta, sender, 500_000_000); - console.log("Transferred 0.5 tokens"); - console.log("Tx:", txSignature); -} - -main().catch(console.error); + console.log("Tx:", tx); +})(); diff --git a/cookbook/actions/unwrap.ts b/cookbook/actions/unwrap.ts index 09d76b0..c39726f 100644 --- a/cookbook/actions/unwrap.ts +++ b/cookbook/actions/unwrap.ts @@ -14,21 +14,21 @@ const payer = Keypair.fromSecretKey( ) ); -async function main() { +(async function () { const rpc = createRpc(RPC_URL); + // Setup: Get compressed tokens (cold storage) const { mint } = await createMint(rpc, payer, payer.publicKey, 9); - console.log("Mint:", mint.toBase58()); - await mintTo(rpc, payer, mint, payer.publicKey, payer, bn(1000)); - const splAta = await createAssociatedTokenAccount(rpc, payer, mint, payer.publicKey); - - // Unwrap auto-loads compressed tokens to hot balance first - const signature = await unwrap(rpc, payer, splAta, payer, mint, bn(500)); - - console.log("Unwrapped 500 tokens to SPL ATA"); - console.log("Tx:", signature); -} - -main().catch(console.error); + // Unwrap rent-free tokens to SPL ATA + const splAta = await createAssociatedTokenAccount( + rpc, + payer, + mint, + payer.publicKey + ); + const tx = await unwrap(rpc, payer, splAta, payer, mint, bn(500)); + + console.log("Tx:", tx); +})(); diff --git a/cookbook/actions/wrap.ts b/cookbook/actions/wrap.ts index de1454e..2d14e72 100644 --- a/cookbook/actions/wrap.ts +++ b/cookbook/actions/wrap.ts @@ -20,25 +20,25 @@ const payer = Keypair.fromSecretKey( ) ); -async function main() { +(async function () { const rpc = createRpc(RPC_URL); + // Setup: Get SPL tokens (needed to wrap) const { mint } = await createMint(rpc, payer, payer.publicKey, 9); - console.log("Mint:", mint.toBase58()); - - const splAta = await createAssociatedTokenAccount(rpc, payer, mint, payer.publicKey); - - // Fund SPL ATA: mint compressed, then decompress + const splAta = await createAssociatedTokenAccount( + rpc, + payer, + mint, + payer.publicKey + ); await mintTo(rpc, payer, mint, payer.publicKey, payer, bn(1000)); await decompress(rpc, payer, mint, bn(1000), payer, splAta); + // Wrap SPL tokens to rent-free token ATA const ctokenAta = getAssociatedTokenAddressInterface(mint, payer.publicKey); await createAtaInterfaceIdempotent(rpc, payer, mint, payer.publicKey); - const signature = await wrap(rpc, payer, splAta, ctokenAta, payer, mint, bn(500)); - - console.log("Wrapped 500 tokens to c-token ATA:", ctokenAta.toBase58()); - console.log("Tx:", signature); -} + const tx = await wrap(rpc, payer, splAta, ctokenAta, payer, mint, bn(500)); -main().catch(console.error); + console.log("Tx:", tx); +})(); diff --git a/cookbook/instructions/create-ata.ts b/cookbook/instructions/create-ata.ts index 5334f83..3a5b2b2 100644 --- a/cookbook/instructions/create-ata.ts +++ b/cookbook/instructions/create-ata.ts @@ -1,11 +1,6 @@ import "dotenv/config"; import { Keypair, ComputeBudgetProgram } from "@solana/web3.js"; -import { - createRpc, - buildAndSignTx, - sendAndConfirmTx, - CTOKEN_PROGRAM_ID, -} from "@lightprotocol/stateless.js"; +import { createRpc, buildAndSignTx, sendAndConfirmTx, CTOKEN_PROGRAM_ID } from "@lightprotocol/stateless.js"; import { createMintInterface, createAssociatedTokenAccountInterfaceInstruction, @@ -21,11 +16,10 @@ const payer = Keypair.fromSecretKey( ) ); -async function main() { +(async function () { const rpc = createRpc(RPC_URL); const { mint } = await createMintInterface(rpc, payer, payer, null, 9); - console.log("Mint:", mint.toBase58()); const owner = Keypair.generate(); const associatedToken = getAssociatedTokenAddressInterface(mint, owner.publicKey); @@ -48,6 +42,4 @@ async function main() { console.log("ATA:", associatedToken.toBase58()); console.log("Tx:", signature); -} - -main().catch(console.error); +})(); diff --git a/cookbook/instructions/create-mint.ts b/cookbook/instructions/create-mint.ts index eab10be..29e4dcb 100644 --- a/cookbook/instructions/create-mint.ts +++ b/cookbook/instructions/create-mint.ts @@ -29,13 +29,12 @@ const payer = Keypair.fromSecretKey( ) ); -async function main() { +(async function () { const rpc = createRpc(RPC_URL); const mintSigner = Keypair.generate(); const addressTreeInfo = getBatchAddressTreeInfo(); const stateTreeInfo = selectStateTreeInfo(await rpc.getStateTreeInfos()); - const [mintPda] = findMintAddress(mintSigner.publicKey); const validityProof = await rpc.getValidityProofV2( @@ -47,8 +46,8 @@ async function main() { const ix = createMintInstruction( mintSigner.publicKey, 9, - payer.publicKey, // mintAuthority - null, // freezeAuthority + payer.publicKey, + null, payer.publicKey, validityProof, addressTreeInfo, @@ -67,6 +66,4 @@ async function main() { console.log("Mint:", mintPda.toBase58()); console.log("Tx:", signature); -} - -main().catch(console.error); +})(); diff --git a/cookbook/instructions/load-ata.ts b/cookbook/instructions/load-ata.ts index 28724a3..cc2922f 100644 --- a/cookbook/instructions/load-ata.ts +++ b/cookbook/instructions/load-ata.ts @@ -1,18 +1,7 @@ import "dotenv/config"; import { Keypair, ComputeBudgetProgram } from "@solana/web3.js"; -import { - createRpc, - bn, - buildAndSignTx, - sendAndConfirmTx, - dedupeSigner, -} from "@lightprotocol/stateless.js"; -import { - createMint, - mintTo, - createLoadAtaInstructions, - getAssociatedTokenAddressInterface, -} from "@lightprotocol/compressed-token"; +import { createRpc, bn, buildAndSignTx, sendAndConfirmTx } from "@lightprotocol/stateless.js"; +import { createMint, mintTo, createLoadAtaInstructions, getAssociatedTokenAddressInterface } from "@lightprotocol/compressed-token"; import { homedir } from "os"; import { readFileSync } from "fs"; @@ -23,14 +12,14 @@ const payer = Keypair.fromSecretKey( ) ); -async function main() { +(async function () { const rpc = createRpc(RPC_URL); + // Setup: Get compressed tokens (cold storage) const { mint } = await createMint(rpc, payer, payer.publicKey, 9); - console.log("Mint:", mint.toBase58()); - await mintTo(rpc, payer, mint, payer.publicKey, payer, bn(1000)); + // Create load instructions to move tokens from cold to hot balance const ctokenAta = getAssociatedTokenAddressInterface(mint, payer.publicKey); const ixs = await createLoadAtaInstructions(rpc, ctokenAta, payer.publicKey, mint, payer.publicKey); @@ -41,18 +30,12 @@ async function main() { } const { blockhash } = await rpc.getLatestBlockhash(); - const additionalSigners = dedupeSigner(payer, [payer]); - const tx = buildAndSignTx( [ComputeBudgetProgram.setComputeUnitLimit({ units: 500_000 }), ...ixs], payer, - blockhash, - additionalSigners + blockhash ); - const signature = await sendAndConfirmTx(rpc, tx); - console.log("Loaded tokens to hot balance"); - console.log("Tx:", signature); -} -main().catch(console.error); + console.log("Tx:", signature); +})(); diff --git a/cookbook/instructions/mint-to.ts b/cookbook/instructions/mint-to.ts index 7bb9884..92ff7fd 100644 --- a/cookbook/instructions/mint-to.ts +++ b/cookbook/instructions/mint-to.ts @@ -24,15 +24,17 @@ const payer = Keypair.fromSecretKey( ) ); -async function main() { +(async function () { const rpc = createRpc(RPC_URL); const { mint } = await createMintInterface(rpc, payer, payer, null, 9); - console.log("Mint:", mint.toBase58()); const recipient = Keypair.generate(); await createAtaInterface(rpc, payer, mint, recipient.publicKey); - const destination = getAssociatedTokenAddressInterface(mint, recipient.publicKey); + const destination = getAssociatedTokenAddressInterface( + mint, + recipient.publicKey + ); const mintInterface = await getMintInterface(rpc, mint); @@ -52,13 +54,12 @@ async function main() { ); } - const amount = 1_000_000_000; const ix = createMintToInterfaceInstruction( mintInterface, destination, payer.publicKey, payer.publicKey, - amount, + 1_000_000_000, validityProof ); @@ -70,8 +71,5 @@ async function main() { ); const signature = await sendAndConfirmTx(rpc, tx); - console.log("Minted:", amount); console.log("Tx:", signature); -} - -main().catch(console.error); +})(); diff --git a/cookbook/instructions/transfer-interface.ts b/cookbook/instructions/transfer-interface.ts index d6d2c38..da24697 100644 --- a/cookbook/instructions/transfer-interface.ts +++ b/cookbook/instructions/transfer-interface.ts @@ -1,10 +1,6 @@ import "dotenv/config"; import { Keypair, ComputeBudgetProgram } from "@solana/web3.js"; -import { - createRpc, - buildAndSignTx, - sendAndConfirmTx, -} from "@lightprotocol/stateless.js"; +import { createRpc, buildAndSignTx, sendAndConfirmTx } from "@lightprotocol/stateless.js"; import { createMintInterface, createAtaInterface, @@ -22,11 +18,10 @@ const payer = Keypair.fromSecretKey( ) ); -async function main() { +(async function () { const rpc = createRpc(RPC_URL); const { mint } = await createMintInterface(rpc, payer, payer, null, 9); - console.log("Mint:", mint.toBase58()); const sender = Keypair.generate(); await createAtaInterface(rpc, payer, mint, sender.publicKey); @@ -48,8 +43,5 @@ async function main() { ); const signature = await sendAndConfirmTx(rpc, tx); - console.log("Transferred 0.5 tokens"); console.log("Tx:", signature); -} - -main().catch(console.error); +})(); diff --git a/cookbook/instructions/unwrap.ts b/cookbook/instructions/unwrap.ts index 303ce9e..f051291 100644 --- a/cookbook/instructions/unwrap.ts +++ b/cookbook/instructions/unwrap.ts @@ -4,7 +4,6 @@ import { createRpc, buildAndSignTx, sendAndConfirmTx, - dedupeSigner, bn, } from "@lightprotocol/stateless.js"; import { @@ -26,25 +25,30 @@ const payer = Keypair.fromSecretKey( ) ); -async function main() { +(async function () { const rpc = createRpc(RPC_URL); + // Setup: Get compressed tokens (cold storage) const { mint } = await createMint(rpc, payer, payer.publicKey, 9); - console.log("Mint:", mint.toBase58()); - await mintTo(rpc, payer, mint, payer.publicKey, payer, bn(1000)); + // Load compressed tokens to hot balance, then create unwrap instruction const ctokenAta = getAssociatedTokenAddressInterface(mint, payer.publicKey); await loadAta(rpc, ctokenAta, payer, mint, payer); - const splAta = await createAssociatedTokenAccount(rpc, payer, mint, payer.publicKey); + const splAta = await createAssociatedTokenAccount( + rpc, + payer, + mint, + payer.publicKey + ); const splInterfaceInfos = await getSplInterfaceInfos(rpc, mint); - const splInterfaceInfo = splInterfaceInfos.find((info) => info.isInitialized); + const splInterfaceInfo = splInterfaceInfos.find( + (info) => info.isInitialized + ); - if (!splInterfaceInfo) { - throw new Error("No SPL interface found"); - } + if (!splInterfaceInfo) throw new Error("No SPL interface found"); const ix = createUnwrapInstruction( ctokenAta, @@ -57,18 +61,12 @@ async function main() { ); const { blockhash } = await rpc.getLatestBlockhash(); - const additionalSigners = dedupeSigner(payer, [payer]); - const tx = buildAndSignTx( [ComputeBudgetProgram.setComputeUnitLimit({ units: 200_000 }), ix], payer, - blockhash, - additionalSigners + blockhash ); - const signature = await sendAndConfirmTx(rpc, tx); - console.log("Unwrapped 500 tokens"); - console.log("Tx:", signature); -} -main().catch(console.error); + console.log("Tx:", signature); +})(); diff --git a/cookbook/instructions/wrap.ts b/cookbook/instructions/wrap.ts index 5df0564..ebb129c 100644 --- a/cookbook/instructions/wrap.ts +++ b/cookbook/instructions/wrap.ts @@ -4,7 +4,6 @@ import { createRpc, buildAndSignTx, sendAndConfirmTx, - dedupeSigner, bn, } from "@lightprotocol/stateless.js"; import { @@ -27,27 +26,30 @@ const payer = Keypair.fromSecretKey( ) ); -async function main() { +(async function () { const rpc = createRpc(RPC_URL); + // Setup: Get SPL tokens (needed to wrap) const { mint } = await createMint(rpc, payer, payer.publicKey, 9); - console.log("Mint:", mint.toBase58()); - - const splAta = await createAssociatedTokenAccount(rpc, payer, mint, payer.publicKey); - - // Fund SPL ATA: mint compressed, then decompress + const splAta = await createAssociatedTokenAccount( + rpc, + payer, + mint, + payer.publicKey + ); await mintTo(rpc, payer, mint, payer.publicKey, payer, bn(1000)); await decompress(rpc, payer, mint, bn(1000), payer, splAta); + // Create wrap instruction const ctokenAta = getAssociatedTokenAddressInterface(mint, payer.publicKey); await createAtaInterfaceIdempotent(rpc, payer, mint, payer.publicKey); const splInterfaceInfos = await getSplInterfaceInfos(rpc, mint); - const splInterfaceInfo = splInterfaceInfos.find((info) => info.isInitialized); + const splInterfaceInfo = splInterfaceInfos.find( + (info) => info.isInitialized + ); - if (!splInterfaceInfo) { - throw new Error("No SPL interface found"); - } + if (!splInterfaceInfo) throw new Error("No SPL interface found"); const ix = createWrapInstruction( splAta, @@ -60,18 +62,12 @@ async function main() { ); const { blockhash } = await rpc.getLatestBlockhash(); - const additionalSigners = dedupeSigner(payer, [payer]); - const tx = buildAndSignTx( [ComputeBudgetProgram.setComputeUnitLimit({ units: 200_000 }), ix], payer, - blockhash, - additionalSigners + blockhash ); - const signature = await sendAndConfirmTx(rpc, tx); - console.log("Wrapped 500 tokens"); - console.log("Tx:", signature); -} -main().catch(console.error); + console.log("Tx:", signature); +})(); diff --git a/cookbook/package.json b/cookbook/package.json index e5dabe3..c6a92b4 100644 --- a/cookbook/package.json +++ b/cookbook/package.json @@ -15,7 +15,6 @@ "compress:action": "ts-node-esm actions/compress.ts", "compress:batch": "ts-node-esm actions/compress-batch.ts", "decompress:action": "ts-node-esm actions/decompress.ts", - "decompress:with-token-pool": "ts-node-esm actions/decompress-with-interface-pda.ts", "wrap:action": "ts-node-esm actions/wrap.ts", "wrap:instruction": "ts-node-esm instructions/wrap.ts", "unwrap:action": "ts-node-esm actions/unwrap.ts", diff --git a/toolkits/payments-and-wallets/get-balance.ts b/toolkits/payments-and-wallets/get-balance.ts index fc7b3a2..08fa5d4 100644 --- a/toolkits/payments-and-wallets/get-balance.ts +++ b/toolkits/payments-and-wallets/get-balance.ts @@ -1,54 +1,69 @@ import "dotenv/config"; import { Keypair } from "@solana/web3.js"; import { createRpc, bn } from "@lightprotocol/stateless.js"; -import { createMint, mintTo } from "@lightprotocol/compressed-token"; import { - getAtaInterface, - getAssociatedTokenAddressInterface, getOrCreateAtaInterface, + transferInterface, + createMintInterface, + mintToInterface, + getAtaInterface, } from "@lightprotocol/compressed-token/unified"; +import { homedir } from "os"; +import { readFileSync } from "fs"; -async function main() { - const rpc = createRpc(); - - // Setup - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); +(async function () { + const rpc = createRpc(RPC_URL); - // Create test mint and tokens - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( + // Setup: mint tokens + const { mint } = await createMintInterface( rpc, payer, - mintAuthority.publicKey, - 9, - mintKeypair + payer.publicKey, + null, + 9 ); + await mintToInterface(rpc, payer, mint, payer.publicKey, payer, bn(1000)); - // Mint tokens (creates cold balance) - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); - - // Create ATA and load cold to hot - await getOrCreateAtaInterface(rpc, payer, mint, owner); - - // === GET BALANCE === - const ata = getAssociatedTokenAddressInterface(mint, owner.publicKey); - const account = await getAtaInterface(rpc, ata, owner.publicKey, mint); + // Create ATA for payer + const { parsed: sourceAta } = await getOrCreateAtaInterface( + rpc, + payer, + mint, + payer + ); - console.log("ATA:", ata.toBase58()); - console.log("Balance:", account.parsed.amount.toString()); + // Create ATA for recipient + const recipient = Keypair.generate(); + const { parsed: recipientAta } = await getOrCreateAtaInterface( + rpc, + payer, + mint, + recipient + ); - // Show balance breakdown by source - console.log("\n=== Balance Sources ==="); - for (const source of account._sources ?? []) { - console.log(`${source.type}: ${source.amount.toString()}`); - } -} + await transferInterface( + rpc, + payer, + sourceAta.address, + mint, + recipientAta.address, + payer, + bn(100) + ); -main().catch(console.error); + // Get recipient's balance after transfer + const { parsed: account } = await getAtaInterface( + rpc, + recipientAta.address, + recipient.publicKey, + mint + ); + console.log("Recipient's balance:", account.amount); +})(); diff --git a/toolkits/payments-and-wallets/get-history.ts b/toolkits/payments-and-wallets/get-history.ts index 7b15c05..5e274ae 100644 --- a/toolkits/payments-and-wallets/get-history.ts +++ b/toolkits/payments-and-wallets/get-history.ts @@ -1,83 +1,63 @@ import "dotenv/config"; import { Keypair } from "@solana/web3.js"; import { createRpc, bn } from "@lightprotocol/stateless.js"; -import { createMint, mintTo } from "@lightprotocol/compressed-token"; import { getOrCreateAtaInterface, - getAssociatedTokenAddressInterface, transferInterface, + createMintInterface, + mintToInterface, } from "@lightprotocol/compressed-token/unified"; +import { homedir } from "os"; +import { readFileSync } from "fs"; -async function main() { - const rpc = createRpc(); +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); - // Setup - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); +(async function () { + const rpc = createRpc(RPC_URL); - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); - - const recipient = Keypair.generate(); - const airdropSig3 = await rpc.requestAirdrop(recipient.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig3, "confirmed"); - - // Create test mint and tokens - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( + // Setup: mint tokens + const { mint } = await createMintInterface( rpc, payer, - mintAuthority.publicKey, - 9, - mintKeypair + payer.publicKey, + null, + 9 ); + await mintToInterface(rpc, payer, mint, payer.publicKey, payer, bn(1000)); - // Mint and create ATAs - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); - await getOrCreateAtaInterface(rpc, payer, mint, owner); - await getOrCreateAtaInterface(rpc, payer, mint, recipient); - - // Make a transfer to create transaction history - const sourceAta = getAssociatedTokenAddressInterface(mint, owner.publicKey); - const destAta = getAssociatedTokenAddressInterface( + // Create ATA for payer + const { parsed: sourceAta } = await getOrCreateAtaInterface( + rpc, + payer, mint, - recipient.publicKey + payer ); - await transferInterface( + // Create ATA for recipient + const recipient = Keypair.generate(); + const { parsed: recipientAta } = await getOrCreateAtaInterface( rpc, payer, - sourceAta, mint, - destAta, - owner, - bn(100) + recipient ); + await transferInterface( rpc, payer, - sourceAta, + sourceAta.address, mint, - destAta, - owner, - bn(200) + recipientAta.address, + payer, + bn(100) ); - // === GET TRANSACTION HISTORY === - const result = await rpc.getSignaturesForOwnerInterface(owner.publicKey); - - console.log("=== Transaction History ==="); - console.log("Total signatures:", result.signatures.length); - console.log("On-chain txs:", result.solana.length); - console.log("Compressed txs:", result.compressed.length); - - console.log("\n=== Recent Transactions ==="); - for (const sig of result.signatures.slice(0, 5)) { - console.log(sig.signature); - } -} - -main().catch(console.error); + // Get transaction history + const result = await rpc.getSignaturesForOwnerInterface(payer.publicKey); + console.log("Signatures:", result.signatures.length); +})(); diff --git a/toolkits/payments-and-wallets/send-and-receive.ts b/toolkits/payments-and-wallets/send-and-receive.ts index 0b2123a..c52b741 100644 --- a/toolkits/payments-and-wallets/send-and-receive.ts +++ b/toolkits/payments-and-wallets/send-and-receive.ts @@ -1,112 +1,62 @@ import "dotenv/config"; import { Keypair } from "@solana/web3.js"; import { createRpc, bn } from "@lightprotocol/stateless.js"; -import { createMint, mintTo } from "@lightprotocol/compressed-token"; import { getOrCreateAtaInterface, - getAssociatedTokenAddressInterface, transferInterface, + createMintInterface, + mintToInterface, + getAtaInterface, } from "@lightprotocol/compressed-token/unified"; +import { homedir } from "os"; +import { readFileSync } from "fs"; -async function main() { - const rpc = createRpc(); +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); - // Setup wallets - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); +(async function () { + const rpc = createRpc(RPC_URL); - const sender = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(sender.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); - - const recipient = Keypair.generate(); - const airdropSig3 = await rpc.requestAirdrop(recipient.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig3, "confirmed"); - - console.log("Sender:", sender.publicKey.toBase58()); - console.log("Recipient:", recipient.publicKey.toBase58()); - - // Create a test mint (in production, use existing stablecoin mint) - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( + // Setup: mint tokens + const { mint } = await createMintInterface( rpc, payer, - mintAuthority.publicKey, - 9, - mintKeypair, + payer.publicKey, + null, + 9 ); - console.log("Mint:", mint.toBase58()); - - // Mint tokens to sender - await mintTo(rpc, payer, mint, sender.publicKey, mintAuthority, bn(1000)); - console.log("Minted 1000 tokens to sender"); + await mintToInterface(rpc, payer, mint, payer.publicKey, payer, bn(1000)); - // === RECEIVE: Get/create sender's ATA === - // This creates the ATA and loads any cold balance to hot - const senderAccount = await getOrCreateAtaInterface( + // Create ATA for payer + const { parsed: sourceAta } = await getOrCreateAtaInterface( rpc, payer, mint, - sender, // Signer enables auto-load - ); - console.log("\nSender ATA:", senderAccount.parsed.address.toBase58()); - console.log("Sender balance:", senderAccount.parsed.amount.toString()); - - // === RECEIVE: Get/create recipient's ATA === - const recipientAccount = await getOrCreateAtaInterface( - rpc, - payer, - mint, - recipient, - ); - console.log("\nRecipient ATA:", recipientAccount.parsed.address.toBase58()); - console.log( - "Recipient balance before:", - recipientAccount.parsed.amount.toString(), - ); - - // === SEND: Transfer tokens === - const sourceAta = getAssociatedTokenAddressInterface( - mint, - sender.publicKey, - ); - const destinationAta = getAssociatedTokenAddressInterface( - mint, - recipient.publicKey, + payer ); - const signature = await transferInterface( + // Create ATA for recipient + const recipient = Keypair.generate(); + const { parsed: recipientAta } = await getOrCreateAtaInterface( rpc, payer, - sourceAta, mint, - destinationAta, - sender, - bn(500), + recipient ); - console.log("\nTransferred 500 tokens"); - console.log("Transaction:", signature); - - // Check final balances - const senderFinal = await getOrCreateAtaInterface( + const txId = await transferInterface( rpc, payer, + sourceAta.address, mint, - sender.publicKey, - ); - const recipientFinal = await getOrCreateAtaInterface( - rpc, + recipientAta.address, payer, - mint, - recipient.publicKey, + bn(100) ); - console.log("\n=== Final Balances ==="); - console.log("Sender:", senderFinal.parsed.amount.toString()); - console.log("Recipient:", recipientFinal.parsed.amount.toString()); -} - -main().catch(console.error); + console.log("Tx:", txId); +})(); diff --git a/toolkits/payments-and-wallets/unwrap.ts b/toolkits/payments-and-wallets/unwrap.ts index e1026a0..8afcd49 100644 --- a/toolkits/payments-and-wallets/unwrap.ts +++ b/toolkits/payments-and-wallets/unwrap.ts @@ -3,65 +3,35 @@ import { Keypair } from "@solana/web3.js"; import { createRpc, bn } from "@lightprotocol/stateless.js"; import { createMint, mintTo } from "@lightprotocol/compressed-token"; import { - getOrCreateAtaInterface, unwrap, + getOrCreateAtaInterface, } from "@lightprotocol/compressed-token/unified"; -import { createAssociatedTokenAccount, getAccount } from "@solana/spl-token"; +import { createAssociatedTokenAccount } from "@solana/spl-token"; +import { homedir } from "os"; +import { readFileSync } from "fs"; -async function main() { - const rpc = createRpc(); +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); - // Setup - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); +(async function () { + const rpc = createRpc(RPC_URL); - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); + const { mint } = await createMint(rpc, payer, payer.publicKey, 9); + await mintTo(rpc, payer, mint, payer.publicKey, payer, bn(1000)); + await getOrCreateAtaInterface(rpc, payer, mint, payer); - // Create test mint - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair, - ); - console.log("Mint:", mint.toBase58()); - - // Mint and load to c-token ATA - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); - const ctokenAccount = await getOrCreateAtaInterface( - rpc, - payer, - mint, - owner, - ); - console.log("C-token ATA:", ctokenAccount.parsed.address.toBase58()); - console.log("C-token balance:", ctokenAccount.parsed.amount.toString()); - - // Create destination SPL ATA (must exist before unwrap) const splAta = await createAssociatedTokenAccount( rpc, payer, mint, - owner.publicKey, + payer.publicKey ); - console.log("\nSPL ATA:", splAta.toBase58()); - - // === UNWRAP: c-token → SPL === - // Off-ramp for CEX withdrawal - const signature = await unwrap(rpc, payer, splAta, owner, mint, bn(500)); - - console.log("\n=== Unwrapped 500 tokens ==="); - console.log("Transaction:", signature); - // Check SPL balance - const splBalance = await getAccount(rpc, splAta); - console.log("\nSPL balance (ready for CEX):", splBalance.amount.toString()); -} + const tx = await unwrap(rpc, payer, splAta, payer, mint, bn(500)); -main().catch(console.error); + console.log("Tx:", tx); +})(); diff --git a/toolkits/payments-and-wallets/wrap.ts b/toolkits/payments-and-wallets/wrap.ts index fd9f090..0122cb0 100644 --- a/toolkits/payments-and-wallets/wrap.ts +++ b/toolkits/payments-and-wallets/wrap.ts @@ -5,77 +5,40 @@ import { createMint, mintTo, decompress, +} from "@lightprotocol/compressed-token"; +import { wrap, getAssociatedTokenAddressInterface, createAtaInterfaceIdempotent, -} from "@lightprotocol/compressed-token"; -import { createAssociatedTokenAccount, getAccount } from "@solana/spl-token"; - -async function main() { - const rpc = createRpc(); - - // Setup - const payer = Keypair.generate(); - const airdropSig = await rpc.requestAirdrop(payer.publicKey, 10e9); - await rpc.confirmTransaction(airdropSig, "confirmed"); - - const owner = Keypair.generate(); - const airdropSig2 = await rpc.requestAirdrop(owner.publicKey, 1e9); - await rpc.confirmTransaction(airdropSig2, "confirmed"); - - // Create test mint - const mintAuthority = Keypair.generate(); - const mintKeypair = Keypair.generate(); - const { mint } = await createMint( - rpc, - payer, - mintAuthority.publicKey, - 9, - mintKeypair, - ); - console.log("Mint:", mint.toBase58()); - - // Create SPL ATA and fund it - // (Simulates receiving tokens from CEX) +} from "@lightprotocol/compressed-token/unified"; +import { createAssociatedTokenAccount } from "@solana/spl-token"; +import { homedir } from "os"; +import { readFileSync } from "fs"; + +const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +const payer = Keypair.fromSecretKey( + new Uint8Array( + JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) + ) +); + +(async function () { + const rpc = createRpc(RPC_URL); + + const { mint } = await createMint(rpc, payer, payer.publicKey, 9); const splAta = await createAssociatedTokenAccount( rpc, payer, mint, - owner.publicKey, - ); - console.log("SPL ATA:", splAta.toBase58()); - - // Mint compressed, then decompress to SPL (simulates CEX deposit) - await mintTo(rpc, payer, mint, owner.publicKey, mintAuthority, bn(1000)); - await decompress(rpc, payer, mint, bn(1000), owner, splAta); - - const splBalanceBefore = await getAccount(rpc, splAta); - console.log("SPL balance before wrap:", splBalanceBefore.amount.toString()); - - // Create c-token ATA (destination) - const ctokenAta = getAssociatedTokenAddressInterface(mint, owner.publicKey); - await createAtaInterfaceIdempotent(rpc, payer, mint, owner.publicKey); - console.log("C-token ATA:", ctokenAta.toBase58()); - - // === WRAP: SPL → c-token === - // On-ramp from CEX - const signature = await wrap( - rpc, - payer, - splAta, - ctokenAta, - owner, - mint, - bn(500), + payer.publicKey ); + await mintTo(rpc, payer, mint, payer.publicKey, payer, bn(1000)); + await decompress(rpc, payer, mint, bn(1000), payer, splAta); - console.log("\n=== Wrapped 500 tokens ==="); - console.log("Transaction:", signature); + const ctokenAta = getAssociatedTokenAddressInterface(mint, payer.publicKey); + await createAtaInterfaceIdempotent(rpc, payer, mint, payer.publicKey); - // Check balances after - const splBalanceAfter = await getAccount(rpc, splAta); - console.log("\nSPL balance after:", splBalanceAfter.amount.toString()); - console.log("C-token ATA now has 500 tokens ready for payments"); -} + const tx = await wrap(rpc, payer, splAta, ctokenAta, payer, mint, bn(500)); -main().catch(console.error); + console.log("Tx:", tx); +})(); From 4c0c3467e5742cafecd6c4eb24d14ee3fad347f4 Mon Sep 17 00:00:00 2001 From: tilo-14 Date: Wed, 24 Dec 2025 00:06:06 +0000 Subject: [PATCH 8/9] ci: add TypeScript type checking workflow Runs tsc --noEmit on all workspaces (quickstart, cookbook, payments-and-wallets) to verify TypeScript compiles without errors.> --- .github/workflows/typescript.yml | 41 ++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 .github/workflows/typescript.yml diff --git a/.github/workflows/typescript.yml b/.github/workflows/typescript.yml new file mode 100644 index 0000000..a92ebd8 --- /dev/null +++ b/.github/workflows/typescript.yml @@ -0,0 +1,41 @@ +name: TypeScript + +on: + push: + branches: [main] + pull_request: + branches: [main] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + NODE_VERSION: "22" + +jobs: + build: + name: Build & Type Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'npm' + + - name: Install dependencies + run: npm install + + - name: Type check quickstart + working-directory: quickstart + run: npx tsc --noEmit + + - name: Type check cookbook + working-directory: cookbook + run: npx tsc --noEmit + + - name: Type check payments-and-wallets + working-directory: toolkits/payments-and-wallets + run: npx tsc --noEmit From b8044abe0810d78c09a8b9c3f18feb5138202de9 Mon Sep 17 00:00:00 2001 From: tilo-14 Date: Wed, 24 Dec 2025 00:08:28 +0000 Subject: [PATCH 9/9] revert: remove CI workflow --- .github/workflows/typescript.yml | 41 -------------------------------- 1 file changed, 41 deletions(-) delete mode 100644 .github/workflows/typescript.yml diff --git a/.github/workflows/typescript.yml b/.github/workflows/typescript.yml deleted file mode 100644 index a92ebd8..0000000 --- a/.github/workflows/typescript.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: TypeScript - -on: - push: - branches: [main] - pull_request: - branches: [main] - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -env: - NODE_VERSION: "22" - -jobs: - build: - name: Build & Type Check - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-node@v4 - with: - node-version: ${{ env.NODE_VERSION }} - cache: 'npm' - - - name: Install dependencies - run: npm install - - - name: Type check quickstart - working-directory: quickstart - run: npx tsc --noEmit - - - name: Type check cookbook - working-directory: cookbook - run: npx tsc --noEmit - - - name: Type check payments-and-wallets - working-directory: toolkits/payments-and-wallets - run: npx tsc --noEmit