Skip to content

Commit 3a8401d

Browse files
chore: add idempotent example (#23)
bump add idempotent example update env example * add idempotent * connection
1 parent ec990ae commit 3a8401d

3 files changed

Lines changed: 124 additions & 31 deletions

File tree

src/scripts/compress-idempotent.ts

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import * as web3 from "@solana/web3.js";
2+
import { Keypair, PublicKey } from "@solana/web3.js";
3+
import {
4+
CompressedTokenProgram,
5+
getTokenPoolInfos,
6+
selectTokenPoolInfo,
7+
} from "@lightprotocol/compressed-token";
8+
import {
9+
bn,
10+
buildAndSignTx,
11+
calculateComputeUnitPrice,
12+
createRpc,
13+
dedupeSigner,
14+
Rpc,
15+
selectStateTreeInfo,
16+
sendAndConfirmTx,
17+
} from "@lightprotocol/stateless.js";
18+
import * as splToken from "@solana/spl-token";
19+
import dotenv from "dotenv";
20+
import bs58 from "bs58";
21+
import { createIdempotentAirdropInstruction } from "./idempotent";
22+
dotenv.config();
23+
24+
const RPC_ENDPOINT = process.env.RPC_ENDPOINT;
25+
const MINT_ADDRESS = new PublicKey(process.env.MINT_ADDRESS!);
26+
const PAYER_KEYPAIR = Keypair.fromSecretKey(
27+
bs58.decode(process.env.PAYER_KEYPAIR!)
28+
);
29+
30+
(async () => {
31+
try {
32+
const connection: Rpc = createRpc(RPC_ENDPOINT);
33+
const mintAddress = MINT_ADDRESS;
34+
const payer = PAYER_KEYPAIR;
35+
36+
const amount = bn(111); // each recipient will receive 111 tokens
37+
const recipients = [PAYER_KEYPAIR.publicKey].map(
38+
(address) => new PublicKey(address)
39+
);
40+
const activeStateTrees = await connection.getStateTreeInfos();
41+
42+
/// Pick a new tree for each transaction!
43+
const treeInfo = selectStateTreeInfo(activeStateTrees);
44+
45+
// Create an SPL token account for the sender.
46+
// The sender will send tokens from this account to the recipients as compressed tokens.
47+
const sourceTokenAccount = await splToken.getOrCreateAssociatedTokenAccount(
48+
connection,
49+
payer,
50+
mintAddress,
51+
payer.publicKey
52+
);
53+
54+
// Airdrop to example recipients addresses
55+
// 1 recipient = 120_000 CU
56+
// 5 recipients = 170_000 CU
57+
// with idempotent cPDA = +250_000 CU
58+
const instructions: web3.TransactionInstruction[] = [];
59+
instructions.push(
60+
web3.ComputeBudgetProgram.setComputeUnitLimit({ units: 370_000 }),
61+
web3.ComputeBudgetProgram.setComputeUnitPrice({
62+
// Replace this with a dynamic priority_fee to land during high network load.
63+
microLamports: calculateComputeUnitPrice(20_000, 370_000),
64+
})
65+
);
66+
67+
const compressInstruction = await CompressedTokenProgram.compress({
68+
payer: payer.publicKey,
69+
owner: payer.publicKey,
70+
source: sourceTokenAccount.address,
71+
toAddress: recipients,
72+
amount: recipients.map(() => amount),
73+
mint: mintAddress,
74+
outputStateTreeInfo: treeInfo,
75+
tokenPoolInfo: selectTokenPoolInfo(
76+
await getTokenPoolInfos(connection, mintAddress)
77+
),
78+
});
79+
instructions.push(compressInstruction);
80+
81+
// Creates a cPDA for a given set of recipients. This lets you retry txns without handling spends client-side.
82+
// The whole txn will fail if the same set of seeds (with the same order) is used a second time.
83+
instructions.push(
84+
await createIdempotentAirdropInstruction(
85+
connection,
86+
payer.publicKey,
87+
mintAddress,
88+
recipients,
89+
treeInfo
90+
)
91+
);
92+
93+
// Sign the transaction with the payer and owner keypair
94+
const owner = payer;
95+
const additionalSigners = dedupeSigner(payer, [owner]);
96+
97+
const { blockhash } = await connection.getLatestBlockhash();
98+
99+
const tx = buildAndSignTx(
100+
instructions,
101+
payer,
102+
blockhash,
103+
additionalSigners
104+
);
105+
106+
const txId = await sendAndConfirmTx(connection, tx);
107+
console.log(`txId: ${txId}`);
108+
} catch (e) {
109+
console.error(`Compression failed:`, e);
110+
}
111+
})();

src/scripts/compress.ts

Lines changed: 5 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import {
1818
import * as splToken from "@solana/spl-token";
1919
import dotenv from "dotenv";
2020
import bs58 from "bs58";
21-
import { createIdempotentAirdropInstruction } from "./idempotent";
2221
dotenv.config();
2322

2423
const RPC_ENDPOINT = process.env.RPC_ENDPOINT;
@@ -33,11 +32,10 @@ const PAYER_KEYPAIR = Keypair.fromSecretKey(
3332
const mintAddress = MINT_ADDRESS;
3433
const payer = PAYER_KEYPAIR;
3534

36-
const amount = bn(333); // each recipient will receive 111 tokens
37-
const recipients = [
38-
"GMPWaPPrCeZPse5kwSR3WUrqYAPrVZBSVwymqh7auNW7",
39-
"GMPWaPPrCeZPse5kwSR3WUrqYAPrVZBSVwymqh7auNW7",
40-
].map((address) => new PublicKey(address));
35+
const amount = bn(111); // each recipient will receive 111 tokens
36+
const recipients = [PAYER_KEYPAIR.publicKey].map(
37+
(address) => new PublicKey(address)
38+
);
4139
const activeStateTrees = await connection.getStateTreeInfos();
4240

4341
/// Pick a new tree for each transaction!
@@ -79,28 +77,6 @@ const PAYER_KEYPAIR = Keypair.fromSecretKey(
7977
});
8078
instructions.push(compressInstruction);
8179

82-
// Creates a cPDA for a given set of recipients. This lets you retry txns without handling spends client-side.
83-
// The whole txn will fail if the same set of seeds (with the same order) is used a second time.
84-
instructions.push(
85-
await createIdempotentAirdropInstruction(
86-
connection,
87-
payer.publicKey,
88-
mintAddress,
89-
recipients,
90-
treeInfo
91-
)
92-
);
93-
94-
// Use zk-compression LUT for your network
95-
// https://www.zkcompression.com/developers/protocol-addresses-and-urls#lookup-tables
96-
const lookupTableAddress = new web3.PublicKey(
97-
"9NYFyEqPkyXUhkerbGHXUXkvb4qpzeEdHuGpgbgpH1NJ" // mainnet
98-
);
99-
// Get the lookup table account state
100-
const lookupTableAccount = (
101-
await connection.getAddressLookupTable(lookupTableAddress)
102-
).value!;
103-
10480
// Sign the transaction with the payer and owner keypair
10581
const owner = payer;
10682
const additionalSigners = dedupeSigner(payer, [owner]);
@@ -111,8 +87,7 @@ const PAYER_KEYPAIR = Keypair.fromSecretKey(
11187
instructions,
11288
payer,
11389
blockhash,
114-
additionalSigners,
115-
[lookupTableAccount]
90+
additionalSigners
11691
);
11792

11893
const txId = await sendAndConfirmTx(connection, tx);

src/scripts/connection.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Rpc } from "@lightprotocol/stateless.js";
2-
import { RPC_ENDPOINT } from "../constants";
2+
import { RPC_ENDPOINT, PAYER_KEYPAIR } from "../constants";
3+
34
const stateless = require("@lightprotocol/stateless.js");
45

56
const connection: Rpc = stateless.createRpc(RPC_ENDPOINT, RPC_ENDPOINT);
@@ -10,4 +11,10 @@ const connection: Rpc = stateless.createRpc(RPC_ENDPOINT, RPC_ENDPOINT);
1011

1112
const health = await connection.getIndexerHealth();
1213
console.log("Indexer Health:", health);
14+
15+
console.log("connection", connection.rpcEndpoint);
16+
const accs = await connection.getCompressedTokenAccountsByOwner(
17+
PAYER_KEYPAIR.publicKey
18+
);
19+
console.log("compressed token accounts: ", accs);
1320
})();

0 commit comments

Comments
 (0)