diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml new file mode 100644 index 00000000..8137d8c3 --- /dev/null +++ b/.github/actions/setup/action.yml @@ -0,0 +1,67 @@ +name: Setup Environment +description: Setup Rust, Solana CLI, and Light CLI for testing + +inputs: + solana-cli-version: + description: "Solana CLI version" + required: false + default: "2.1.21" + rust-toolchain: + description: "Rust toolchain version" + required: false + default: "1.85.0" + light-cli-version: + description: "Light CLI version" + required: false + default: "alpha" + +runs: + using: composite + steps: + - name: Install Rust toolchain + uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: ${{ inputs.rust-toolchain }} + cache: false + + - name: Setup Node.js (for Light CLI) + uses: actions/setup-node@v4 + with: + node-version: "22" + + - name: Cache npm global packages + uses: actions/cache@v4 + with: + path: ~/.npm + key: npm-${{ runner.os }}-light-cli-${{ inputs.light-cli-version }} + + - name: Cache Solana CLI tools + uses: actions/cache@v4 + with: + path: | + ~/.cache/solana/ + ~/.local/share/solana/ + key: solana-cli-${{ runner.os }}-${{ inputs.solana-cli-version }} + + - name: Install Solana CLI tools + shell: bash + run: | + sh -c "$(curl -sSfL https://release.anza.xyz/v${{ inputs.solana-cli-version }}/install)" + echo "/home/runner/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH + + - name: Install Light CLI + shell: bash + run: npm install -g @lightprotocol/zk-compression-cli@${{ inputs.light-cli-version }} + + - name: Generate keypair + shell: bash + run: solana-keygen new --no-bip39-passphrase + + - name: Display versions + shell: bash + run: | + rustc --version + cargo --version + solana --version + light --version + diff --git a/.github/workflows/typescript-tests.yml b/.github/workflows/typescript-tests.yml new file mode 100644 index 00000000..1b487439 --- /dev/null +++ b/.github/workflows/typescript-tests.yml @@ -0,0 +1,85 @@ +name: TypeScript + +on: + push: + branches: + - main + pull_request: + types: [opened, synchronize, reopened] + branches: + - main + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + SOLANA_CLI_VERSION: "2.1.21" + NODE_VERSION: "22" + +jobs: + typescript-tests: + name: TypeScript Tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Cache Solana CLI tools + uses: actions/cache@v4 + with: + path: | + ~/.cache/solana/ + ~/.local/share/solana/ + key: solana-cli-${{ runner.os }}-${{ env.SOLANA_CLI_VERSION }} + + - name: Install Solana CLI tools + run: | + sh -c "$(curl -sSfL https://release.anza.xyz/v${{ env.SOLANA_CLI_VERSION }}/install)" + echo "/home/runner/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH + + - name: Install Light CLI + run: npm install -g @lightprotocol/zk-compression-cli@alpha + + - name: Install Rust (for Photon) + uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: stable + cache: false + + - name: Cache Photon indexer + id: cache-photon + uses: actions/cache@v4 + with: + path: ~/.cargo/bin/photon + key: photon-${{ runner.os }}-1a785036de52896b68d06413e3b0231122d6aa4a + + - name: Install Photon indexer + if: steps.cache-photon.outputs.cache-hit != 'true' + run: cargo install --git https://github.com/lightprotocol/photon.git --rev 1a785036de52896b68d06413e3b0231122d6aa4a --locked + env: + RUSTFLAGS: "-A dead-code" + + - name: Generate keypair + run: solana-keygen new --no-bip39-passphrase + + - name: Install dependencies + working-directory: typescript-client + run: npm install + + - name: Start test validator + run: | + light test-validator & + sleep 15 + + - name: Run actions + working-directory: typescript-client + run: npm run test:actions + + - name: Run instructions + working-directory: typescript-client + run: npm run test:instructions diff --git a/.gitignore b/.gitignore index d57540e5..1803e1d1 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,6 @@ **/pnpm-lock.yaml **/package-lock.json **/*.json.bak -**/test-ledger \ No newline at end of file +**/test-ledger +**/target +cli/accounts/ diff --git a/README.md b/README.md index 40681d11..9d4b303d 100644 --- a/README.md +++ b/README.md @@ -1,85 +1,39 @@ # Light Token Examples -## Quickstart -### [Devnet Quickstart](devnet-quickstart/) +Light token is a high-performance token standard that reduces the cost of mint and token accounts by 200x. -End-to-end example: create a mint, token account, mint tokens, and transfer on devnet. +* All light mint and token accounts are on-chain accounts like SPL, but the light token program sponsors the rent-exemption cost for you. +* Light-token accounts can hold balances from any light, SPL, or Token-2022 mint. +* Light-mint accounts represent a unique mint and optionally can store token-metadata. Functionally equivalent to SPL mints. -## Cookbook +### Toolkits -Step-by-step recipes for light-token on Devnet/Localnet. +- **[Payments and Wallets](toolkits/payments-and-wallets/)** - All you need for wallet integrations and payment flows. Minimal API differences to SPL. +- **[Streaming Tokens](toolkits/streaming-tokens/)** - Stream mint events using Laserstream -### [Actions](cookbook/actions/) +### TypeScript Client -- **[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 +TypeScript examples for light-token-sdk. -### [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 - -## Toolkits - -### [Payments and Wallets](toolkits/payments-and-wallets/) - -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](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/) - -Rust program example with test to stream mint events of the Light-Token Program. - - -## Setup - -```bash -npm install @lightprotocol/stateless.js@alpha \ - @lightprotocol/compressed-token@alpha -``` - -```bash -cp .env.example .env # ...and set RPC_URL -``` - -## Run - -From repo root: - -```bash -# quickstart -npm run quickstart - -# cookbook (local) -npm run cookbook create-mint:action -npm run cookbook compress:action -# ... see cookbook/package.json for more - -# payments -npm run toolkit:payments send-and-receive -``` - - -For local net, install via `npm i -g @lightprotocol/zk-compression-cli@alpha`, then run `light test-validator` in a separate terminal. +- **create-mint** - Create a light-token mint + - [Action](typescript-client/actions/create-mint.ts) | [Instruction](typescript-client/instructions/create-mint.ts) +- **create-ata** - Create an associated light-token account + - [Action](typescript-client/actions/create-ata.ts) | [Instruction](typescript-client/instructions/create-ata.ts) +- **load-ata** - Load cold token account to hot balance + - [Action](typescript-client/actions/load-ata.ts) | [Instruction](typescript-client/instructions/load-ata.ts) +- **mint-to** - Mint tokens to a light-account + - [Action](typescript-client/actions/mint-to.ts) | [Instruction](typescript-client/instructions/mint-to.ts) +- **transfer-interface** - Transfer between light-token, T22, and SPL accounts + - [Action](typescript-client/actions/transfer-interface.ts) | [Instruction](typescript-client/instructions/transfer-interface.ts) +- **wrap** - Wrap SPL/T22 to light-token + - [Action](typescript-client/actions/wrap.ts) +- **unwrap** - Unwrap light-token to SPL/T22 + - [Action](typescript-client/actions/unwrap.ts) +- **delegate-approve** - Approve delegate + - [Action](typescript-client/actions/delegate-approve.ts) +- **delegate-revoke** - Revoke delegate + - [Action](typescript-client/actions/delegate-revoke.ts) ## Documentation Learn more [about to Light-Token here](https://www.zkcompression.com/light-token/welcome). - diff --git a/cookbook/actions/compress-batch.ts b/cookbook/actions/compress-batch.ts deleted file mode 100644 index 17286846..00000000 --- a/cookbook/actions/compress-batch.ts +++ /dev/null @@ -1,38 +0,0 @@ -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 { createAssociatedTokenAccount } from "@solana/spl-token"; -import { homedir } from "os"; -import { readFileSync } from "fs"; - -// devnet: -const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -// localnet: -// const RPC_URL = undefined; -const payer = Keypair.fromSecretKey( - new Uint8Array( - JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) - ) -); - -(async function () { - // devnet: - const rpc = createRpc(RPC_URL); - // localnet: - // const rpc = createRpc(); - - // Setup: Get SPL tokens (needed to compress) - const { mint } = await createMint(rpc, payer, payer.publicKey, 9); - 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 amounts = [bn(100), bn(200), bn(300), bn(400), bn(500)]; - - const tx = await compress(rpc, payer, mint, amounts, payer, splAta, recipients); - - console.log("Tx:", tx); -})(); diff --git a/cookbook/actions/compress.ts b/cookbook/actions/compress.ts deleted file mode 100644 index 5d46974a..00000000 --- a/cookbook/actions/compress.ts +++ /dev/null @@ -1,36 +0,0 @@ -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 { createAssociatedTokenAccount } from "@solana/spl-token"; -import { homedir } from "os"; -import { readFileSync } from "fs"; - -// devnet: -const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -// localnet: -// const RPC_URL = undefined; -const payer = Keypair.fromSecretKey( - new Uint8Array( - JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) - ) -); - -(async function () { - // devnet: - const rpc = createRpc(RPC_URL); - // localnet: - // const rpc = createRpc(); - - // Setup: Get SPL tokens (needed to compress) - const { mint } = await createMint(rpc, payer, payer.publicKey, 9); - 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 tx = await compress(rpc, payer, mint, bn(500), payer, splAta, recipient.publicKey); - - console.log("Tx:", tx); -})(); diff --git a/cookbook/actions/decompress-with-interface-pda.ts b/cookbook/actions/decompress-with-interface-pda.ts deleted file mode 100644 index 5c9d5618..00000000 --- a/cookbook/actions/decompress-with-interface-pda.ts +++ /dev/null @@ -1,66 +0,0 @@ -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"; - -// devnet: -const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -// localnet: -// const RPC_URL = undefined; -const payer = Keypair.fromSecretKey( - new Uint8Array( - JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) - ) -); - -async function main() { - // devnet: - const rpc = createRpc(RPC_URL); - // localnet: - // const rpc = createRpc(); - - 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.ts b/cookbook/actions/decompress.ts deleted file mode 100644 index b9aaacf1..00000000 --- a/cookbook/actions/decompress.ts +++ /dev/null @@ -1,43 +0,0 @@ -import "dotenv/config"; -import { Keypair } from "@solana/web3.js"; -import { createRpc, bn } from "@lightprotocol/stateless.js"; -import { - createMint, - mintTo, - decompress, -} from "@lightprotocol/compressed-token"; -import { createAssociatedTokenAccount } from "@solana/spl-token"; -import { homedir } from "os"; -import { readFileSync } from "fs"; - -// devnet: -const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -// localnet: -// const RPC_URL = undefined; -const payer = Keypair.fromSecretKey( - new Uint8Array( - JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) - ) -); - -(async function () { - // devnet: - const rpc = createRpc(RPC_URL); - // localnet: - // const rpc = createRpc(); - - // Setup: Get compressed tokens (cold storage) - const { mint } = await createMint(rpc, payer, payer.publicKey, 9); - 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); - - console.log("Tx:", tx); -})(); diff --git a/cookbook/actions/merge-token-accounts.ts b/cookbook/actions/merge-token-accounts.ts deleted file mode 100644 index 49155d6e..00000000 --- a/cookbook/actions/merge-token-accounts.ts +++ /dev/null @@ -1,38 +0,0 @@ -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 { homedir } from "os"; -import { readFileSync } from "fs"; - -// devnet: -const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -// localnet: -// const RPC_URL = undefined; -const payer = Keypair.fromSecretKey( - new Uint8Array( - JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) - ) -); - -(async function () { - // devnet: - const rpc = createRpc(RPC_URL); - // localnet: - // const rpc = createRpc(); - - // Setup: Create multiple compressed token accounts - const { mint } = await createMint(rpc, payer, payer.publicKey, 9); - for (let i = 0; i < 5; i++) { - await mintTo(rpc, payer, mint, payer.publicKey, payer, bn(100)); - } - - // Merge multiple accounts into one - const tx = await mergeTokenAccounts(rpc, payer, mint, payer); - - console.log("Tx:", tx); -})(); diff --git a/toolkits/README.md b/toolkits/README.md new file mode 100644 index 00000000..841d36bc --- /dev/null +++ b/toolkits/README.md @@ -0,0 +1,21 @@ +# Light Token SDK - Toolkits + +Integration examples for wallets, payments, and streaming. + +### Payments and Wallets + +The Light-token API matches the SPL-token API almost entirely, and extends their functionality to include the light token program in addition to the SPL-token and Token-2022 programs. +Your users hold and receive tokens of the same mints, just stored more efficiently. Get an overview [in the README](payments-and-wallets/README.md). +- **[get-balance](payments-and-wallets/get-balance.ts)** - Fetch token balances +- **[get-history](payments-and-wallets/get-history.ts)** - Fetch transaction history +- **[send-and-receive](payments-and-wallets/send-and-receive.ts)** - Send and receive light-tokens +- **[wrap](payments-and-wallets/wrap.ts)** - Wrap SPL/T22 to light-token +- **[unwrap](payments-and-wallets/unwrap.ts)** - Unwrap light-token to SPL/T22 + +### Streaming Tokens + +[Rust program example to stream mint events](streaming-tokens/) of the Light-Token Program. + +## Documentation + +Learn more [about Light-Token here](https://www.zkcompression.com/light-token/welcome). diff --git a/toolkits/payments-and-wallets/README.md b/toolkits/payments-and-wallets/README.md index 028d2c50..db6cc1b7 100644 --- a/toolkits/payments-and-wallets/README.md +++ b/toolkits/payments-and-wallets/README.md @@ -18,13 +18,26 @@ | `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` | +| `wrap.ts` | SPL → light-token | `wrap` | +| `unwrap.ts` | light-token → SPL | `unwrap` | ## Get Started +## Setup + +```bash +npm install @lightprotocol/stateless.js@alpha \ + @lightprotocol/compressed-token@alpha +``` + +For Localnet: +```bash +npm i -g @lightprotocol/zk-compression-cli@alpha +``` + +For Devnet: ```bash -npm install -g @lightprotocol/zk-compression-cli@alpha +cp ../../.env.example .env # ...and set API_KEY ``` ```bash @@ -40,3 +53,8 @@ pnpm run get-history pnpm run wrap pnpm run unwrap ``` + +## Documentation + +Learn more [about to Light-Token here](https://www.zkcompression.com/light-token/welcome). + diff --git a/typescript-client/README.md b/typescript-client/README.md new file mode 100644 index 00000000..0d825c72 --- /dev/null +++ b/typescript-client/README.md @@ -0,0 +1,59 @@ +# Light Token SDK - TypeScript Client + +### Actions + +- **[create-mint](actions/create-mint.ts)** - Create a light-token mint with metadata +- **[create-ata](actions/create-ata.ts)** - Create an associated light-token account +- **[load-ata](actions/load-ata.ts)** - Load cold token account to hot balance +- **[mint-to](actions/mint-to.ts)** - Mint tokens to a light-account +- **[transfer-interface](actions/transfer-interface.ts)** - Transfer between light-token, T22, and SPL accounts +- **[delegate-approve](actions/delegate-approve.ts)** - Approve delegate +- **[delegate-revoke](actions/delegate-revoke.ts)** - Revoke delegate +- **[wrap](actions/wrap.ts)** - Wrap SPL/T22 to light-token +- **[unwrap](actions/unwrap.ts)** - Unwrap light-token to SPL/T22 + +### Instructions + +- **[create-mint](instructions/create-mint.ts)** - Build create mint instruction +- **[create-ata](instructions/create-ata.ts)** - Build create ATA instruction +- **[load-ata](instructions/load-ata.ts)** - Build load ATA instruction +- **[mint-to](instructions/mint-to.ts)** - Build mint-to instruction +- **[transfer-interface](instructions/transfer-interface.ts)** - Build transfer instruction +- **[wrap](instructions/wrap.ts)** - Wrap SPL/T22 to light-token +- **[unwrap](instructions/unwrap.ts)** - Unwrap light-token to SPL/T22 + +## Setup + +```bash +npm install @lightprotocol/stateless.js@alpha \ + @lightprotocol/compressed-token@alpha +``` + +For Localnet: +```bash +npm i -g @lightprotocol/zk-compression-cli@alpha +``` + +For Devnet: +```bash +cp ../.env.example .env # ...and set API_KEY +``` + +## Run + +```bash +npm run create-mint:action +npm run mint-to:action +npm run transfer-interface:action +# See package.json for all scripts +``` +```bash +npm run create-mint:instruction +npm run create-ata:instruction +npm run load-ata:instruction +# See package.json for all scripts +``` + +## Documentation + +Learn more [about to Light-Token here](https://www.zkcompression.com/light-token/welcome). \ No newline at end of file diff --git a/cookbook/actions/create-ata.ts b/typescript-client/actions/create-ata.ts similarity index 80% rename from cookbook/actions/create-ata.ts rename to typescript-client/actions/create-ata.ts index 66ddb0de..9d7c0f95 100644 --- a/cookbook/actions/create-ata.ts +++ b/typescript-client/actions/create-ata.ts @@ -9,9 +9,9 @@ import { homedir } from "os"; import { readFileSync } from "fs"; // devnet: -const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; // localnet: -// const RPC_URL = undefined; +const RPC_URL = undefined; const payer = Keypair.fromSecretKey( new Uint8Array( JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) @@ -20,9 +20,9 @@ const payer = Keypair.fromSecretKey( (async function () { // devnet: - const rpc = createRpc(RPC_URL); + // const rpc = createRpc(RPC_URL); // localnet: - // const rpc = createRpc(); + const rpc = createRpc(); const { mint } = await createMintInterface(rpc, payer, payer, null, 9); diff --git a/cookbook/actions/create-mint.ts b/typescript-client/actions/create-mint.ts similarity index 83% rename from cookbook/actions/create-mint.ts rename to typescript-client/actions/create-mint.ts index 957e8090..c5eb146d 100644 --- a/cookbook/actions/create-mint.ts +++ b/typescript-client/actions/create-mint.ts @@ -6,9 +6,9 @@ import { homedir } from "os"; import { readFileSync } from "fs"; // devnet: -const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; // localnet: -// const RPC_URL = undefined; +const RPC_URL = undefined; const payer = Keypair.fromSecretKey( new Uint8Array( JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) @@ -17,9 +17,9 @@ const payer = Keypair.fromSecretKey( (async function () { // devnet: - const rpc = createRpc(RPC_URL); + // const rpc = createRpc(RPC_URL); // localnet: - // const rpc = createRpc(); + const rpc = createRpc(); const { mint, transactionSignature } = await createMintInterface( rpc, diff --git a/cookbook/actions/delegate-approve.ts b/typescript-client/actions/delegate-approve.ts similarity index 83% rename from cookbook/actions/delegate-approve.ts rename to typescript-client/actions/delegate-approve.ts index 408d599c..c786e00b 100644 --- a/cookbook/actions/delegate-approve.ts +++ b/typescript-client/actions/delegate-approve.ts @@ -6,9 +6,9 @@ import { homedir } from "os"; import { readFileSync } from "fs"; // devnet: -const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; // localnet: -// const RPC_URL = undefined; +const RPC_URL = undefined; const payer = Keypair.fromSecretKey( new Uint8Array( JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) @@ -17,9 +17,9 @@ const payer = Keypair.fromSecretKey( (async function () { // devnet: - const rpc = createRpc(RPC_URL); + // const rpc = createRpc(RPC_URL); // localnet: - // const rpc = createRpc(); + const rpc = createRpc(); // Setup: Get compressed tokens const { mint } = await createMint(rpc, payer, payer.publicKey, 9); diff --git a/cookbook/actions/delegate-revoke.ts b/typescript-client/actions/delegate-revoke.ts similarity index 85% rename from cookbook/actions/delegate-revoke.ts rename to typescript-client/actions/delegate-revoke.ts index 908bbd4f..a689e906 100644 --- a/cookbook/actions/delegate-revoke.ts +++ b/typescript-client/actions/delegate-revoke.ts @@ -11,9 +11,9 @@ import { homedir } from "os"; import { readFileSync } from "fs"; // devnet: -const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; // localnet: -// const RPC_URL = undefined; +const RPC_URL = undefined; const payer = Keypair.fromSecretKey( new Uint8Array( JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) @@ -22,9 +22,9 @@ const payer = Keypair.fromSecretKey( (async function () { // devnet: - const rpc = createRpc(RPC_URL); + // const rpc = createRpc(RPC_URL); // localnet: - // const rpc = createRpc(); + const rpc = createRpc(); // Setup: Get compressed tokens const { mint } = await createMint(rpc, payer, payer.publicKey, 9); diff --git a/cookbook/actions/load-ata.ts b/typescript-client/actions/load-ata.ts similarity index 84% rename from cookbook/actions/load-ata.ts rename to typescript-client/actions/load-ata.ts index 79f957e1..39bf7490 100644 --- a/cookbook/actions/load-ata.ts +++ b/typescript-client/actions/load-ata.ts @@ -11,9 +11,9 @@ import { homedir } from "os"; import { readFileSync } from "fs"; // devnet: -const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; // localnet: -// const RPC_URL = undefined; +const RPC_URL = undefined; const payer = Keypair.fromSecretKey( new Uint8Array( JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) @@ -22,9 +22,9 @@ const payer = Keypair.fromSecretKey( (async function () { // devnet: - const rpc = createRpc(RPC_URL); + // const rpc = createRpc(RPC_URL); // localnet: - // const rpc = createRpc(); + const rpc = createRpc(); // Setup: Get compressed tokens (cold storage) const { mint } = await createMint(rpc, payer, payer.publicKey, 9); diff --git a/cookbook/actions/mint-to.ts b/typescript-client/actions/mint-to.ts similarity index 84% rename from cookbook/actions/mint-to.ts rename to typescript-client/actions/mint-to.ts index 5fb77ff7..ba0fd291 100644 --- a/cookbook/actions/mint-to.ts +++ b/typescript-client/actions/mint-to.ts @@ -11,9 +11,9 @@ import { homedir } from "os"; import { readFileSync } from "fs"; // devnet: -const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; // localnet: -// const RPC_URL = undefined; +const RPC_URL = undefined; const payer = Keypair.fromSecretKey( new Uint8Array( JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) @@ -22,9 +22,9 @@ const payer = Keypair.fromSecretKey( (async function () { // devnet: - const rpc = createRpc(RPC_URL); + // const rpc = createRpc(RPC_URL); // localnet: - // const rpc = createRpc(); + const rpc = createRpc(); const { mint } = await createMintInterface(rpc, payer, payer, null, 9); diff --git a/cookbook/actions/transfer-interface.ts b/typescript-client/actions/transfer-interface.ts similarity index 87% rename from cookbook/actions/transfer-interface.ts rename to typescript-client/actions/transfer-interface.ts index a9c2ccb6..517fa6ae 100644 --- a/cookbook/actions/transfer-interface.ts +++ b/typescript-client/actions/transfer-interface.ts @@ -12,9 +12,9 @@ import { homedir } from "os"; import { readFileSync } from "fs"; // devnet: -const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; // localnet: -// const RPC_URL = undefined; +const RPC_URL = undefined; const payer = Keypair.fromSecretKey( new Uint8Array( JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) @@ -23,9 +23,9 @@ const payer = Keypair.fromSecretKey( (async function () { // devnet: - const rpc = createRpc(RPC_URL); + // const rpc = createRpc(RPC_URL); // localnet: - // const rpc = createRpc(); + const rpc = createRpc(); const { mint } = await createMintInterface(rpc, payer, payer, null, 9); diff --git a/cookbook/actions/unwrap.ts b/typescript-client/actions/unwrap.ts similarity index 85% rename from cookbook/actions/unwrap.ts rename to typescript-client/actions/unwrap.ts index ffacb9f9..364cdf21 100644 --- a/cookbook/actions/unwrap.ts +++ b/typescript-client/actions/unwrap.ts @@ -8,9 +8,9 @@ import { homedir } from "os"; import { readFileSync } from "fs"; // devnet: -const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; // localnet: -// const RPC_URL = undefined; +const RPC_URL = undefined; const payer = Keypair.fromSecretKey( new Uint8Array( JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) @@ -19,9 +19,9 @@ const payer = Keypair.fromSecretKey( (async function () { // devnet: - const rpc = createRpc(RPC_URL); + // const rpc = createRpc(RPC_URL); // localnet: - // const rpc = createRpc(); + const rpc = createRpc(); // Setup: Get compressed tokens (cold storage) const { mint } = await createMint(rpc, payer, payer.publicKey, 9); diff --git a/cookbook/actions/wrap.ts b/typescript-client/actions/wrap.ts similarity index 88% rename from cookbook/actions/wrap.ts rename to typescript-client/actions/wrap.ts index 72d46086..cfb9d89c 100644 --- a/cookbook/actions/wrap.ts +++ b/typescript-client/actions/wrap.ts @@ -14,9 +14,9 @@ import { homedir } from "os"; import { readFileSync } from "fs"; // devnet: -const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; // localnet: -// const RPC_URL = undefined; +const RPC_URL = undefined; const payer = Keypair.fromSecretKey( new Uint8Array( JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8")) @@ -25,9 +25,9 @@ const payer = Keypair.fromSecretKey( (async function () { // devnet: - const rpc = createRpc(RPC_URL); + // const rpc = createRpc(RPC_URL); // localnet: - // const rpc = createRpc(); + const rpc = createRpc(); // Setup: Get SPL tokens (needed to wrap) const { mint } = await createMint(rpc, payer, payer.publicKey, 9); diff --git a/cookbook/instructions/create-ata.ts b/typescript-client/instructions/create-ata.ts similarity index 89% rename from cookbook/instructions/create-ata.ts rename to typescript-client/instructions/create-ata.ts index 9022a5fa..55966d8e 100644 --- a/cookbook/instructions/create-ata.ts +++ b/typescript-client/instructions/create-ata.ts @@ -14,10 +14,10 @@ import { homedir } from "os"; import { readFileSync } from "fs"; // devnet: -const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -const rpc = createRpc(RPC_URL); +// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +// const rpc = createRpc(RPC_URL); // localnet: -// const rpc = createRpc(); +const rpc = createRpc(); const payer = Keypair.fromSecretKey( new Uint8Array( diff --git a/cookbook/instructions/create-mint.ts b/typescript-client/instructions/create-mint.ts similarity index 93% rename from cookbook/instructions/create-mint.ts rename to typescript-client/instructions/create-mint.ts index ed4fa83f..f1250aff 100644 --- a/cookbook/instructions/create-mint.ts +++ b/typescript-client/instructions/create-mint.ts @@ -29,10 +29,10 @@ function findMintAddress(mintSigner: PublicKey): [PublicKey, number] { } // devnet: -const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -const rpc = createRpc(RPC_URL); +// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +// const rpc = createRpc(RPC_URL); // localnet: -// const rpc = createRpc(); +const rpc = createRpc(); const payer = Keypair.fromSecretKey( new Uint8Array( diff --git a/cookbook/instructions/load-ata.ts b/typescript-client/instructions/load-ata.ts similarity index 94% rename from cookbook/instructions/load-ata.ts rename to typescript-client/instructions/load-ata.ts index 3e585d3a..a94d5083 100644 --- a/cookbook/instructions/load-ata.ts +++ b/typescript-client/instructions/load-ata.ts @@ -16,7 +16,7 @@ import { homedir } from "os"; import { readFileSync } from "fs"; // devnet: -const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; const rpc = createRpc(RPC_URL); // localnet: // const rpc = createRpc(); diff --git a/cookbook/instructions/mint-to.ts b/typescript-client/instructions/mint-to.ts similarity index 93% rename from cookbook/instructions/mint-to.ts rename to typescript-client/instructions/mint-to.ts index 9c34a8d2..404b9647 100644 --- a/cookbook/instructions/mint-to.ts +++ b/typescript-client/instructions/mint-to.ts @@ -12,10 +12,10 @@ import { homedir } from "os"; import { readFileSync } from "fs"; // devnet: -const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -const rpc = createRpc(RPC_URL); +// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +// const rpc = createRpc(RPC_URL); // localnet: -// const rpc = createRpc(); +const rpc = createRpc(); const payer = Keypair.fromSecretKey( new Uint8Array( diff --git a/cookbook/instructions/transfer-interface.ts b/typescript-client/instructions/transfer-interface.ts similarity index 91% rename from cookbook/instructions/transfer-interface.ts rename to typescript-client/instructions/transfer-interface.ts index a0c2c2e8..c2dc0f09 100644 --- a/cookbook/instructions/transfer-interface.ts +++ b/typescript-client/instructions/transfer-interface.ts @@ -17,10 +17,10 @@ import { homedir } from "os"; import { readFileSync } from "fs"; // devnet: -const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; -const rpc = createRpc(RPC_URL); +// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +// const rpc = createRpc(RPC_URL); // localnet: -// const rpc = createRpc(); +const rpc = createRpc(); const payer = Keypair.fromSecretKey( new Uint8Array( diff --git a/cookbook/instructions/unwrap.ts b/typescript-client/instructions/unwrap.ts similarity index 96% rename from cookbook/instructions/unwrap.ts rename to typescript-client/instructions/unwrap.ts index 02f3fcad..209c4a88 100644 --- a/cookbook/instructions/unwrap.ts +++ b/typescript-client/instructions/unwrap.ts @@ -14,7 +14,7 @@ import { homedir } from "os"; import { readFileSync } from "fs"; // devnet: -const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; const rpc = createRpc(RPC_URL); // localnet: // const rpc = createRpc(); diff --git a/cookbook/instructions/wrap.ts b/typescript-client/instructions/wrap.ts similarity index 96% rename from cookbook/instructions/wrap.ts rename to typescript-client/instructions/wrap.ts index b577e4bf..3490574a 100644 --- a/cookbook/instructions/wrap.ts +++ b/typescript-client/instructions/wrap.ts @@ -15,7 +15,7 @@ import { homedir } from "os"; import { readFileSync } from "fs"; // devnet: -const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; +// const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`; const rpc = createRpc(RPC_URL); // localnet: // const rpc = createRpc(); diff --git a/cookbook/package.json b/typescript-client/package.json similarity index 66% rename from cookbook/package.json rename to typescript-client/package.json index 24952dcd..23d8e11a 100644 --- a/cookbook/package.json +++ b/typescript-client/package.json @@ -3,7 +3,20 @@ "version": "1.0.0", "type": "module", "description": "Working examples for light-token operations on Solana devnet", + "dependencies": { + "@lightprotocol/compressed-token": "alpha", + "@lightprotocol/stateless.js": "alpha", + "@solana/web3.js": "^1.98.0", + "dotenv": "^16.0.0" + }, + "devDependencies": { + "tsx": "^4.0.0" + }, "scripts": { + "test:localnet": "./switch-network.sh localnet && npm run test:all", + "test:all": "npm run test:actions && npm run test:instructions", + "test:actions": "tsx actions/create-mint.ts && tsx actions/create-ata.ts && tsx actions/mint-to.ts && tsx actions/transfer-interface.ts", + "test:instructions": "tsx instructions/create-mint.ts && tsx instructions/create-ata.ts && tsx instructions/mint-to.ts && tsx instructions/transfer-interface.ts", "create-mint:action": "tsx actions/create-mint.ts", "create-mint:instruction": "tsx instructions/create-mint.ts", "mint-to:action": "tsx actions/mint-to.ts", diff --git a/cookbook/tsconfig.json b/typescript-client/tsconfig.json similarity index 100% rename from cookbook/tsconfig.json rename to typescript-client/tsconfig.json