Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
API_KEY=YOUR_KEY
12 changes: 7 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
node_modules/
dist/
.env
pnpm-lock.yaml
package-lock.json
**/node_modules/
**/dist/
**/.env
**/pnpm-lock.yaml
**/package-lock.json
**/*.json.bak
**/test-ledger
3 changes: 3 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"tabWidth": 4
}
29 changes: 27 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,27 @@
# examples-light-token
Examples for Light-Token Program
# Light Token Examples

## Setup

```bash
cp .env.example .env # ...and set RPC_URL
npm install
```

## 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
```

Cookbook examples use local test-validator (install via `npm i -g @lightprotocol/zk-compression-cli@alpha`, then run `light test-validator`).
2 changes: 0 additions & 2 deletions cookbook/.env.example

This file was deleted.

109 changes: 56 additions & 53 deletions cookbook/actions/compress-batch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
106 changes: 53 additions & 53 deletions cookbook/actions/compress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
73 changes: 37 additions & 36 deletions cookbook/actions/create-ata.ts
Original file line number Diff line number Diff line change
@@ -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);
});
Loading