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