Skip to content

Commit 8363c96

Browse files
chore: bump to 0.20.9, feat: compress, transfer (#16)
* pick pseudorandom batch transfer for mainnet 0.19.0 add airdrop.ts add multi-trees, add transfer, compress * clean transfer.ts
1 parent 1ea7ea5 commit 8363c96

File tree

7 files changed

+283
-12
lines changed

7 files changed

+283
-12
lines changed

package-lock.json

Lines changed: 64 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
"create-account-pulse": "ts-node src/internal/create-account-pulse.ts",
2020
"create-account-with-lamports-pulse": "ts-node src/internal/create-account-with-lamports-pulse.ts",
2121
"airdrop": "ts-node src/scripts/airdrop/airdrop.ts",
22+
"transfer": "ts-node src/scripts/transfer.ts",
23+
"compress": "ts-node src/scripts/compress.ts",
2224
"test": "npm run lamports && npm run token && npm run connection && npm run batch-compress && npm run mint-spl && npm run mint-spl-22 && npm run mint-spl-22-manual"
2325
},
2426
"repository": {
@@ -33,8 +35,8 @@
3335
},
3436
"homepage": "https://github.com/Lightprotocol/example-nodejs-client#readme",
3537
"dependencies": {
36-
"@lightprotocol/compressed-token": "0.20.3",
37-
"@lightprotocol/stateless.js": "0.20.3",
38+
"@lightprotocol/compressed-token": "0.20.9",
39+
"@lightprotocol/stateless.js": "0.20.9",
3840
"@solana/spl-token": "0.3.9",
3941
"@solana/spl-token-metadata": "^0.1.6",
4042
"@solana/web3.js": "^1.98.0",

src/constants.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,28 @@ export const LUT_DEVNET_AUTHORITY_KEYPAIR = process.env.LUT_DEVNET_AUTH_KEYPAIR
2525
: undefined;
2626

2727
export const MINT_ADDRESS = new PublicKey(process.env.MINT_ADDRESS!);
28+
29+
export const AUTHORITY_KEYPAIR = process.env.LUT_AUTHORITY_KEYPAIR
30+
? Keypair.fromSecretKey(
31+
Uint8Array.from(JSON.parse(process.env.LUT_AUTHORITY_KEYPAIR))
32+
)
33+
: undefined;
34+
35+
export const BOB_KEYPAIR = process.env.BOB_KEYPAIR
36+
? Keypair.fromSecretKey(Uint8Array.from(JSON.parse(process.env.BOB_KEYPAIR)))
37+
: undefined;
38+
39+
export const LUT_MAINNET_AUTHORITY_KEYPAIR = process.env.LUT_AUTHORITY_KEYPAIR
40+
? Keypair.fromSecretKey(
41+
Uint8Array.from(JSON.parse(process.env.LUT_AUTHORITY_KEYPAIR))
42+
)
43+
: undefined;
44+
45+
export const LUT_DEVNET_AUTHORITY_KEYPAIR = process.env.LUT_DEVNET_AUTH_KEYPAIR
46+
? Keypair.fromSecretKey(bs58.decode(process.env.LUT_DEVNET_AUTH_KEYPAIR))
47+
: undefined;
48+
49+
2850
if (!RPC_ENDPOINT) throw new Error("Please set RPC_ENDPOINT in .env");
2951
if (!PAYER_KEYPAIR)
3052
throw new Error("Please set PAYER_KEYPAIR as bs58 string in .env");

src/scripts/batch-compress.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
dedupeSigner,
1010
pickRandomTreeAndQueue,
1111
Rpc,
12+
sendAndConfirmTx,
1213
} from "@lightprotocol/stateless.js";
1314
import * as splToken from "@solana/spl-token";
1415

@@ -131,6 +132,9 @@ import * as splToken from "@solana/spl-token";
131132
} else {
132133
console.log("Simulation successful", simulate);
133134
}
135+
// Uncomment to send the transaction:
136+
// const txId = await sendAndConfirmTx(connection, tx);
137+
// console.log(`txId: ${txId}`);
134138
} catch (e) {
135139
console.error(`Batch compression failed:`, e);
136140
}

src/scripts/compress.ts

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import * as web3 from "@solana/web3.js";
2+
import { Keypair, PublicKey } from "@solana/web3.js";
3+
import { CompressedTokenProgram } from "@lightprotocol/compressed-token";
4+
import {
5+
bn,
6+
buildAndSignTx,
7+
calculateComputeUnitPrice,
8+
createRpc,
9+
dedupeSigner,
10+
pickRandomTreeAndQueue,
11+
Rpc,
12+
sendAndConfirmTx,
13+
} from "@lightprotocol/stateless.js";
14+
import * as splToken from "@solana/spl-token";
15+
import dotenv from "dotenv";
16+
import bs58 from "bs58";
17+
dotenv.config();
18+
19+
const RPC_ENDPOINT = process.env.RPC_ENDPOINT;
20+
const MINT_ADDRESS = new PublicKey(process.env.MINT_ADDRESS!);
21+
const PAYER_KEYPAIR = Keypair.fromSecretKey(
22+
bs58.decode(process.env.PAYER_KEYPAIR!)
23+
);
24+
25+
(async () => {
26+
try {
27+
const connection: Rpc = createRpc(RPC_ENDPOINT);
28+
const mintAddress = MINT_ADDRESS;
29+
const payer = PAYER_KEYPAIR;
30+
31+
const activeStateTrees = await connection.getCachedActiveStateTreeInfo();
32+
33+
/// Pick a new tree for each transaction!
34+
const { tree } = pickRandomTreeAndQueue(activeStateTrees);
35+
36+
// Create an SPL token account for the sender.
37+
// The sender will send tokens from this account to the recipients as compressed tokens.
38+
const sourceTokenAccount = await splToken.getOrCreateAssociatedTokenAccount(
39+
connection,
40+
payer,
41+
mintAddress,
42+
payer.publicKey
43+
);
44+
45+
// Airdrop to example recipients addresses
46+
// 1 recipient = 120_000 CU
47+
// 5 recipients = 170_000 CU
48+
const airDropAddresses = [
49+
"GMPWaPPrCeZPse5kwSR3WUrqYAPrVZBSVwymqh7auNW7",
50+
].map((address) => new web3.PublicKey(address));
51+
52+
const amount = bn(111); // each recipient will receive 111 tokens
53+
const instructions: web3.TransactionInstruction[] = [];
54+
55+
instructions.push(
56+
web3.ComputeBudgetProgram.setComputeUnitLimit({ units: 120_000 }),
57+
web3.ComputeBudgetProgram.setComputeUnitPrice({
58+
// ideally replace this with a dynamic priority_fee based on network conditions.
59+
microLamports: calculateComputeUnitPrice(20_000, 120_000),
60+
})
61+
);
62+
63+
const compressInstruction = await CompressedTokenProgram.compress({
64+
payer: payer.publicKey,
65+
owner: payer.publicKey,
66+
source: sourceTokenAccount.address, // here, the owner of this account is also the payer.
67+
toAddress: airDropAddresses,
68+
amount: airDropAddresses.map(() => amount),
69+
mint: mintAddress,
70+
outputStateTree: tree,
71+
});
72+
instructions.push(compressInstruction);
73+
74+
// Use zk-compression LUT for your network
75+
// https://www.zkcompression.com/developers/protocol-addresses-and-urls#lookup-tables
76+
const lookupTableAddress = new web3.PublicKey(
77+
// "9NYFyEqPkyXUhkerbGHXUXkvb4qpzeEdHuGpgbgpH1NJ" // mainnet
78+
"qAJZMgnQJ8G6vA3WRcjD9Jan1wtKkaCFWLWskxJrR5V" // devnet
79+
);
80+
81+
// Get the lookup table account state
82+
const lookupTableAccount = (
83+
await connection.getAddressLookupTable(lookupTableAddress)
84+
).value!;
85+
86+
// Sign the transaction with the payer and owner keypair
87+
const owner = payer;
88+
const additionalSigners = dedupeSigner(payer, [owner]);
89+
90+
const { blockhash } = await connection.getLatestBlockhash();
91+
92+
const tx = buildAndSignTx(
93+
instructions,
94+
payer,
95+
blockhash,
96+
additionalSigners,
97+
[lookupTableAccount]
98+
);
99+
100+
const simulate = await connection.simulateTransaction(tx);
101+
if (simulate.value.err) {
102+
console.error("Simulation failed", simulate);
103+
} else {
104+
console.log("Simulation successful", simulate);
105+
}
106+
// Uncomment to send the transaction.
107+
// const txId = await sendAndConfirmTx(connection, tx);
108+
// console.log(`txId: ${txId}`);
109+
} catch (e) {
110+
console.error(`Compression failed:`, e);
111+
}
112+
})();

src/scripts/mint-spl.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,13 @@ const connection: Rpc = createRpc(RPC_ENDPOINT, RPC_ENDPOINT);
3737

3838
console.log(`ATA: ${ata.address}`);
3939

40-
await mintToSpl(
40+
const mintTxId = await mintToSpl(
4141
connection,
4242
payer,
4343
mint,
4444
ata.address,
4545
payer.publicKey,
4646
BigInt("240000050")
4747
);
48+
console.log(`mint-spl success! txId: ${mintTxId}`);
4849
})();

0 commit comments

Comments
 (0)