@lightprotocol/compressed-token 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,9 @@
1
1
  import { getIndexOrAdd, bn, padOutputStateMerkleTrees, useWallet, confirmConfig, defaultStaticAccountsStruct, toArray, LightSystemProgram, sumUpLamports, validateSufficientBalance, validateSameOwner, dedupeSigner, buildAndSignTx, sendAndConfirmTx, defaultTestStateTreeAccounts } from '@lightprotocol/stateless.js';
2
2
  import { utils, AnchorProvider, setProvider, Program } from '@coral-xyz/anchor';
3
- import { PublicKey, TransactionInstruction, Keypair, Connection, SystemProgram, ComputeBudgetProgram } from '@solana/web3.js';
3
+ import { PublicKey, TransactionInstruction, SystemProgram, Transaction, sendAndConfirmTransaction, Keypair, Connection, ComputeBudgetProgram } from '@solana/web3.js';
4
4
 
5
5
  const IDL = {
6
- version: '0.3.0',
6
+ version: '0.3.1',
7
7
  name: 'light_compressed_token',
8
8
  constants: [
9
9
  {
@@ -16,9 +16,10 @@ const IDL = {
16
16
  {
17
17
  name: 'createMint',
18
18
  docs: [
19
- 'This instruction expects a mint account to be created in a separate token program instruction',
20
- 'with token authority as mint authority.',
21
- 'This instruction creates a token pool account for that mint owned by token authority.',
19
+ 'This instruction expects a mint account to be created in a separate',
20
+ 'token program instruction with token authority as mint authority. This',
21
+ 'instruction creates a token pool account for that mint owned by token',
22
+ 'authority.',
22
23
  ],
23
24
  accounts: [
24
25
  {
@@ -98,7 +99,7 @@ const IDL = {
98
99
  isSigner: false,
99
100
  },
100
101
  {
101
- name: 'compressedPdaProgram',
102
+ name: 'lightSystemProgram',
102
103
  isMut: false,
103
104
  isSigner: false,
104
105
  },
@@ -132,6 +133,11 @@ const IDL = {
132
133
  isMut: false,
133
134
  isSigner: false,
134
135
  },
136
+ {
137
+ name: 'systemProgram',
138
+ isMut: false,
139
+ isSigner: false,
140
+ },
135
141
  ],
136
142
  args: [
137
143
  {
@@ -146,6 +152,10 @@ const IDL = {
146
152
  vec: 'u64',
147
153
  },
148
154
  },
155
+ {
156
+ name: 'bump',
157
+ type: 'u8',
158
+ },
149
159
  ],
150
160
  },
151
161
  {
@@ -153,7 +163,7 @@ const IDL = {
153
163
  accounts: [
154
164
  {
155
165
  name: 'feePayer',
156
- isMut: false,
166
+ isMut: true,
157
167
  isSigner: true,
158
168
  },
159
169
  {
@@ -167,7 +177,7 @@ const IDL = {
167
177
  isSigner: false,
168
178
  },
169
179
  {
170
- name: 'compressedPdaProgram',
180
+ name: 'lightSystemProgram',
171
181
  isMut: false,
172
182
  isSigner: false,
173
183
  },
@@ -214,139 +224,161 @@ const IDL = {
214
224
  isSigner: false,
215
225
  isOptional: true,
216
226
  },
227
+ {
228
+ name: 'systemProgram',
229
+ isMut: false,
230
+ isSigner: false,
231
+ },
217
232
  ],
218
233
  args: [
219
234
  {
220
235
  name: 'inputs',
221
236
  type: 'bytes',
222
237
  },
223
- {
224
- name: 'cpiContext',
225
- type: {
226
- option: {
227
- defined: 'CompressedCpiContext',
228
- },
229
- },
230
- },
231
238
  ],
232
239
  },
233
240
  ],
234
241
  types: [
235
242
  {
236
- name: 'CompressedAccountWithMerkleContext',
243
+ name: 'InstructionDataInvoke',
237
244
  type: {
238
245
  kind: 'struct',
239
246
  fields: [
240
247
  {
241
- name: 'compressedAccount',
248
+ name: 'proof',
242
249
  type: {
243
- defined: 'CompressedAccount',
250
+ option: {
251
+ defined: 'CompressedProof',
252
+ },
244
253
  },
245
254
  },
246
255
  {
247
- name: 'merkleTreePubkeyIndex',
248
- type: 'u8',
256
+ name: 'inputRootIndices',
257
+ type: {
258
+ vec: 'u16',
259
+ },
249
260
  },
250
261
  {
251
- name: 'nullifierQueuePubkeyIndex',
252
- type: 'u8',
262
+ name: 'inputCompressedAccountsWithMerkleContext',
263
+ type: {
264
+ vec: {
265
+ defined: 'PackedCompressedAccountWithMerkleContext',
266
+ },
267
+ },
253
268
  },
254
269
  {
255
- name: 'leafIndex',
256
- type: 'u32',
270
+ name: 'outputCompressedAccounts',
271
+ type: {
272
+ vec: {
273
+ defined: 'CompressedAccount',
274
+ },
275
+ },
257
276
  },
258
- ],
259
- },
260
- },
261
- {
262
- name: 'MerkleContext',
263
- type: {
264
- kind: 'struct',
265
- fields: [
266
277
  {
267
- name: 'merkleTreePubkey',
268
- type: 'publicKey',
278
+ name: 'outputStateMerkleTreeAccountIndices',
279
+ docs: [
280
+ 'The indices of the accounts in the output state merkle tree.',
281
+ ],
282
+ type: 'bytes',
269
283
  },
270
284
  {
271
- name: 'nullifierQueuePubkey',
272
- type: 'publicKey',
285
+ name: 'relayFee',
286
+ type: {
287
+ option: 'u64',
288
+ },
273
289
  },
274
290
  {
275
- name: 'leafIndex',
276
- type: 'u32',
291
+ name: 'newAddressParams',
292
+ type: {
293
+ vec: {
294
+ defined: 'NewAddressParamsPacked',
295
+ },
296
+ },
297
+ },
298
+ {
299
+ name: 'compressionLamports',
300
+ type: {
301
+ option: 'u64',
302
+ },
303
+ },
304
+ {
305
+ name: 'isCompress',
306
+ type: 'bool',
277
307
  },
278
308
  ],
279
309
  },
280
310
  },
281
311
  {
282
- name: 'PackedMerkleContext',
312
+ name: 'NewAddressParamsPacked',
283
313
  type: {
284
314
  kind: 'struct',
285
315
  fields: [
286
316
  {
287
- name: 'merkleTreePubkeyIndex',
317
+ name: 'seed',
318
+ type: {
319
+ array: ['u8', 32],
320
+ },
321
+ },
322
+ {
323
+ name: 'addressQueueAccountIndex',
288
324
  type: 'u8',
289
325
  },
290
326
  {
291
- name: 'nullifierQueuePubkeyIndex',
327
+ name: 'addressMerkleTreeAccountIndex',
292
328
  type: 'u8',
293
329
  },
294
330
  {
295
- name: 'leafIndex',
296
- type: 'u32',
331
+ name: 'addressMerkleTreeRootIndex',
332
+ type: 'u16',
297
333
  },
298
334
  ],
299
335
  },
300
336
  },
301
337
  {
302
- name: 'CompressedAccount',
338
+ name: 'NewAddressParams',
303
339
  type: {
304
340
  kind: 'struct',
305
341
  fields: [
306
342
  {
307
- name: 'owner',
308
- type: 'publicKey',
343
+ name: 'seed',
344
+ type: {
345
+ array: ['u8', 32],
346
+ },
309
347
  },
310
348
  {
311
- name: 'lamports',
312
- type: 'u64',
349
+ name: 'addressQueuePubkey',
350
+ type: 'publicKey',
313
351
  },
314
352
  {
315
- name: 'address',
316
- type: {
317
- option: {
318
- array: ['u8', 32],
319
- },
320
- },
353
+ name: 'addressMerkleTreePubkey',
354
+ type: 'publicKey',
321
355
  },
322
356
  {
323
- name: 'data',
324
- type: {
325
- option: {
326
- defined: 'CompressedAccountData',
327
- },
328
- },
357
+ name: 'addressMerkleTreeRootIndex',
358
+ type: 'u16',
329
359
  },
330
360
  ],
331
361
  },
332
362
  },
333
363
  {
334
- name: 'CompressedAccountData',
364
+ name: 'CompressedProof',
335
365
  type: {
336
366
  kind: 'struct',
337
367
  fields: [
338
368
  {
339
- name: 'discriminator',
369
+ name: 'a',
340
370
  type: {
341
- array: ['u8', 8],
371
+ array: ['u8', 32],
342
372
  },
343
373
  },
344
374
  {
345
- name: 'data',
346
- type: 'bytes',
375
+ name: 'b',
376
+ type: {
377
+ array: ['u8', 64],
378
+ },
347
379
  },
348
380
  {
349
- name: 'dataHash',
381
+ name: 'c',
350
382
  type: {
351
383
  array: ['u8', 32],
352
384
  },
@@ -355,57 +387,37 @@ const IDL = {
355
387
  },
356
388
  },
357
389
  {
358
- name: 'CompressedCpiContext',
359
- docs: ['To spend multiple compressed'],
390
+ name: 'InstructionDataInvokeCpi',
360
391
  type: {
361
392
  kind: 'struct',
362
393
  fields: [
363
394
  {
364
- name: 'cpiSignatureAccountIndex',
365
- docs: [
366
- 'index of the output state Merkle tree that will be used to store cpi signatures',
367
- 'The transaction will fail if this index is not consistent in your transaction.',
368
- ],
369
- type: 'u8',
370
- },
371
- {
372
- name: 'execute',
373
- docs: [
374
- 'The final cpi of your program needs to set execute to true.',
375
- 'Execute compressed transaction will verify the proof and execute the transaction if this is true.',
376
- 'If this is false the transaction will be stored in the cpi signature account.',
377
- ],
378
- type: 'bool',
395
+ name: 'proof',
396
+ type: {
397
+ option: {
398
+ defined: 'CompressedProof',
399
+ },
400
+ },
379
401
  },
380
- ],
381
- },
382
- },
383
- {
384
- name: 'PublicTransactionEvent',
385
- type: {
386
- kind: 'struct',
387
- fields: [
388
402
  {
389
- name: 'inputCompressedAccountHashes',
403
+ name: 'newAddressParams',
390
404
  type: {
391
405
  vec: {
392
- array: ['u8', 32],
406
+ defined: 'NewAddressParamsPacked',
393
407
  },
394
408
  },
395
409
  },
396
410
  {
397
- name: 'outputCompressedAccountHashes',
411
+ name: 'inputRootIndices',
398
412
  type: {
399
- vec: {
400
- array: ['u8', 32],
401
- },
413
+ vec: 'u16',
402
414
  },
403
415
  },
404
416
  {
405
- name: 'inputCompressedAccounts',
417
+ name: 'inputCompressedAccountsWithMerkleContext',
406
418
  type: {
407
419
  vec: {
408
- defined: 'CompressedAccountWithMerkleContext',
420
+ defined: 'PackedCompressedAccountWithMerkleContext',
409
421
  },
410
422
  },
411
423
  },
@@ -419,16 +431,19 @@ const IDL = {
419
431
  },
420
432
  {
421
433
  name: 'outputStateMerkleTreeAccountIndices',
434
+ docs: [
435
+ 'The indices of the accounts in the output state merkle tree.',
436
+ ],
422
437
  type: 'bytes',
423
438
  },
424
439
  {
425
- name: 'outputLeafIndices',
440
+ name: 'relayFee',
426
441
  type: {
427
- vec: 'u32',
442
+ option: 'u64',
428
443
  },
429
444
  },
430
445
  {
431
- name: 'relayFee',
446
+ name: 'compressionLamports',
432
447
  type: {
433
448
  option: 'u64',
434
449
  },
@@ -438,97 +453,128 @@ const IDL = {
438
453
  type: 'bool',
439
454
  },
440
455
  {
441
- name: 'compressionLamports',
442
- type: {
443
- option: 'u64',
444
- },
445
- },
446
- {
447
- name: 'pubkeyArray',
456
+ name: 'signerSeeds',
448
457
  type: {
449
- vec: 'publicKey',
458
+ vec: 'bytes',
450
459
  },
451
460
  },
452
461
  {
453
- name: 'message',
462
+ name: 'cpiContext',
454
463
  type: {
455
- option: 'bytes',
464
+ option: {
465
+ defined: 'CompressedCpiContext',
466
+ },
456
467
  },
457
468
  },
458
469
  ],
459
470
  },
460
471
  },
461
472
  {
462
- name: 'InstructionDataTransfer',
473
+ name: 'PackedCompressedAccountWithMerkleContext',
463
474
  type: {
464
475
  kind: 'struct',
465
476
  fields: [
466
477
  {
467
- name: 'proof',
478
+ name: 'compressedAccount',
468
479
  type: {
469
- option: {
470
- defined: 'CompressedProof',
471
- },
480
+ defined: 'CompressedAccount',
472
481
  },
473
482
  },
474
483
  {
475
- name: 'newAddressParams',
484
+ name: 'merkleContext',
476
485
  type: {
477
- vec: {
478
- defined: 'NewAddressParamsPacked',
479
- },
486
+ defined: 'PackedMerkleContext',
480
487
  },
481
488
  },
489
+ ],
490
+ },
491
+ },
492
+ {
493
+ name: 'CompressedAccountWithMerkleContext',
494
+ type: {
495
+ kind: 'struct',
496
+ fields: [
482
497
  {
483
- name: 'inputRootIndices',
498
+ name: 'compressedAccount',
484
499
  type: {
485
- vec: 'u16',
500
+ defined: 'CompressedAccount',
486
501
  },
487
502
  },
488
503
  {
489
- name: 'inputCompressedAccountsWithMerkleContext',
504
+ name: 'merkleContext',
490
505
  type: {
491
- vec: {
492
- defined: 'CompressedAccountWithMerkleContext',
493
- },
506
+ defined: 'MerkleContext',
494
507
  },
495
508
  },
509
+ ],
510
+ },
511
+ },
512
+ {
513
+ name: 'MerkleContext',
514
+ type: {
515
+ kind: 'struct',
516
+ fields: [
496
517
  {
497
- name: 'outputCompressedAccounts',
498
- type: {
499
- vec: {
500
- defined: 'CompressedAccount',
501
- },
502
- },
518
+ name: 'merkleTreePubkey',
519
+ type: 'publicKey',
503
520
  },
504
521
  {
505
- name: 'outputStateMerkleTreeAccountIndices',
506
- docs: [
507
- 'The indices of the accounts in the output state merkle tree.',
508
- ],
509
- type: 'bytes',
522
+ name: 'nullifierQueuePubkey',
523
+ type: 'publicKey',
510
524
  },
511
525
  {
512
- name: 'relayFee',
513
- type: {
514
- option: 'u64',
515
- },
526
+ name: 'leafIndex',
527
+ type: 'u32',
516
528
  },
529
+ ],
530
+ },
531
+ },
532
+ {
533
+ name: 'PackedMerkleContext',
534
+ type: {
535
+ kind: 'struct',
536
+ fields: [
517
537
  {
518
- name: 'compressionLamports',
519
- type: {
520
- option: 'u64',
521
- },
538
+ name: 'merkleTreePubkeyIndex',
539
+ type: 'u8',
522
540
  },
523
541
  {
524
- name: 'isCompress',
525
- type: 'bool',
542
+ name: 'nullifierQueuePubkeyIndex',
543
+ type: 'u8',
526
544
  },
527
545
  {
528
- name: 'signerSeeds',
546
+ name: 'leafIndex',
547
+ type: 'u32',
548
+ },
549
+ ],
550
+ },
551
+ },
552
+ {
553
+ name: 'CompressedAccount',
554
+ type: {
555
+ kind: 'struct',
556
+ fields: [
557
+ {
558
+ name: 'owner',
559
+ type: 'publicKey',
560
+ },
561
+ {
562
+ name: 'lamports',
563
+ type: 'u64',
564
+ },
565
+ {
566
+ name: 'address',
567
+ type: {
568
+ option: {
569
+ array: ['u8', 32],
570
+ },
571
+ },
572
+ },
573
+ {
574
+ name: 'data',
529
575
  type: {
530
576
  option: {
531
- vec: 'bytes',
577
+ defined: 'CompressedAccountData',
532
578
  },
533
579
  },
534
580
  },
@@ -536,79 +582,111 @@ const IDL = {
536
582
  },
537
583
  },
538
584
  {
539
- name: 'NewAddressParamsPacked',
585
+ name: 'CompressedAccountData',
540
586
  type: {
541
587
  kind: 'struct',
542
588
  fields: [
543
589
  {
544
- name: 'seed',
590
+ name: 'discriminator',
545
591
  type: {
546
- array: ['u8', 32],
592
+ array: ['u8', 8],
547
593
  },
548
594
  },
549
595
  {
550
- name: 'addressQueueAccountIndex',
551
- type: 'u8',
552
- },
553
- {
554
- name: 'addressMerkleTreeAccountIndex',
555
- type: 'u8',
596
+ name: 'data',
597
+ type: 'bytes',
556
598
  },
557
599
  {
558
- name: 'addressMerkleTreeRootIndex',
559
- type: 'u16',
600
+ name: 'dataHash',
601
+ type: {
602
+ array: ['u8', 32],
603
+ },
560
604
  },
561
605
  ],
562
606
  },
563
607
  },
564
608
  {
565
- name: 'NewAddressParams',
609
+ name: 'PublicTransactionEvent',
566
610
  type: {
567
611
  kind: 'struct',
568
612
  fields: [
569
613
  {
570
- name: 'seed',
614
+ name: 'inputCompressedAccountHashes',
571
615
  type: {
572
- array: ['u8', 32],
616
+ vec: {
617
+ array: ['u8', 32],
618
+ },
573
619
  },
574
620
  },
575
621
  {
576
- name: 'addressQueuePubkey',
577
- type: 'publicKey',
622
+ name: 'outputCompressedAccountHashes',
623
+ type: {
624
+ vec: {
625
+ array: ['u8', 32],
626
+ },
627
+ },
578
628
  },
579
629
  {
580
- name: 'addressMerkleTreePubkey',
581
- type: 'publicKey',
630
+ name: 'outputCompressedAccounts',
631
+ type: {
632
+ vec: {
633
+ defined: 'CompressedAccount',
634
+ },
635
+ },
582
636
  },
583
637
  {
584
- name: 'addressMerkleTreeRootIndex',
585
- type: 'u16',
638
+ name: 'outputStateMerkleTreeAccountIndices',
639
+ type: 'bytes',
640
+ },
641
+ {
642
+ name: 'outputLeafIndices',
643
+ type: {
644
+ vec: 'u32',
645
+ },
646
+ },
647
+ {
648
+ name: 'relayFee',
649
+ type: {
650
+ option: 'u64',
651
+ },
652
+ },
653
+ {
654
+ name: 'isCompress',
655
+ type: 'bool',
656
+ },
657
+ {
658
+ name: 'compressionLamports',
659
+ type: {
660
+ option: 'u64',
661
+ },
662
+ },
663
+ {
664
+ name: 'pubkeyArray',
665
+ type: {
666
+ vec: 'publicKey',
667
+ },
668
+ },
669
+ {
670
+ name: 'message',
671
+ type: {
672
+ option: 'bytes',
673
+ },
586
674
  },
587
675
  ],
588
676
  },
589
677
  },
590
678
  {
591
- name: 'CompressedProof',
679
+ name: 'CompressedCpiContext',
592
680
  type: {
593
681
  kind: 'struct',
594
682
  fields: [
595
683
  {
596
- name: 'a',
597
- type: {
598
- array: ['u8', 32],
599
- },
600
- },
601
- {
602
- name: 'b',
603
- type: {
604
- array: ['u8', 64],
605
- },
684
+ name: 'setContext',
685
+ type: 'bool',
606
686
  },
607
687
  {
608
- name: 'c',
609
- type: {
610
- array: ['u8', 32],
611
- },
688
+ name: 'cpiContextAccountIndex',
689
+ type: 'u8',
612
690
  },
613
691
  ],
614
692
  },
@@ -641,16 +719,10 @@ const IDL = {
641
719
  },
642
720
  },
643
721
  {
644
- name: 'merkleTreePubkeyIndex',
645
- type: 'u8',
646
- },
647
- {
648
- name: 'nullifierQueuePubkeyIndex',
649
- type: 'u8',
650
- },
651
- {
652
- name: 'leafIndex',
653
- type: 'u32',
722
+ name: 'merkleContext',
723
+ type: {
724
+ defined: 'PackedMerkleContext',
725
+ },
654
726
  },
655
727
  ],
656
728
  },
@@ -712,6 +784,14 @@ const IDL = {
712
784
  option: 'u64',
713
785
  },
714
786
  },
787
+ {
788
+ name: 'cpiContext',
789
+ type: {
790
+ option: {
791
+ defined: 'CompressedCpiContext',
792
+ },
793
+ },
794
+ },
715
795
  ],
716
796
  },
717
797
  },
@@ -794,69 +874,11 @@ const IDL = {
794
874
  ],
795
875
  },
796
876
  },
797
- {
798
- name: 'TokenDataClient',
799
- type: {
800
- kind: 'struct',
801
- fields: [
802
- {
803
- name: 'mint',
804
- docs: ['The mint associated with this account'],
805
- type: 'publicKey',
806
- },
807
- {
808
- name: 'owner',
809
- docs: ['The owner of this account.'],
810
- type: 'publicKey',
811
- },
812
- {
813
- name: 'amount',
814
- docs: ['The amount of tokens this account holds.'],
815
- type: 'u64',
816
- },
817
- {
818
- name: 'delegate',
819
- docs: [
820
- 'If `delegate` is `Some` then `delegated_amount` represents',
821
- 'the amount authorized by the delegate',
822
- ],
823
- type: {
824
- option: 'publicKey',
825
- },
826
- },
827
- {
828
- name: 'state',
829
- docs: ["The account's state"],
830
- type: 'u8',
831
- },
832
- {
833
- name: 'isNative',
834
- docs: [
835
- 'If is_some, this is a native token, and the value logs the rent-exempt',
836
- 'reserve. An Account is required to be rent-exempt, so the value is',
837
- 'used by the Processor to ensure that wrapped SOL accounts do not',
838
- 'drop below this threshold.',
839
- ],
840
- type: {
841
- option: 'u64',
842
- },
843
- },
844
- {
845
- name: 'delegatedAmount',
846
- docs: ['The amount delegated'],
847
- type: 'u64',
848
- },
849
- ],
850
- },
851
- },
852
877
  {
853
878
  name: 'AccountState',
854
879
  type: {
855
880
  kind: 'enum',
856
881
  variants: [
857
- {
858
- name: 'Uninitialized',
859
- },
860
882
  {
861
883
  name: 'Initialized',
862
884
  },
@@ -960,9 +982,11 @@ function packCompressedTokenAccounts(params) {
960
982
  ? null
961
983
  : account.parsed.delegatedAmount,
962
984
  isNative: account.parsed.isNative,
963
- merkleTreePubkeyIndex,
964
- nullifierQueuePubkeyIndex,
965
- leafIndex: account.compressedAccount.leafIndex,
985
+ merkleContext: {
986
+ merkleTreePubkeyIndex,
987
+ nullifierQueuePubkeyIndex,
988
+ leafIndex: account.compressedAccount.leafIndex,
989
+ },
966
990
  });
967
991
  });
968
992
  /// pack output state trees
@@ -995,7 +1019,7 @@ const TOKEN_PROGRAM_ID = new PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ
995
1019
  /** Address of the SPL Token 2022 program */
996
1020
  new PublicKey('TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb');
997
1021
  /** Address of the SPL Associated Token Account program */
998
- new PublicKey('ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL');
1022
+ const ASSOCIATED_TOKEN_PROGRAM_ID = new PublicKey('ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL');
999
1023
  /** Address of the special mint for wrapped native SOL in spl-token */
1000
1024
  new PublicKey('So11111111111111111111111111111111111111112');
1001
1025
  /** Address of the special mint for wrapped native SOL in spl-token-2022 */
@@ -5424,6 +5448,62 @@ const publicKey = (property) => {
5424
5448
  return publicKeyLayout;
5425
5449
  };
5426
5450
 
5451
+ /** Base class for errors */
5452
+ class TokenError extends Error {
5453
+ constructor(message) {
5454
+ super(message);
5455
+ }
5456
+ }
5457
+ /** Thrown if an account is not found at the expected address */
5458
+ class TokenAccountNotFoundError extends TokenError {
5459
+ constructor() {
5460
+ super(...arguments);
5461
+ this.name = 'TokenAccountNotFoundError';
5462
+ }
5463
+ }
5464
+ /** Thrown if a program state account is not a valid Account */
5465
+ class TokenInvalidAccountError extends TokenError {
5466
+ constructor() {
5467
+ super(...arguments);
5468
+ this.name = 'TokenInvalidAccountError';
5469
+ }
5470
+ }
5471
+ /** Thrown if a program state account is not owned by the expected token program */
5472
+ class TokenInvalidAccountOwnerError extends TokenError {
5473
+ constructor() {
5474
+ super(...arguments);
5475
+ this.name = 'TokenInvalidAccountOwnerError';
5476
+ }
5477
+ }
5478
+ /** Thrown if the byte length of an program state account doesn't match the expected size */
5479
+ class TokenInvalidAccountSizeError extends TokenError {
5480
+ constructor() {
5481
+ super(...arguments);
5482
+ this.name = 'TokenInvalidAccountSizeError';
5483
+ }
5484
+ }
5485
+ /** Thrown if the mint of a token account doesn't match the expected mint */
5486
+ class TokenInvalidMintError extends TokenError {
5487
+ constructor() {
5488
+ super(...arguments);
5489
+ this.name = 'TokenInvalidMintError';
5490
+ }
5491
+ }
5492
+ /** Thrown if the owner of a token account doesn't match the expected owner */
5493
+ class TokenInvalidOwnerError extends TokenError {
5494
+ constructor() {
5495
+ super(...arguments);
5496
+ this.name = 'TokenInvalidOwnerError';
5497
+ }
5498
+ }
5499
+ /** Thrown if the owner of a token account is a PDA (Program Derived Address) */
5500
+ class TokenOwnerOffCurveError extends TokenError {
5501
+ constructor() {
5502
+ super(...arguments);
5503
+ this.name = 'TokenOwnerOffCurveError';
5504
+ }
5505
+ }
5506
+
5427
5507
  /** Instructions defined by the program */
5428
5508
  var TokenInstruction;
5429
5509
  (function (TokenInstruction) {
@@ -5463,6 +5543,10 @@ var TokenInstruction;
5463
5543
  TokenInstruction[TokenInstruction["InterestBearingMintExtension"] = 33] = "InterestBearingMintExtension";
5464
5544
  TokenInstruction[TokenInstruction["CpiGuardExtension"] = 34] = "CpiGuardExtension";
5465
5545
  TokenInstruction[TokenInstruction["InitializePermanentDelegate"] = 35] = "InitializePermanentDelegate";
5546
+ TokenInstruction[TokenInstruction["TransferHookExtension"] = 36] = "TransferHookExtension";
5547
+ // ConfidentialTransferFeeExtension = 37,
5548
+ // WithdrawalExcessLamports = 38,
5549
+ TokenInstruction[TokenInstruction["MetadataPointerExtension"] = 39] = "MetadataPointerExtension";
5466
5550
  })(TokenInstruction || (TokenInstruction = {}));
5467
5551
 
5468
5552
  /** @internal */
@@ -5510,6 +5594,112 @@ function createApproveInstruction(account, delegate, owner, amount, multiSigners
5510
5594
  return new TransactionInstruction({ keys, programId, data });
5511
5595
  }
5512
5596
 
5597
+ var AccountType;
5598
+ (function (AccountType) {
5599
+ AccountType[AccountType["Uninitialized"] = 0] = "Uninitialized";
5600
+ AccountType[AccountType["Mint"] = 1] = "Mint";
5601
+ AccountType[AccountType["Account"] = 2] = "Account";
5602
+ })(AccountType || (AccountType = {}));
5603
+ const ACCOUNT_TYPE_SIZE = 1;
5604
+
5605
+ /** Buffer layout for de/serializing a multisig */
5606
+ const MultisigLayout = struct([
5607
+ u8('m'),
5608
+ u8('n'),
5609
+ bool('isInitialized'),
5610
+ publicKey('signer1'),
5611
+ publicKey('signer2'),
5612
+ publicKey('signer3'),
5613
+ publicKey('signer4'),
5614
+ publicKey('signer5'),
5615
+ publicKey('signer6'),
5616
+ publicKey('signer7'),
5617
+ publicKey('signer8'),
5618
+ publicKey('signer9'),
5619
+ publicKey('signer10'),
5620
+ publicKey('signer11'),
5621
+ ]);
5622
+ /** Byte length of a multisig */
5623
+ const MULTISIG_SIZE = MultisigLayout.span;
5624
+
5625
+ /** Token account state as stored by the program */
5626
+ var AccountState;
5627
+ (function (AccountState) {
5628
+ AccountState[AccountState["Uninitialized"] = 0] = "Uninitialized";
5629
+ AccountState[AccountState["Initialized"] = 1] = "Initialized";
5630
+ AccountState[AccountState["Frozen"] = 2] = "Frozen";
5631
+ })(AccountState || (AccountState = {}));
5632
+ /** Buffer layout for de/serializing a token account */
5633
+ const AccountLayout = struct([
5634
+ publicKey('mint'),
5635
+ publicKey('owner'),
5636
+ u64('amount'),
5637
+ u32('delegateOption'),
5638
+ publicKey('delegate'),
5639
+ u8('state'),
5640
+ u32('isNativeOption'),
5641
+ u64('isNative'),
5642
+ u64('delegatedAmount'),
5643
+ u32('closeAuthorityOption'),
5644
+ publicKey('closeAuthority'),
5645
+ ]);
5646
+ /** Byte length of a token account */
5647
+ const ACCOUNT_SIZE = AccountLayout.span;
5648
+ /**
5649
+ * Retrieve information about a token account
5650
+ *
5651
+ * @param connection Connection to use
5652
+ * @param address Token account
5653
+ * @param commitment Desired level of commitment for querying the state
5654
+ * @param programId SPL Token program account
5655
+ *
5656
+ * @return Token account information
5657
+ */
5658
+ async function getAccount(connection, address, commitment, programId = TOKEN_PROGRAM_ID) {
5659
+ const info = await connection.getAccountInfo(address, commitment);
5660
+ return unpackAccount(address, info, programId);
5661
+ }
5662
+ /**
5663
+ * Unpack a token account
5664
+ *
5665
+ * @param address Token account
5666
+ * @param info Token account data
5667
+ * @param programId SPL Token program account
5668
+ *
5669
+ * @return Unpacked token account
5670
+ */
5671
+ function unpackAccount(address, info, programId = TOKEN_PROGRAM_ID) {
5672
+ if (!info)
5673
+ throw new TokenAccountNotFoundError();
5674
+ if (!info.owner.equals(programId))
5675
+ throw new TokenInvalidAccountOwnerError();
5676
+ if (info.data.length < ACCOUNT_SIZE)
5677
+ throw new TokenInvalidAccountSizeError();
5678
+ const rawAccount = AccountLayout.decode(info.data.slice(0, ACCOUNT_SIZE));
5679
+ let tlvData = Buffer.alloc(0);
5680
+ if (info.data.length > ACCOUNT_SIZE) {
5681
+ if (info.data.length === MULTISIG_SIZE)
5682
+ throw new TokenInvalidAccountSizeError();
5683
+ if (info.data[ACCOUNT_SIZE] != AccountType.Account)
5684
+ throw new TokenInvalidAccountError();
5685
+ tlvData = info.data.slice(ACCOUNT_SIZE + ACCOUNT_TYPE_SIZE);
5686
+ }
5687
+ return {
5688
+ address,
5689
+ mint: rawAccount.mint,
5690
+ owner: rawAccount.owner,
5691
+ amount: rawAccount.amount,
5692
+ delegate: rawAccount.delegateOption ? rawAccount.delegate : null,
5693
+ delegatedAmount: rawAccount.delegatedAmount,
5694
+ isInitialized: rawAccount.state !== AccountState.Uninitialized,
5695
+ isFrozen: rawAccount.state === AccountState.Frozen,
5696
+ isNative: !!rawAccount.isNativeOption,
5697
+ rentExemptReserve: rawAccount.isNativeOption ? rawAccount.isNative : null,
5698
+ closeAuthority: rawAccount.closeAuthorityOption ? rawAccount.closeAuthority : null,
5699
+ tlvData,
5700
+ };
5701
+ }
5702
+
5513
5703
  /** Buffer layout for de/serializing a mint */
5514
5704
  const MintLayout = struct([
5515
5705
  u32('mintAuthorityOption'),
@@ -5522,6 +5712,54 @@ const MintLayout = struct([
5522
5712
  ]);
5523
5713
  /** Byte length of a mint */
5524
5714
  const MINT_SIZE = MintLayout.span;
5715
+ /**
5716
+ * Get the address of the associated token account for a given mint and owner
5717
+ *
5718
+ * @param mint Token mint account
5719
+ * @param owner Owner of the new account
5720
+ * @param allowOwnerOffCurve Allow the owner account to be a PDA (Program Derived Address)
5721
+ * @param programId SPL Token program account
5722
+ * @param associatedTokenProgramId SPL Associated Token program account
5723
+ *
5724
+ * @return Address of the associated token account
5725
+ */
5726
+ function getAssociatedTokenAddressSync(mint, owner, allowOwnerOffCurve = false, programId = TOKEN_PROGRAM_ID, associatedTokenProgramId = ASSOCIATED_TOKEN_PROGRAM_ID) {
5727
+ if (!allowOwnerOffCurve && !PublicKey.isOnCurve(owner.toBuffer()))
5728
+ throw new TokenOwnerOffCurveError();
5729
+ const [address] = PublicKey.findProgramAddressSync([owner.toBuffer(), programId.toBuffer(), mint.toBuffer()], associatedTokenProgramId);
5730
+ return address;
5731
+ }
5732
+
5733
+ /**
5734
+ * Construct a CreateAssociatedTokenAccount instruction
5735
+ *
5736
+ * @param payer Payer of the initialization fees
5737
+ * @param associatedToken New associated token account
5738
+ * @param owner Owner of the new account
5739
+ * @param mint Token mint account
5740
+ * @param programId SPL Token program account
5741
+ * @param associatedTokenProgramId SPL Associated Token program account
5742
+ *
5743
+ * @return Instruction to add to a transaction
5744
+ */
5745
+ function createAssociatedTokenAccountInstruction(payer, associatedToken, owner, mint, programId = TOKEN_PROGRAM_ID, associatedTokenProgramId = ASSOCIATED_TOKEN_PROGRAM_ID) {
5746
+ return buildAssociatedTokenAccountInstruction(payer, associatedToken, owner, mint, Buffer.alloc(0), programId, associatedTokenProgramId);
5747
+ }
5748
+ function buildAssociatedTokenAccountInstruction(payer, associatedToken, owner, mint, instructionData, programId = TOKEN_PROGRAM_ID, associatedTokenProgramId = ASSOCIATED_TOKEN_PROGRAM_ID) {
5749
+ const keys = [
5750
+ { pubkey: payer, isSigner: true, isWritable: true },
5751
+ { pubkey: associatedToken, isSigner: false, isWritable: true },
5752
+ { pubkey: owner, isSigner: false, isWritable: false },
5753
+ { pubkey: mint, isSigner: false, isWritable: false },
5754
+ { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
5755
+ { pubkey: programId, isSigner: false, isWritable: false },
5756
+ ];
5757
+ return new TransactionInstruction({
5758
+ keys,
5759
+ programId: associatedTokenProgramId,
5760
+ data: instructionData,
5761
+ });
5762
+ }
5525
5763
 
5526
5764
  /** TODO: docs */
5527
5765
  const initializeMint2InstructionData = struct([
@@ -5555,9 +5793,93 @@ function createInitializeMint2Instruction(mint, decimals, mintAuthority, freezeA
5555
5793
  return new TransactionInstruction({ keys, programId, data });
5556
5794
  }
5557
5795
 
5796
+ /**
5797
+ * Retrieve the associated token account, or create it if it doesn't exist
5798
+ *
5799
+ * @param connection Connection to use
5800
+ * @param payer Payer of the transaction and initialization fees
5801
+ * @param mint Mint associated with the account to set or verify
5802
+ * @param owner Owner of the account to set or verify
5803
+ * @param allowOwnerOffCurve Allow the owner account to be a PDA (Program Derived Address)
5804
+ * @param commitment Desired level of commitment for querying the state
5805
+ * @param confirmOptions Options for confirming the transaction
5806
+ * @param programId SPL Token program account
5807
+ * @param associatedTokenProgramId SPL Associated Token program account
5808
+ *
5809
+ * @return Address of the new associated token account
5810
+ */
5811
+ async function getOrCreateAssociatedTokenAccount(connection, payer, mint, owner, allowOwnerOffCurve = false, commitment, confirmOptions, programId = TOKEN_PROGRAM_ID, associatedTokenProgramId = ASSOCIATED_TOKEN_PROGRAM_ID) {
5812
+ const associatedToken = getAssociatedTokenAddressSync(mint, owner, allowOwnerOffCurve, programId, associatedTokenProgramId);
5813
+ // This is the optimal logic, considering TX fee, client-side computation, RPC roundtrips and guaranteed idempotent.
5814
+ // Sadly we can't do this atomically.
5815
+ let account;
5816
+ try {
5817
+ account = await getAccount(connection, associatedToken, commitment, programId);
5818
+ }
5819
+ catch (error) {
5820
+ // TokenAccountNotFoundError can be possible if the associated address has already received some lamports,
5821
+ // becoming a system account. Assuming program derived addressing is safe, this is the only case for the
5822
+ // TokenInvalidAccountOwnerError in this code path.
5823
+ if (error instanceof TokenAccountNotFoundError || error instanceof TokenInvalidAccountOwnerError) {
5824
+ // As this isn't atomic, it's possible others can create associated accounts meanwhile.
5825
+ try {
5826
+ const transaction = new Transaction().add(createAssociatedTokenAccountInstruction(payer.publicKey, associatedToken, owner, mint, programId, associatedTokenProgramId));
5827
+ await sendAndConfirmTransaction(connection, transaction, [payer], confirmOptions);
5828
+ }
5829
+ catch (error) {
5830
+ // Ignore all errors; for now there is no API-compatible way to selectively ignore the expected
5831
+ // instruction error if the associated account exists already.
5832
+ }
5833
+ // Now this should always succeed
5834
+ account = await getAccount(connection, associatedToken, commitment, programId);
5835
+ }
5836
+ else {
5837
+ throw error;
5838
+ }
5839
+ }
5840
+ if (!account.mint.equals(mint))
5841
+ throw new TokenInvalidMintError();
5842
+ if (!account.owner.equals(owner))
5843
+ throw new TokenInvalidOwnerError();
5844
+ return account;
5845
+ }
5846
+
5847
+ /** TODO: docs */
5848
+ const mintToInstructionData = struct([u8('instruction'), u64('amount')]);
5849
+ /**
5850
+ * Construct a MintTo instruction
5851
+ *
5852
+ * @param mint Public key of the mint
5853
+ * @param destination Address of the token account to mint to
5854
+ * @param authority The mint authority
5855
+ * @param amount Amount to mint
5856
+ * @param multiSigners Signing accounts if `authority` is a multisig
5857
+ * @param programId SPL Token program account
5858
+ *
5859
+ * @return Instruction to add to a transaction
5860
+ */
5861
+ function createMintToInstruction(mint, destination, authority, amount, multiSigners = [], programId = TOKEN_PROGRAM_ID) {
5862
+ const keys = addSigners([
5863
+ { pubkey: mint, isSigner: false, isWritable: true },
5864
+ { pubkey: destination, isSigner: false, isWritable: true },
5865
+ ], authority, multiSigners);
5866
+ const data = Buffer.alloc(mintToInstructionData.span);
5867
+ mintToInstructionData.encode({
5868
+ instruction: TokenInstruction.MintTo,
5869
+ amount: BigInt(amount),
5870
+ }, data);
5871
+ return new TransactionInstruction({ keys, programId, data });
5872
+ }
5873
+
5874
+ /**
5875
+ * Sum up the token amounts of the compressed token accounts
5876
+ */
5558
5877
  const sumUpTokenAmount = (accounts) => {
5559
5878
  return accounts.reduce((acc, account) => acc.add(account.parsed.amount), bn(0));
5560
5879
  };
5880
+ /**
5881
+ * Validate that all the compressed token accounts are owned by the same owner.
5882
+ */
5561
5883
  const validateSameTokenOwner = (accounts) => {
5562
5884
  const owner = accounts[0].parsed.owner;
5563
5885
  accounts.forEach(acc => {
@@ -5566,12 +5888,23 @@ const validateSameTokenOwner = (accounts) => {
5566
5888
  }
5567
5889
  });
5568
5890
  };
5569
- const parseInputTokenData = (inputCompressedTokenAccounts) => {
5570
- const mint = inputCompressedTokenAccounts[0].parsed.mint;
5571
- const currentOwner = inputCompressedTokenAccounts[0].parsed.owner;
5572
- const delegate = inputCompressedTokenAccounts[0].parsed.delegate;
5891
+ /**
5892
+ * Parse compressed token accounts to get the mint, current owner and delegate.
5893
+ */
5894
+ const parseTokenData = (compressedTokenAccounts) => {
5895
+ const mint = compressedTokenAccounts[0].parsed.mint;
5896
+ const currentOwner = compressedTokenAccounts[0].parsed.owner;
5897
+ const delegate = compressedTokenAccounts[0].parsed.delegate;
5573
5898
  return { mint, currentOwner, delegate };
5574
5899
  };
5900
+ /**
5901
+ * Create the output state for a transfer transaction.
5902
+ * @param inputCompressedTokenAccounts Input state
5903
+ * @param toAddress Recipient address
5904
+ * @param amount Amount of tokens to transfer
5905
+ * @returns Output token data for the transfer
5906
+ * instruction
5907
+ */
5575
5908
  function createTransferOutputState(inputCompressedTokenAccounts, toAddress, amount) {
5576
5909
  amount = bn(amount);
5577
5910
  const inputAmount = sumUpTokenAmount(inputCompressedTokenAccounts);
@@ -5604,6 +5937,13 @@ function createTransferOutputState(inputCompressedTokenAccounts, toAddress, amou
5604
5937
  ];
5605
5938
  return outputCompressedAccounts;
5606
5939
  }
5940
+ /**
5941
+ * Create the output state for a compress transaction.
5942
+ * @param inputCompressedTokenAccounts Input state
5943
+ * @param amount Amount of tokens to compress
5944
+ * @returns Output token data for the compress
5945
+ * instruction
5946
+ */
5607
5947
  function createDecompressOutputState(inputCompressedTokenAccounts, amount) {
5608
5948
  amount = bn(amount);
5609
5949
  const inputLamports = sumUpLamports(inputCompressedTokenAccounts.map(acc => acc.compressedAccount));
@@ -5633,10 +5973,9 @@ class CompressedTokenProgram {
5633
5973
  /**
5634
5974
  * Public key that identifies the CompressedPda program
5635
5975
  */
5636
- static programId = new PublicKey(
5637
- // TODO: can add check to ensure its consistent with the idl
5638
- '9sixVEthz2kMSKfeApZXHwuboT6DZuT6crAYJTciUCqE');
5976
+ static programId = new PublicKey('9sixVEthz2kMSKfeApZXHwuboT6DZuT6crAYJTciUCqE');
5639
5977
  static _program = null;
5978
+ /** @internal */
5640
5979
  static get program() {
5641
5980
  if (!this._program) {
5642
5981
  this.initializeProgram();
@@ -5644,12 +5983,14 @@ class CompressedTokenProgram {
5644
5983
  return this._program;
5645
5984
  }
5646
5985
  /**
5986
+ * @internal
5647
5987
  * Initializes the program statically if not already initialized.
5648
5988
  */
5649
5989
  static initializeProgram() {
5650
5990
  if (!this._program) {
5651
- /// We can use a mock connection because we're using the program only for
5652
- /// serde and building instructions, not for interacting with the network.
5991
+ /// Note: We can use a mock connection because we're using the
5992
+ /// program only for serde and building instructions, not for
5993
+ /// interacting with the network.
5653
5994
  const mockKeypair = Keypair.generate();
5654
5995
  const mockConnection = new Connection('http://127.0.0.1:8899', 'confirmed');
5655
5996
  const mockProvider = new AnchorProvider(mockConnection, useWallet(mockKeypair), confirmConfig);
@@ -5659,8 +6000,7 @@ class CompressedTokenProgram {
5659
6000
  }
5660
6001
  /** @internal */
5661
6002
  static deriveMintAuthorityPda = (authority, mint) => {
5662
- const [pubkey] = PublicKey.findProgramAddressSync([MINT_AUTHORITY_SEED, authority.toBuffer(), mint.toBuffer()], this.programId);
5663
- return pubkey;
6003
+ return PublicKey.findProgramAddressSync([MINT_AUTHORITY_SEED, authority.toBuffer(), mint.toBuffer()], this.programId);
5664
6004
  };
5665
6005
  /** @internal */
5666
6006
  static deriveTokenPoolPda(mint) {
@@ -5673,8 +6013,12 @@ class CompressedTokenProgram {
5673
6013
  const [address, _] = PublicKey.findProgramAddressSync([CPI_AUTHORITY_SEED], this.programId);
5674
6014
  return address;
5675
6015
  }
6016
+ /**
6017
+ * Construct createMint instruction for compressed tokens
6018
+ */
5676
6019
  static async createMint(params) {
5677
6020
  const { mint, authority, feePayer, rentExemptBalance } = params;
6021
+ /// Create and initialize SPL Mint account
5678
6022
  const createMintAccountInstruction = SystemProgram.createAccount({
5679
6023
  fromPubkey: feePayer,
5680
6024
  lamports: rentExemptBalance,
@@ -5682,14 +6026,17 @@ class CompressedTokenProgram {
5682
6026
  programId: TOKEN_PROGRAM_ID,
5683
6027
  space: MINT_SIZE,
5684
6028
  });
5685
- const mintAuthorityPda = this.deriveMintAuthorityPda(authority, mint);
6029
+ const [mintAuthorityPda] = this.deriveMintAuthorityPda(authority, mint);
5686
6030
  const initializeMintInstruction = createInitializeMint2Instruction(mint, params.decimals, mintAuthorityPda, params.freezeAuthority, TOKEN_PROGRAM_ID);
6031
+ /// Fund the mint authority PDA. The authority is system-owned in order
6032
+ /// to natively mint compressed tokens.
5687
6033
  const fundAuthorityPdaInstruction = SystemProgram.transfer({
5688
6034
  fromPubkey: feePayer,
5689
6035
  toPubkey: mintAuthorityPda,
5690
- lamports: rentExemptBalance, // TODO: check that this is the right PDA size
6036
+ lamports: rentExemptBalance,
5691
6037
  });
5692
6038
  const tokenPoolPda = this.deriveTokenPoolPda(mint);
6039
+ /// Create omnibus compressed mint account
5693
6040
  const ix = await this.program.methods
5694
6041
  .createMint()
5695
6042
  .accounts({
@@ -5710,15 +6057,41 @@ class CompressedTokenProgram {
5710
6057
  ix,
5711
6058
  ];
5712
6059
  }
6060
+ /**
6061
+ * Enable compression for an existing SPL mint, creating an omnibus account.
6062
+ * For new mints, use `CompressedTokenProgram.createMint`.
6063
+ */
6064
+ static async registerMint(params) {
6065
+ const { mint, authority, feePayer } = params;
6066
+ const [mintAuthorityPda] = this.deriveMintAuthorityPda(authority, mint);
6067
+ const tokenPoolPda = this.deriveTokenPoolPda(mint);
6068
+ const ix = await this.program.methods
6069
+ .createMint()
6070
+ .accounts({
6071
+ mint,
6072
+ feePayer,
6073
+ authority,
6074
+ tokenPoolPda,
6075
+ systemProgram: SystemProgram.programId,
6076
+ mintAuthorityPda,
6077
+ tokenProgram: TOKEN_PROGRAM_ID,
6078
+ cpiAuthorityPda: this.deriveCpiAuthorityPda,
6079
+ })
6080
+ .instruction();
6081
+ return [ix];
6082
+ }
6083
+ /**
6084
+ * Construct mintTo instruction for compressed tokens
6085
+ */
5713
6086
  static async mintTo(params) {
5714
6087
  const systemKeys = defaultStaticAccountsStruct();
5715
6088
  const { mint, feePayer, authority, merkleTree, toPubkey, amount } = params;
5716
6089
  const tokenPoolPda = this.deriveTokenPoolPda(mint);
5717
- const mintAuthorityPda = this.deriveMintAuthorityPda(authority, mint);
6090
+ const [mintAuthorityPda, bump] = this.deriveMintAuthorityPda(authority, mint);
5718
6091
  const amounts = toArray(amount).map(amount => bn(amount));
5719
6092
  const toPubkeys = toArray(toPubkey);
5720
- const ix = await this.program.methods
5721
- .mintTo(toPubkeys, amounts)
6093
+ const instruction = await this.program.methods
6094
+ .mintTo(toPubkeys, amounts, bump)
5722
6095
  .accounts({
5723
6096
  feePayer,
5724
6097
  authority,
@@ -5726,7 +6099,7 @@ class CompressedTokenProgram {
5726
6099
  mint,
5727
6100
  tokenPoolPda,
5728
6101
  tokenProgram: TOKEN_PROGRAM_ID,
5729
- compressedPdaProgram: LightSystemProgram.programId,
6102
+ lightSystemProgram: LightSystemProgram.programId,
5730
6103
  registeredProgramPda: systemKeys.registeredProgramPda,
5731
6104
  noopProgram: systemKeys.noopProgram,
5732
6105
  accountCompressionAuthority: systemKeys.accountCompressionAuthority,
@@ -5735,18 +6108,43 @@ class CompressedTokenProgram {
5735
6108
  selfProgram: this.programId,
5736
6109
  })
5737
6110
  .instruction();
5738
- return ix;
6111
+ return instruction;
6112
+ }
6113
+ /// TODO: add compressBatch functionality for batch minting
6114
+ /**
6115
+ * Mint tokens from registed SPL mint account to a compressed account
6116
+ */
6117
+ static async approveAndMintTo(params) {
6118
+ const { mint, feePayer, authorityTokenAccount, authority, merkleTree, toPubkey, } = params;
6119
+ const amount = BigInt(params.amount.toString());
6120
+ /// 1. Mint to mint authority ATA
6121
+ const splMintToInstruction = createMintToInstruction(mint, authorityTokenAccount, authority, amount);
6122
+ /// 2. Compressed token program mintTo
6123
+ const approveInstruction = createApproveInstruction(authorityTokenAccount, this.deriveCpiAuthorityPda, authority, amount);
6124
+ /// 3. Compress from mint authority ATA to recipient compressed account
6125
+ const ixs = await this.compress({
6126
+ payer: feePayer,
6127
+ owner: authority,
6128
+ source: authorityTokenAccount,
6129
+ toAddress: toPubkey,
6130
+ mint,
6131
+ amount: bn(amount.toString()),
6132
+ outputStateTree: merkleTree,
6133
+ });
6134
+ return [splMintToInstruction, approveInstruction, ...ixs];
5739
6135
  }
6136
+ /**
6137
+ * Construct transfer instruction for compressed tokens
6138
+ */
5740
6139
  static async transfer(params) {
5741
6140
  const { payer, inputCompressedTokenAccounts, recentInputStateRootIndices, recentValidityProof, amount, outputStateTrees, toAddress, } = params;
5742
6141
  const outputCompressedAccounts = createTransferOutputState(inputCompressedTokenAccounts, toAddress, amount);
5743
- /// Pack
5744
6142
  const { inputTokenDataWithContext, outputStateMerkleTreeIndices, remainingAccountMetas, } = packCompressedTokenAccounts({
5745
6143
  inputCompressedTokenAccounts,
5746
6144
  outputCompressedAccountsLength: outputCompressedAccounts.length,
5747
6145
  outputStateTrees,
5748
6146
  });
5749
- const { mint, currentOwner } = parseInputTokenData(inputCompressedTokenAccounts);
6147
+ const { mint, currentOwner } = parseTokenData(inputCompressedTokenAccounts);
5750
6148
  const data = {
5751
6149
  proof: recentValidityProof,
5752
6150
  rootIndices: recentInputStateRootIndices,
@@ -5757,16 +6155,17 @@ class CompressedTokenProgram {
5757
6155
  outputStateMerkleTreeAccountIndices: Buffer$1.from(outputStateMerkleTreeIndices),
5758
6156
  compressionAmount: null,
5759
6157
  isCompress: false,
6158
+ cpiContext: null,
5760
6159
  };
5761
6160
  const encodedData = this.program.coder.types.encode('CompressedTokenInstructionDataTransfer', data);
5762
6161
  const { accountCompressionAuthority, noopProgram, registeredProgramPda, accountCompressionProgram, } = defaultStaticAccountsStruct();
5763
6162
  const instruction = await this.program.methods
5764
- .transfer(encodedData, null)
6163
+ .transfer(encodedData)
5765
6164
  .accounts({
5766
6165
  feePayer: payer,
5767
6166
  authority: currentOwner,
5768
6167
  cpiAuthorityPda: this.deriveCpiAuthorityPda,
5769
- compressedPdaProgram: LightSystemProgram.programId,
6168
+ lightSystemProgram: LightSystemProgram.programId,
5770
6169
  registeredProgramPda: registeredProgramPda,
5771
6170
  noopProgram: noopProgram,
5772
6171
  accountCompressionAuthority: accountCompressionAuthority,
@@ -5778,11 +6177,12 @@ class CompressedTokenProgram {
5778
6177
  })
5779
6178
  .remainingAccounts(remainingAccountMetas)
5780
6179
  .instruction();
5781
- return [
5782
- ComputeBudgetProgram.setComputeUnitLimit({ units: 1000000 }),
5783
- instruction,
5784
- ];
6180
+ return instruction;
5785
6181
  }
6182
+ /**
6183
+ * Construct approve and compress instructions
6184
+ * @returns [approveInstruction, compressInstruction]
6185
+ */
5786
6186
  static async compress(params) {
5787
6187
  const { payer, owner, source, toAddress, mint, outputStateTree } = params;
5788
6188
  const amount = bn(params.amount);
@@ -5793,7 +6193,6 @@ class CompressedTokenProgram {
5793
6193
  lamports: bn(0),
5794
6194
  },
5795
6195
  ];
5796
- /// Pack
5797
6196
  const { inputTokenDataWithContext, outputStateMerkleTreeIndices, remainingAccountMetas, } = packCompressedTokenAccounts({
5798
6197
  inputCompressedTokenAccounts: [],
5799
6198
  outputCompressedAccountsLength: outputCompressedAccounts.length,
@@ -5809,19 +6208,18 @@ class CompressedTokenProgram {
5809
6208
  outputStateMerkleTreeAccountIndices: Buffer$1.from(outputStateMerkleTreeIndices),
5810
6209
  compressionAmount: amount,
5811
6210
  isCompress: true,
6211
+ cpiContext: null,
5812
6212
  };
5813
6213
  const encodedData = this.program.coder.types.encode('CompressedTokenInstructionDataTransfer', data);
5814
6214
  const { accountCompressionAuthority, noopProgram, registeredProgramPda, accountCompressionProgram, } = defaultStaticAccountsStruct();
5815
- /// TODO: add support for multiSigners
5816
- /// TODO: validate that we don't need approveChecked
5817
6215
  const approveInstruction = createApproveInstruction(source, this.deriveCpiAuthorityPda, owner, BigInt(amount.toString()));
5818
6216
  const instruction = await this.program.methods
5819
- .transfer(encodedData, null)
6217
+ .transfer(encodedData)
5820
6218
  .accounts({
5821
6219
  feePayer: payer,
5822
6220
  authority: owner,
5823
6221
  cpiAuthorityPda: this.deriveCpiAuthorityPda,
5824
- compressedPdaProgram: LightSystemProgram.programId,
6222
+ lightSystemProgram: LightSystemProgram.programId,
5825
6223
  registeredProgramPda: registeredProgramPda,
5826
6224
  noopProgram: noopProgram,
5827
6225
  accountCompressionAuthority: accountCompressionAuthority,
@@ -5833,12 +6231,11 @@ class CompressedTokenProgram {
5833
6231
  })
5834
6232
  .remainingAccounts(remainingAccountMetas)
5835
6233
  .instruction();
5836
- return [
5837
- ComputeBudgetProgram.setComputeUnitLimit({ units: 1000000 }),
5838
- approveInstruction,
5839
- instruction,
5840
- ];
6234
+ return [approveInstruction, instruction];
5841
6235
  }
6236
+ /**
6237
+ * Construct decompress instruction
6238
+ */
5842
6239
  static async decompress(params) {
5843
6240
  const { payer, inputCompressedTokenAccounts, toAddress, outputStateTree, recentValidityProof, recentInputStateRootIndices, } = params;
5844
6241
  const amount = bn(params.amount);
@@ -5849,7 +6246,7 @@ class CompressedTokenProgram {
5849
6246
  outputCompressedAccountsLength: tokenTransferOutputs.length,
5850
6247
  outputStateTrees: [outputStateTree],
5851
6248
  });
5852
- const { mint, currentOwner } = parseInputTokenData(inputCompressedTokenAccounts);
6249
+ const { mint, currentOwner } = parseTokenData(inputCompressedTokenAccounts);
5853
6250
  const data = {
5854
6251
  proof: recentValidityProof,
5855
6252
  rootIndices: recentInputStateRootIndices,
@@ -5860,34 +6257,68 @@ class CompressedTokenProgram {
5860
6257
  outputStateMerkleTreeAccountIndices: Buffer$1.from(outputStateMerkleTreeIndices),
5861
6258
  compressionAmount: amount,
5862
6259
  isCompress: false,
6260
+ cpiContext: null,
5863
6261
  };
5864
6262
  const encodedData = this.program.coder.types.encode('CompressedTokenInstructionDataTransfer', data);
5865
6263
  const { accountCompressionAuthority, noopProgram, registeredProgramPda, accountCompressionProgram, } = defaultStaticAccountsStruct();
5866
6264
  const instruction = await this.program.methods
5867
- .transfer(encodedData, null)
6265
+ .transfer(encodedData)
5868
6266
  .accounts({
5869
6267
  feePayer: payer,
5870
6268
  authority: currentOwner,
5871
6269
  cpiAuthorityPda: this.deriveCpiAuthorityPda,
5872
- compressedPdaProgram: LightSystemProgram.programId,
6270
+ lightSystemProgram: LightSystemProgram.programId,
5873
6271
  registeredProgramPda: registeredProgramPda,
5874
6272
  noopProgram: noopProgram,
5875
6273
  accountCompressionAuthority: accountCompressionAuthority,
5876
6274
  accountCompressionProgram: accountCompressionProgram,
5877
6275
  selfProgram: this.programId,
5878
6276
  tokenPoolPda: this.deriveTokenPoolPda(mint),
5879
- decompressTokenAccount: toAddress, // token
6277
+ decompressTokenAccount: toAddress,
5880
6278
  tokenProgram: TOKEN_PROGRAM_ID,
5881
6279
  })
5882
6280
  .remainingAccounts(remainingAccountMetas)
5883
6281
  .instruction();
5884
- return [
5885
- ComputeBudgetProgram.setComputeUnitLimit({ units: 1000000 }),
5886
- instruction,
5887
- ];
6282
+ return instruction;
5888
6283
  }
5889
6284
  }
5890
6285
 
6286
+ /**
6287
+ * Mint compressed tokens to a solana address from an external mint authority
6288
+ *
6289
+ * @param rpc Rpc to use
6290
+ * @param payer Payer of the transaction fees
6291
+ * @param mint Mint for the account
6292
+ * @param destination Address of the account to mint to
6293
+ * @param authority Minting authority
6294
+ * @param amount Amount to mint
6295
+ * @param merkleTree State tree account that the compressed tokens should be
6296
+ * part of. Defaults to the default state tree account.
6297
+ * @param confirmOptions Options for confirming the transaction
6298
+ *
6299
+ * @return Signature of the confirmed transaction
6300
+ */
6301
+ async function approveAndMintTo(rpc, payer, mint, destination, authority, amount, merkleTree = defaultTestStateTreeAccounts().merkleTree, confirmOptions) {
6302
+ const authorityTokenAccount = await getOrCreateAssociatedTokenAccount(rpc, payer, mint, authority.publicKey);
6303
+ const ixs = await CompressedTokenProgram.approveAndMintTo({
6304
+ feePayer: payer.publicKey,
6305
+ mint,
6306
+ authority: authority.publicKey,
6307
+ authorityTokenAccount: authorityTokenAccount.address,
6308
+ amount,
6309
+ toPubkey: destination,
6310
+ merkleTree,
6311
+ });
6312
+ const { blockhash } = await rpc.getLatestBlockhash();
6313
+ const additionalSigners = dedupeSigner(payer, [authority]);
6314
+ const tx = buildAndSignTx([
6315
+ ComputeBudgetProgram.setComputeUnitLimit({ units: 1000000 }),
6316
+ ...ixs,
6317
+ ], payer, blockhash, additionalSigners);
6318
+ const txId = await sendAndConfirmTx(rpc, tx, confirmOptions);
6319
+ return txId;
6320
+ }
6321
+
5891
6322
  /**
5892
6323
  * Compress SPL tokens
5893
6324
  *
@@ -5908,7 +6339,7 @@ class CompressedTokenProgram {
5908
6339
  */
5909
6340
  async function compress(rpc, payer, mint, amount, owner, sourceTokenAccount, toAddress, merkleTree = defaultTestStateTreeAccounts().merkleTree, confirmOptions) {
5910
6341
  amount = bn(amount);
5911
- const ixs = await CompressedTokenProgram.compress({
6342
+ const [approveIx, compressIx] = await CompressedTokenProgram.compress({
5912
6343
  payer: payer.publicKey,
5913
6344
  owner: owner.publicKey,
5914
6345
  source: sourceTokenAccount,
@@ -5919,7 +6350,13 @@ async function compress(rpc, payer, mint, amount, owner, sourceTokenAccount, toA
5919
6350
  });
5920
6351
  const blockhashCtx = await rpc.getLatestBlockhash();
5921
6352
  const additionalSigners = dedupeSigner(payer, [owner]);
5922
- const signedTx = buildAndSignTx(ixs, payer, blockhashCtx.blockhash, additionalSigners);
6353
+ const signedTx = buildAndSignTx([
6354
+ ComputeBudgetProgram.setComputeUnitLimit({
6355
+ units: 1000000,
6356
+ }),
6357
+ approveIx,
6358
+ compressIx,
6359
+ ], payer, blockhashCtx.blockhash, additionalSigners);
5923
6360
  const txId = await sendAndConfirmTx(rpc, signedTx, confirmOptions, blockhashCtx);
5924
6361
  return txId;
5925
6362
  }
@@ -5949,7 +6386,7 @@ merkleTree = defaultTestStateTreeAccounts().merkleTree, confirmOptions) {
5949
6386
  });
5950
6387
  const [inputAccounts] = selectMinCompressedTokenAccountsForTransfer(compressedTokenAccounts, amount);
5951
6388
  const proof = await rpc.getValidityProof(inputAccounts.map(account => bn(account.compressedAccount.hash)));
5952
- const ixs = await CompressedTokenProgram.transfer({
6389
+ const ix = await CompressedTokenProgram.transfer({
5953
6390
  payer: payer.publicKey,
5954
6391
  inputCompressedTokenAccounts: inputAccounts,
5955
6392
  toAddress,
@@ -5960,7 +6397,7 @@ merkleTree = defaultTestStateTreeAccounts().merkleTree, confirmOptions) {
5960
6397
  });
5961
6398
  const { blockhash } = await rpc.getLatestBlockhash();
5962
6399
  const additionalSigners = dedupeSigner(payer, [owner]);
5963
- const signedTx = buildAndSignTx(ixs, payer, blockhash, additionalSigners);
6400
+ const signedTx = buildAndSignTx([ComputeBudgetProgram.setComputeUnitLimit({ units: 1000000 }), ix], payer, blockhash, additionalSigners);
5964
6401
  const txId = await sendAndConfirmTx(rpc, signedTx, confirmOptions);
5965
6402
  return txId;
5966
6403
  }
@@ -6021,7 +6458,7 @@ merkleTree = defaultTestStateTreeAccounts().merkleTree, confirmOptions) {
6021
6458
  /// TODO: consider using a different selection algorithm
6022
6459
  const [inputAccounts] = selectMinCompressedTokenAccountsForTransfer(compressedTokenAccounts, amount);
6023
6460
  const proof = await rpc.getValidityProof(inputAccounts.map(account => bn(account.compressedAccount.hash)));
6024
- const ixs = await CompressedTokenProgram.decompress({
6461
+ const ix = await CompressedTokenProgram.decompress({
6025
6462
  payer: payer.publicKey,
6026
6463
  inputCompressedTokenAccounts: inputAccounts,
6027
6464
  toAddress, // TODO: add explicit check that it is a token account
@@ -6032,7 +6469,7 @@ merkleTree = defaultTestStateTreeAccounts().merkleTree, confirmOptions) {
6032
6469
  });
6033
6470
  const { blockhash } = await rpc.getLatestBlockhash();
6034
6471
  const additionalSigners = dedupeSigner(payer, [owner]);
6035
- const signedTx = buildAndSignTx(ixs, payer, blockhash, additionalSigners);
6472
+ const signedTx = buildAndSignTx([ComputeBudgetProgram.setComputeUnitLimit({ units: 1000000 }), ix], payer, blockhash, additionalSigners);
6036
6473
  const txId = await sendAndConfirmTx(rpc, signedTx, confirmOptions);
6037
6474
  return txId;
6038
6475
  }
@@ -6098,5 +6535,29 @@ confirmOptions) {
6098
6535
  return txId;
6099
6536
  }
6100
6537
 
6101
- export { CPI_AUTHORITY_SEED, CompressedTokenProgram, IDL, MINT_AUTHORITY_SEED, POOL_SEED, SPL_TOKEN_MINT_RENT_EXEMPT_BALANCE, compress, createDecompressOutputState, createMint, createTransferOutputState, decompress, mintTo, packCompressedTokenAccounts, parseInputTokenData, selectMinCompressedTokenAccountsForTransfer, sumUpTokenAmount, transfer, validateSameTokenOwner };
6538
+ /**
6539
+ * Register an existing mint with the CompressedToken program
6540
+ *
6541
+ * @param rpc RPC to use
6542
+ * @param payer Payer of the transaction and initialization fees
6543
+ * @param mintAuthority Account or multisig that will control minting. Is signer.
6544
+ * @param mintAddress Address of the existing mint
6545
+ * @param confirmOptions Options for confirming the transaction
6546
+ *
6547
+ * @return transaction signature
6548
+ */
6549
+ async function registerMint(rpc, payer, mintAuthority, mintAddress, confirmOptions) {
6550
+ const ixs = await CompressedTokenProgram.registerMint({
6551
+ feePayer: payer.publicKey,
6552
+ mint: mintAddress,
6553
+ authority: mintAuthority.publicKey,
6554
+ });
6555
+ const { blockhash } = await rpc.getLatestBlockhash();
6556
+ const additionalSigners = dedupeSigner(payer, [mintAuthority]);
6557
+ const tx = buildAndSignTx(ixs, payer, blockhash, additionalSigners);
6558
+ const txId = await sendAndConfirmTx(rpc, tx, confirmOptions);
6559
+ return txId;
6560
+ }
6561
+
6562
+ export { CPI_AUTHORITY_SEED, CompressedTokenProgram, IDL, MINT_AUTHORITY_SEED, POOL_SEED, SPL_TOKEN_MINT_RENT_EXEMPT_BALANCE, approveAndMintTo, compress, createDecompressOutputState, createMint, createTransferOutputState, decompress, mintTo, packCompressedTokenAccounts, parseTokenData, registerMint, selectMinCompressedTokenAccountsForTransfer, sumUpTokenAmount, transfer, validateSameTokenOwner };
6102
6563
  //# sourceMappingURL=index.js.map