@@ -11,14 +11,14 @@ import {
11
11
calculateComputeUnitPrice ,
12
12
createRpc ,
13
13
dedupeSigner ,
14
- pickRandomTreeAndQueue ,
15
14
Rpc ,
16
15
selectStateTreeInfo ,
17
16
sendAndConfirmTx ,
18
17
} from "@lightprotocol/stateless.js" ;
19
18
import * as splToken from "@solana/spl-token" ;
20
19
import dotenv from "dotenv" ;
21
20
import bs58 from "bs58" ;
21
+ import { createIdempotentAirdropInstruction } from "./idempotent" ;
22
22
dotenv . config ( ) ;
23
23
24
24
const RPC_ENDPOINT = process . env . RPC_ENDPOINT ;
@@ -34,9 +34,10 @@ const PAYER_KEYPAIR = Keypair.fromSecretKey(
34
34
const payer = PAYER_KEYPAIR ;
35
35
36
36
const amount = bn ( 333 ) ; // each recipient will receive 111 tokens
37
- const recipients = [ "GMPWaPPrCeZPse5kwSR3WUrqYAPrVZBSVwymqh7auNW7" ] . map (
38
- ( address ) => new PublicKey ( address )
39
- ) ;
37
+ const recipients = [
38
+ "GMPWaPPrCeZPse5kwSR3WUrqYAPrVZBSVwymqh7auNW7" ,
39
+ "GMPWaPPrCeZPse5kwSR3WUrqYAPrVZBSVwymqh7auNW7" ,
40
+ ] . map ( ( address ) => new PublicKey ( address ) ) ;
40
41
const activeStateTrees = await connection . getStateTreeInfos ( ) ;
41
42
42
43
/// Pick a new tree for each transaction!
@@ -54,21 +55,20 @@ const PAYER_KEYPAIR = Keypair.fromSecretKey(
54
55
// Airdrop to example recipients addresses
55
56
// 1 recipient = 120_000 CU
56
57
// 5 recipients = 170_000 CU
57
-
58
+ // with idempotent cPDA = +250_000 CU
58
59
const instructions : web3 . TransactionInstruction [ ] = [ ] ;
59
-
60
60
instructions . push (
61
- web3 . ComputeBudgetProgram . setComputeUnitLimit ( { units : 120_000 } ) ,
61
+ web3 . ComputeBudgetProgram . setComputeUnitLimit ( { units : 370_000 } ) ,
62
62
web3 . ComputeBudgetProgram . setComputeUnitPrice ( {
63
- // ideally replace this with a dynamic priority_fee based on network conditions .
64
- microLamports : calculateComputeUnitPrice ( 20_000 , 120_000 ) ,
63
+ // Replace this with a dynamic priority_fee to land during high network load .
64
+ microLamports : calculateComputeUnitPrice ( 20_000 , 370_000 ) ,
65
65
} )
66
66
) ;
67
67
68
68
const compressInstruction = await CompressedTokenProgram . compress ( {
69
69
payer : payer . publicKey ,
70
70
owner : payer . publicKey ,
71
- source : sourceTokenAccount . address , // here, the owner of this account is also the payer.
71
+ source : sourceTokenAccount . address ,
72
72
toAddress : recipients ,
73
73
amount : recipients . map ( ( ) => amount ) ,
74
74
mint : mintAddress ,
@@ -79,13 +79,23 @@ const PAYER_KEYPAIR = Keypair.fromSecretKey(
79
79
} ) ;
80
80
instructions . push ( compressInstruction ) ;
81
81
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
+
82
94
// Use zk-compression LUT for your network
83
95
// https://www.zkcompression.com/developers/protocol-addresses-and-urls#lookup-tables
84
96
const lookupTableAddress = new web3 . PublicKey (
85
97
"9NYFyEqPkyXUhkerbGHXUXkvb4qpzeEdHuGpgbgpH1NJ" // mainnet
86
- // "qAJZMgnQJ8G6vA3WRcjD9Jan1wtKkaCFWLWskxJrR5V" // devnet
87
98
) ;
88
-
89
99
// Get the lookup table account state
90
100
const lookupTableAccount = (
91
101
await connection . getAddressLookupTable ( lookupTableAddress )
@@ -105,7 +115,6 @@ const PAYER_KEYPAIR = Keypair.fromSecretKey(
105
115
[ lookupTableAccount ]
106
116
) ;
107
117
108
- // Uncomment to send the transaction.
109
118
const txId = await sendAndConfirmTx ( connection , tx ) ;
110
119
console . log ( `txId: ${ txId } ` ) ;
111
120
} catch ( e ) {
0 commit comments