@lightprotocol/stateless.js 0.1.0-alpha.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.
Files changed (44) hide show
  1. package/README.md +58 -0
  2. package/dist/cjs/index.cjs +4031 -0
  3. package/dist/es/index.js +3988 -0
  4. package/dist/types/actions/common.d.ts +3 -0
  5. package/dist/types/actions/compress-lamports.d.ts +16 -0
  6. package/dist/types/actions/decompress-lamports.d.ts +16 -0
  7. package/dist/types/actions/index.d.ts +4 -0
  8. package/dist/types/actions/init-sol-omnibus-account.d.ts +13 -0
  9. package/dist/types/constants.d.ts +34 -0
  10. package/dist/types/errors.d.ts +74 -0
  11. package/dist/types/idls/account_compression.d.ts +932 -0
  12. package/dist/types/idls/index.d.ts +5 -0
  13. package/dist/types/idls/light.d.ts +192 -0
  14. package/dist/types/idls/psp_compressed_pda.d.ts +607 -0
  15. package/dist/types/idls/user_registry.d.ts +69 -0
  16. package/dist/types/index.d.ts +12 -0
  17. package/dist/types/instruction/index.d.ts +1 -0
  18. package/dist/types/instruction/pack-compressed-accounts.d.ts +30 -0
  19. package/dist/types/programs/compressed-pda.d.ts +148 -0
  20. package/dist/types/programs/index.d.ts +1 -0
  21. package/dist/types/rpc-interface.d.ts +430 -0
  22. package/dist/types/rpc.d.ts +26 -0
  23. package/dist/types/state/BN254.d.ts +20 -0
  24. package/dist/types/state/compressed-account.d.ts +35 -0
  25. package/dist/types/state/index.d.ts +3 -0
  26. package/dist/types/state/types.d.ts +108 -0
  27. package/dist/types/test-utils/common.d.ts +32 -0
  28. package/dist/types/test-utils/index.d.ts +5 -0
  29. package/dist/types/test-utils/merkle-tree.d.ts +92 -0
  30. package/dist/types/test-utils/parse-event.d.ts +7 -0
  31. package/dist/types/test-utils/parse-validity-proof.d.ts +20 -0
  32. package/dist/types/test-utils/test-rpc.d.ts +51 -0
  33. package/dist/types/utils/airdrop.d.ts +7 -0
  34. package/dist/types/utils/conversion.d.ts +10 -0
  35. package/dist/types/utils/index.d.ts +6 -0
  36. package/dist/types/utils/pipe.d.ts +2 -0
  37. package/dist/types/utils/send-and-confirm.d.ts +18 -0
  38. package/dist/types/utils/sleep.d.ts +1 -0
  39. package/dist/types/utils/validation.d.ts +4 -0
  40. package/dist/types/wallet/index.d.ts +1 -0
  41. package/dist/types/wallet/interface.d.ts +25 -0
  42. package/dist/types/wallet/use-wallet.d.ts +9 -0
  43. package/dist/umd/index.js +4027 -0
  44. package/package.json +81 -0
@@ -0,0 +1,4027 @@
1
+ (function (global, factory) {
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@coral-xyz/anchor'), require('@solana/web3.js'), require('tweetnacl'), require('@coral-xyz/anchor/dist/cjs/utils/bytes'), require('buffer'), require('@noble/hashes/sha3'), require('@lightprotocol/hasher.rs'), require('axios'), require('superstruct')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', '@coral-xyz/anchor', '@solana/web3.js', 'tweetnacl', '@coral-xyz/anchor/dist/cjs/utils/bytes', 'buffer', '@noble/hashes/sha3', '@lightprotocol/hasher.rs', 'axios', 'superstruct'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global["@lightprotocol/stateless"] = global["@lightprotocol/stateless"] || {}, global["@lightprotocol/stateless"].js = {}), global.anchor, global.web3.js, global.tweetnacl, global.bytes, global.buffer, global.sha3, global.hasher_rs, global.axios, global.superstruct));
5
+ })(this, (function (exports, anchor, web3_js, tweetnacl, bytes, buffer, sha3, hasher_rs, axios, superstruct) { 'use strict';
6
+
7
+ const IDL$3 = {
8
+ version: '0.3.0',
9
+ name: 'psp_compressed_pda',
10
+ constants: [
11
+ {
12
+ name: 'COMPRESSED_SOL_PDA_SEED',
13
+ type: 'bytes',
14
+ value: '[99, 111, 109, 112, 114, 101, 115, 115, 101, 100, 95, 115, 111, 108, 95, 112, 100, 97]',
15
+ },
16
+ ],
17
+ instructions: [
18
+ {
19
+ name: 'initCompressSolPda',
20
+ docs: [
21
+ 'Initializes the compressed sol pda.',
22
+ 'This pda is used to store compressed sol for the protocol.',
23
+ ],
24
+ accounts: [
25
+ {
26
+ name: 'feePayer',
27
+ isMut: true,
28
+ isSigner: true,
29
+ },
30
+ {
31
+ name: 'compressedSolPda',
32
+ isMut: true,
33
+ isSigner: false,
34
+ },
35
+ {
36
+ name: 'systemProgram',
37
+ isMut: false,
38
+ isSigner: false,
39
+ },
40
+ ],
41
+ args: [],
42
+ },
43
+ {
44
+ name: 'executeCompressedTransaction',
45
+ docs: [
46
+ 'This function can be used to transfer sol and execute any other compressed transaction.',
47
+ 'Instruction data is not optimized for space.',
48
+ 'This method can be called by cpi so that instruction data can be compressed with a custom algorithm.',
49
+ ],
50
+ accounts: [
51
+ {
52
+ name: 'signer',
53
+ isMut: false,
54
+ isSigner: true,
55
+ },
56
+ {
57
+ name: 'registeredProgramPda',
58
+ isMut: false,
59
+ isSigner: false,
60
+ },
61
+ {
62
+ name: 'noopProgram',
63
+ isMut: false,
64
+ isSigner: false,
65
+ },
66
+ {
67
+ name: 'pspAccountCompressionAuthority',
68
+ isMut: true,
69
+ isSigner: false,
70
+ },
71
+ {
72
+ name: 'accountCompressionProgram',
73
+ isMut: false,
74
+ isSigner: false,
75
+ },
76
+ {
77
+ name: 'cpiSignatureAccount',
78
+ isMut: false,
79
+ isSigner: false,
80
+ isOptional: true,
81
+ },
82
+ {
83
+ name: 'invokingProgram',
84
+ isMut: false,
85
+ isSigner: false,
86
+ isOptional: true,
87
+ },
88
+ {
89
+ name: 'compressedSolPda',
90
+ isMut: true,
91
+ isSigner: false,
92
+ isOptional: true,
93
+ },
94
+ {
95
+ name: 'compressionRecipient',
96
+ isMut: true,
97
+ isSigner: false,
98
+ isOptional: true,
99
+ },
100
+ {
101
+ name: 'systemProgram',
102
+ isMut: false,
103
+ isSigner: false,
104
+ isOptional: true,
105
+ },
106
+ ],
107
+ args: [
108
+ {
109
+ name: 'inputs',
110
+ type: 'bytes',
111
+ },
112
+ ],
113
+ returns: {
114
+ defined: 'crate::event::PublicTransactionEvent',
115
+ },
116
+ },
117
+ ],
118
+ accounts: [
119
+ {
120
+ name: 'cpiSignatureAccount',
121
+ docs: [
122
+ 'collects invocations without proofs',
123
+ 'invocations are collected and processed when an invocation with a proof is received',
124
+ ],
125
+ type: {
126
+ kind: 'struct',
127
+ fields: [
128
+ {
129
+ name: 'slot',
130
+ type: 'u64',
131
+ },
132
+ {
133
+ name: 'signatures',
134
+ type: {
135
+ vec: {
136
+ defined: 'InstructionDataTransfer',
137
+ },
138
+ },
139
+ },
140
+ ],
141
+ },
142
+ },
143
+ {
144
+ name: 'compressedSolPda',
145
+ type: {
146
+ kind: 'struct',
147
+ fields: [],
148
+ },
149
+ },
150
+ ],
151
+ types: [
152
+ {
153
+ name: 'CompressedAccountWithMerkleContext',
154
+ type: {
155
+ kind: 'struct',
156
+ fields: [
157
+ {
158
+ name: 'compressedAccount',
159
+ type: {
160
+ defined: 'CompressedAccount',
161
+ },
162
+ },
163
+ {
164
+ name: 'merkleTreePubkeyIndex',
165
+ type: 'u8',
166
+ },
167
+ {
168
+ name: 'nullifierQueuePubkeyIndex',
169
+ type: 'u8',
170
+ },
171
+ {
172
+ name: 'leafIndex',
173
+ type: 'u32',
174
+ },
175
+ ],
176
+ },
177
+ },
178
+ {
179
+ name: 'CompressedAccount',
180
+ type: {
181
+ kind: 'struct',
182
+ fields: [
183
+ {
184
+ name: 'owner',
185
+ type: 'publicKey',
186
+ },
187
+ {
188
+ name: 'lamports',
189
+ type: 'u64',
190
+ },
191
+ {
192
+ name: 'address',
193
+ type: {
194
+ option: {
195
+ array: ['u8', 32],
196
+ },
197
+ },
198
+ },
199
+ {
200
+ name: 'data',
201
+ type: {
202
+ option: {
203
+ defined: 'CompressedAccountData',
204
+ },
205
+ },
206
+ },
207
+ ],
208
+ },
209
+ },
210
+ {
211
+ name: 'CompressedAccountData',
212
+ type: {
213
+ kind: 'struct',
214
+ fields: [
215
+ {
216
+ name: 'discriminator',
217
+ type: {
218
+ array: ['u8', 8],
219
+ },
220
+ },
221
+ {
222
+ name: 'data',
223
+ type: 'bytes',
224
+ },
225
+ {
226
+ name: 'dataHash',
227
+ type: {
228
+ array: ['u8', 32],
229
+ },
230
+ },
231
+ ],
232
+ },
233
+ },
234
+ {
235
+ name: 'PublicTransactionEvent',
236
+ type: {
237
+ kind: 'struct',
238
+ fields: [
239
+ {
240
+ name: 'inputCompressedAccountHashes',
241
+ type: {
242
+ vec: {
243
+ array: ['u8', 32],
244
+ },
245
+ },
246
+ },
247
+ {
248
+ name: 'outputCompressedAccountHashes',
249
+ type: {
250
+ vec: {
251
+ array: ['u8', 32],
252
+ },
253
+ },
254
+ },
255
+ {
256
+ name: 'inputCompressedAccounts',
257
+ type: {
258
+ vec: {
259
+ defined: 'CompressedAccountWithMerkleContext',
260
+ },
261
+ },
262
+ },
263
+ {
264
+ name: 'outputCompressedAccounts',
265
+ type: {
266
+ vec: {
267
+ defined: 'CompressedAccount',
268
+ },
269
+ },
270
+ },
271
+ {
272
+ name: 'outputStateMerkleTreeAccountIndices',
273
+ type: 'bytes',
274
+ },
275
+ {
276
+ name: 'outputLeafIndices',
277
+ type: {
278
+ vec: 'u32',
279
+ },
280
+ },
281
+ {
282
+ name: 'relayFee',
283
+ type: {
284
+ option: 'u64',
285
+ },
286
+ },
287
+ {
288
+ name: 'isCompress',
289
+ type: 'bool',
290
+ },
291
+ {
292
+ name: 'compressionLamports',
293
+ type: {
294
+ option: 'u64',
295
+ },
296
+ },
297
+ {
298
+ name: 'pubkeyArray',
299
+ type: {
300
+ vec: 'publicKey',
301
+ },
302
+ },
303
+ {
304
+ name: 'message',
305
+ type: {
306
+ option: 'bytes',
307
+ },
308
+ },
309
+ ],
310
+ },
311
+ },
312
+ {
313
+ name: 'InstructionDataTransfer',
314
+ type: {
315
+ kind: 'struct',
316
+ fields: [
317
+ {
318
+ name: 'proof',
319
+ type: {
320
+ option: {
321
+ defined: 'CompressedProof',
322
+ },
323
+ },
324
+ },
325
+ {
326
+ name: 'newAddressParams',
327
+ type: {
328
+ vec: {
329
+ defined: 'NewAddressParamsPacked',
330
+ },
331
+ },
332
+ },
333
+ {
334
+ name: 'inputRootIndices',
335
+ type: {
336
+ vec: 'u16',
337
+ },
338
+ },
339
+ {
340
+ name: 'inputCompressedAccountsWithMerkleContext',
341
+ type: {
342
+ vec: {
343
+ defined: 'CompressedAccountWithMerkleContext',
344
+ },
345
+ },
346
+ },
347
+ {
348
+ name: 'outputCompressedAccounts',
349
+ type: {
350
+ vec: {
351
+ defined: 'CompressedAccount',
352
+ },
353
+ },
354
+ },
355
+ {
356
+ name: 'outputStateMerkleTreeAccountIndices',
357
+ docs: [
358
+ 'The indices of the accounts in the output state merkle tree.',
359
+ ],
360
+ type: 'bytes',
361
+ },
362
+ {
363
+ name: 'relayFee',
364
+ type: {
365
+ option: 'u64',
366
+ },
367
+ },
368
+ {
369
+ name: 'compressionLamports',
370
+ type: {
371
+ option: 'u64',
372
+ },
373
+ },
374
+ {
375
+ name: 'isCompress',
376
+ type: 'bool',
377
+ },
378
+ ],
379
+ },
380
+ },
381
+ {
382
+ name: 'NewAddressParamsPacked',
383
+ type: {
384
+ kind: 'struct',
385
+ fields: [
386
+ {
387
+ name: 'seed',
388
+ type: {
389
+ array: ['u8', 32],
390
+ },
391
+ },
392
+ {
393
+ name: 'addressQueueAccountIndex',
394
+ type: 'u8',
395
+ },
396
+ {
397
+ name: 'addressMerkleTreeAccountIndex',
398
+ type: 'u8',
399
+ },
400
+ {
401
+ name: 'addressMerkleTreeRootIndex',
402
+ type: 'u16',
403
+ },
404
+ ],
405
+ },
406
+ },
407
+ {
408
+ name: 'NewAddressParams',
409
+ type: {
410
+ kind: 'struct',
411
+ fields: [
412
+ {
413
+ name: 'seed',
414
+ type: {
415
+ array: ['u8', 32],
416
+ },
417
+ },
418
+ {
419
+ name: 'addressQueuePubkey',
420
+ type: 'publicKey',
421
+ },
422
+ {
423
+ name: 'addressMerkleTreePubkey',
424
+ type: 'publicKey',
425
+ },
426
+ {
427
+ name: 'addressMerkleTreeRootIndex',
428
+ type: 'u16',
429
+ },
430
+ ],
431
+ },
432
+ },
433
+ {
434
+ name: 'CompressedProof',
435
+ type: {
436
+ kind: 'struct',
437
+ fields: [
438
+ {
439
+ name: 'a',
440
+ type: {
441
+ array: ['u8', 32],
442
+ },
443
+ },
444
+ {
445
+ name: 'b',
446
+ type: {
447
+ array: ['u8', 64],
448
+ },
449
+ },
450
+ {
451
+ name: 'c',
452
+ type: {
453
+ array: ['u8', 32],
454
+ },
455
+ },
456
+ ],
457
+ },
458
+ },
459
+ ],
460
+ errors: [
461
+ {
462
+ code: 6000,
463
+ name: 'SumCheckFailed',
464
+ msg: 'Sum check failed',
465
+ },
466
+ {
467
+ code: 6001,
468
+ name: 'SignerCheckFailed',
469
+ msg: 'Signer check failed',
470
+ },
471
+ {
472
+ code: 6002,
473
+ name: 'CpiSignerCheckFailed',
474
+ msg: 'Cpi signer check failed',
475
+ },
476
+ {
477
+ code: 6003,
478
+ name: 'ComputeInputSumFailed',
479
+ msg: 'Computing input sum failed.',
480
+ },
481
+ {
482
+ code: 6004,
483
+ name: 'ComputeOutputSumFailed',
484
+ msg: 'Computing output sum failed.',
485
+ },
486
+ {
487
+ code: 6005,
488
+ name: 'ComputeRpcSumFailed',
489
+ msg: 'Computing rpc sum failed.',
490
+ },
491
+ {
492
+ code: 6006,
493
+ name: 'InUtxosAlreadyAdded',
494
+ msg: 'InUtxosAlreadyAdded',
495
+ },
496
+ {
497
+ code: 6007,
498
+ name: 'NumberOfLeavesMissmatch',
499
+ msg: 'NumberOfLeavesMissmatch',
500
+ },
501
+ {
502
+ code: 6008,
503
+ name: 'MerkleTreePubkeysMissmatch',
504
+ msg: 'MerkleTreePubkeysMissmatch',
505
+ },
506
+ {
507
+ code: 6009,
508
+ name: 'NullifierArrayPubkeysMissmatch',
509
+ msg: 'NullifierArrayPubkeysMissmatch',
510
+ },
511
+ {
512
+ code: 6010,
513
+ name: 'InvalidNoopPubkey',
514
+ msg: 'InvalidNoopPubkey',
515
+ },
516
+ {
517
+ code: 6011,
518
+ name: 'InvalidPublicInputsLength',
519
+ msg: 'InvalidPublicInputsLength',
520
+ },
521
+ {
522
+ code: 6012,
523
+ name: 'DecompressG1Failed',
524
+ msg: 'Decompress G1 Failed',
525
+ },
526
+ {
527
+ code: 6013,
528
+ name: 'DecompressG2Failed',
529
+ msg: 'Decompress G2 Failed',
530
+ },
531
+ {
532
+ code: 6014,
533
+ name: 'CreateGroth16VerifierFailed',
534
+ msg: 'CreateGroth16VerifierFailed',
535
+ },
536
+ {
537
+ code: 6015,
538
+ name: 'ProofVerificationFailed',
539
+ msg: 'ProofVerificationFailed',
540
+ },
541
+ {
542
+ code: 6016,
543
+ name: 'PublicInputsTryIntoFailed',
544
+ msg: 'PublicInputsTryIntoFailed',
545
+ },
546
+ {
547
+ code: 6017,
548
+ name: 'CompressedAccountHashError',
549
+ msg: 'CompressedAccountHashError',
550
+ },
551
+ {
552
+ code: 6018,
553
+ name: 'InvalidAddress',
554
+ msg: 'InvalidAddress',
555
+ },
556
+ {
557
+ code: 6019,
558
+ name: 'InvalidAddressQueue',
559
+ msg: 'InvalidAddressQueue',
560
+ },
561
+ {
562
+ code: 6020,
563
+ name: 'InvalidNullifierQueue',
564
+ msg: 'InvalidNullifierQueue',
565
+ },
566
+ {
567
+ code: 6021,
568
+ name: 'DeriveAddressError',
569
+ msg: 'DeriveAddressError',
570
+ },
571
+ {
572
+ code: 6022,
573
+ name: 'CompressSolTransferFailed',
574
+ msg: 'CompressSolTransferFailed',
575
+ },
576
+ {
577
+ code: 6023,
578
+ name: 'CompressedSolPdaUndefinedForCompressSol',
579
+ msg: 'CompressedSolPdaUndefinedForCompressSol',
580
+ },
581
+ {
582
+ code: 6024,
583
+ name: 'DeCompressLamportsUndefinedForCompressSol',
584
+ msg: 'DeCompressLamportsUndefinedForCompressSol',
585
+ },
586
+ {
587
+ code: 6025,
588
+ name: 'CompressedSolPdaUndefinedForDecompressSol',
589
+ msg: 'CompressedSolPdaUndefinedForDecompressSol',
590
+ },
591
+ {
592
+ code: 6026,
593
+ name: 'DeCompressLamportsUndefinedForDecompressSol',
594
+ msg: 'DeCompressLamportsUndefinedForDecompressSol',
595
+ },
596
+ {
597
+ code: 6027,
598
+ name: 'DecompressRecipientUndefinedForDecompressSol',
599
+ msg: 'DecompressRecipientUndefinedForDecompressSol',
600
+ },
601
+ {
602
+ code: 6028,
603
+ name: 'LengthMismatch',
604
+ msg: 'LengthMismatch',
605
+ },
606
+ {
607
+ code: 6029,
608
+ name: 'DelegateUndefined',
609
+ msg: 'DelegateUndefined while delegated amount is defined',
610
+ },
611
+ ],
612
+ };
613
+
614
+ /// TODO: extract wallet into its own npm package
615
+ /// Mock Solana web3 library
616
+ class Wallet {
617
+ constructor(keypair, url, commitment) {
618
+ this.signTransaction = async (tx) => {
619
+ await tx.sign([this._keypair]);
620
+ return tx;
621
+ };
622
+ this.sendTransaction = async (transaction) => {
623
+ const signature = await this._connection.sendTransaction(transaction);
624
+ return signature;
625
+ };
626
+ this.signAllTransactions = async (transactions) => {
627
+ const signedTxs = await Promise.all(transactions.map(async (tx) => {
628
+ return await this.signTransaction(tx);
629
+ }));
630
+ return signedTxs;
631
+ };
632
+ this.signMessage = async (message) => {
633
+ return tweetnacl.sign.detached(message, this._keypair.secretKey);
634
+ };
635
+ this.sendAndConfirmTransaction = async (transaction, signers = []) => {
636
+ const response = await web3_js.sendAndConfirmTransaction(this._connection, transaction, [this._keypair, ...signers], {
637
+ commitment: this._commitment,
638
+ });
639
+ return response;
640
+ };
641
+ this._publicKey = keypair.publicKey;
642
+ this._keypair = keypair;
643
+ this._connection = new web3_js.Connection(url);
644
+ this._url = url;
645
+ this._commitment = commitment;
646
+ }
647
+ }
648
+
649
+ // // TODO consider adding isNodeWallet
650
+ const useWallet = (keypair, url = 'http://127.0.0.1:8899', commitment = 'confirmed') => {
651
+ url = url !== 'mock' ? url : 'http://127.0.0.1:8899';
652
+ const wallet = new Wallet(keypair, url, commitment);
653
+ return {
654
+ publicKey: wallet._publicKey,
655
+ sendAndConfirmTransaction: wallet.sendAndConfirmTransaction,
656
+ signMessage: wallet.signMessage,
657
+ signTransaction: wallet.signTransaction,
658
+ signAllTransactions: wallet.signAllTransactions,
659
+ sendTransaction: wallet.sendTransaction,
660
+ };
661
+ };
662
+
663
+ const FIELD_SIZE = new anchor.BN('21888242871839275222246405745257275088548364400416034343698204186575808495617');
664
+ // TODO: implement properly
665
+ const noopProgram = 'noopb9bkMVfRPU8AsbpTUg8AQkHtKwMYZiFUjNRtMmV';
666
+ const lightProgram = '5WzvRtu7LABotw1SUEpguJiKU27LRGsiCnF5FH6VV7yP';
667
+ const accountCompressionProgram = // also: merkletree program
668
+ '5QPEJ5zDsVou9FQS3KCauKswM3VwBEBu4dpL9xTqkWwN';
669
+ const getRegisteredProgramPda = () => new web3_js.PublicKey('ytwwVWhQUMoTKdirKmvEW5xCRVr4B2dJZnToiHtE2L2'); // TODO: better labelling. gov authority pda
670
+ const getPspAccountCompressionAuthority = () => web3_js.PublicKey.findProgramAddressSync([
671
+ buffer.Buffer.from('cpi_authority'),
672
+ new web3_js.PublicKey(accountCompressionProgram).toBytes(),
673
+ ], new web3_js.PublicKey(
674
+ // TODO: can add check to ensure its consistent with the idl
675
+ '6UqiSPd2mRCTTwkzhcs1M6DGYsqHWd5jiPueX3LwDMXQ'))[0];
676
+ const defaultStaticAccounts = () => [
677
+ new web3_js.PublicKey(getRegisteredProgramPda()),
678
+ new web3_js.PublicKey(noopProgram),
679
+ new web3_js.PublicKey(accountCompressionProgram),
680
+ new web3_js.PublicKey(getPspAccountCompressionAuthority()),
681
+ ];
682
+ const defaultStaticAccountsStruct = () => {
683
+ return {
684
+ registeredProgramPda: new web3_js.PublicKey(getRegisteredProgramPda()),
685
+ noopProgram: new web3_js.PublicKey(noopProgram),
686
+ accountCompressionProgram: new web3_js.PublicKey(accountCompressionProgram),
687
+ pspAccountCompressionAuthority: new web3_js.PublicKey(getPspAccountCompressionAuthority()),
688
+ cpiSignatureAccount: null,
689
+ };
690
+ };
691
+ const defaultTestStateTreeAccounts = () => {
692
+ return {
693
+ nullifierQueue: new web3_js.PublicKey(nullifierQueuePubkey),
694
+ merkleTree: new web3_js.PublicKey(merkletreePubkey),
695
+ merkleTreeHeight: DEFAULT_MERKLE_TREE_HEIGHT,
696
+ };
697
+ };
698
+ const nullifierQueuePubkey = '44J4oDXpjPAbzHCSc24q7NEiPekss4sAbLd8ka4gd9CZ'; // also called indexed_array
699
+ const merkletreePubkey = '5bdFnXU47QjzGpzHfXnxcEi5WXyxzEAZzd1vrE39bf1W';
700
+ const confirmConfig = {
701
+ commitment: 'confirmed',
702
+ preflightCommitment: 'confirmed',
703
+ };
704
+ const DEFAULT_MERKLE_TREE_HEIGHT = 26;
705
+ const DEFAULT_MERKLE_TREE_ROOTS = 2800;
706
+ /** Threshold (per asset) at which new in-UTXOs get merged, in order to reduce UTXO pool size */
707
+ const UTXO_MERGE_THRESHOLD = 20;
708
+ const UTXO_MERGE_MAXIMUM = 10;
709
+ /**
710
+ * Treshold after which the currently used transaction Merkle tree is switched
711
+ * to the next one
712
+ */
713
+ const TRANSACTION_MERKLE_TREE_ROLLOVER_THRESHOLD = new anchor.BN(Math.floor(2 ** DEFAULT_MERKLE_TREE_HEIGHT * 0.95));
714
+
715
+ // TODO: consider implementing BN254 as wrapper class around _BN mirroring
716
+ // PublicKey this would encapsulate our runtime checks and also enforce
717
+ // typesafety at compile time
718
+ const bn = (number, base, endian) => new anchor.BN(number, base, endian);
719
+ /** Create a bigint instance with <254-bit max size and base58 capabilities */
720
+ const createBN254 = (number, base) => {
721
+ if (base === 'base58') {
722
+ if (typeof number !== 'string')
723
+ throw new Error('Must be a base58 string');
724
+ return createBN254(bytes.bs58.decode(number));
725
+ }
726
+ const bigintNumber = new anchor.BN(number, base);
727
+ return enforceSize(bigintNumber);
728
+ };
729
+ /**
730
+ * Enforces a maximum size of <254 bits for bigint instances. This is necessary
731
+ * for compatibility with zk-SNARKs, where hashes must be less than the field
732
+ * modulus (~2^254).
733
+ */
734
+ function enforceSize(bigintNumber) {
735
+ if (bigintNumber.gte(FIELD_SIZE)) {
736
+ throw new Error('Value is too large. Max <254 bits');
737
+ }
738
+ return bigintNumber;
739
+ }
740
+ /** Convert <254-bit bigint to Base58 string. Fills up to 32 bytes. */
741
+ function encodeBN254toBase58(bigintNumber, pad = 32) {
742
+ let buffer$1 = buffer.Buffer.from(bigintNumber.toString(16), 'hex');
743
+ // Ensure the buffer is 32 bytes. If not, pad it with leading zeros.
744
+ if (buffer$1.length < pad) {
745
+ const padding = buffer.Buffer.alloc(pad - buffer$1.length);
746
+ buffer$1 = buffer.Buffer.concat([padding, buffer$1], pad);
747
+ }
748
+ return bytes.bs58.encode(buffer$1);
749
+ }
750
+ /** Convert Base58 string to <254-bit Solana Public key*/
751
+ function bigint254ToPublicKey(bigintNumber) {
752
+ const paddedBase58 = encodeBN254toBase58(bigintNumber);
753
+ return new web3_js.PublicKey(paddedBase58);
754
+ }
755
+ // FIXME: assumes <254 bit pubkey. just use consistent type (pubkey254)
756
+ /** Convert Solana Public key to <254-bit bigint */
757
+ function PublicKeyToBN254(publicKey) {
758
+ const buffer = publicKey.toBuffer();
759
+ // Remove leading zeros from the buffer
760
+ const trimmedBuffer = buffer.subarray(buffer.findIndex(byte => byte !== 0));
761
+ return createBN254(trimmedBuffer);
762
+ }
763
+ //@ts-ignore
764
+ if (undefined) {
765
+ //@ts-ignore
766
+ const { it, expect, describe } = undefined;
767
+ describe('createBN254 function', () => {
768
+ it('should create a BN254 from a string', () => {
769
+ const bigint = createBN254('100');
770
+ expect(bigint.toNumber()).toBe(100);
771
+ });
772
+ it('should create a BN254 from a number', () => {
773
+ const bigint = createBN254(100);
774
+ expect(bigint.toNumber()).toBe(100);
775
+ });
776
+ it('should create a BN254 from a bigint', () => {
777
+ const bigint = createBN254(bn(100));
778
+ expect(bigint.toNumber()).toBe(100);
779
+ });
780
+ it('should create a BN254 from a Buffer', () => {
781
+ const bigint = createBN254(buffer.Buffer.from([100]));
782
+ expect(bigint.toNumber()).toBe(100);
783
+ });
784
+ it('should create a BN254 from a Uint8Array', () => {
785
+ const bigint = createBN254(new Uint8Array([100]));
786
+ expect(bigint.toNumber()).toBe(100);
787
+ });
788
+ it('should create a BN254 from a number[]', () => {
789
+ const bigint = createBN254([100]);
790
+ expect(bigint.toNumber()).toBe(100);
791
+ });
792
+ it('should create a BN254 from a base58 string', () => {
793
+ const bigint = createBN254('2j', 'base58');
794
+ expect(bigint.toNumber()).toBe(bn(100).toNumber());
795
+ });
796
+ });
797
+ describe('encodeBN254toBase58 function', () => {
798
+ it('should convert a BN254 to a base58 string, no pad', () => {
799
+ const bigint = createBN254('100');
800
+ const base58 = encodeBN254toBase58(bigint, 0);
801
+ expect(base58).toBe('2j');
802
+ });
803
+ it('should convert a BN254 to a base58 string, with pad', () => {
804
+ const bigint = createBN254('100');
805
+ const base58 = encodeBN254toBase58(bigint);
806
+ expect(base58).toBe('11111111111111111111111111111112j');
807
+ });
808
+ it('should throw an error for a value that is too large', () => {
809
+ expect(() => createBN254(FIELD_SIZE)).toThrow('Value is too large. Max <254 bits');
810
+ });
811
+ });
812
+ describe('bigint254ToPublicKey function', () => {
813
+ it('should convert a BN254 to a PublicKey', () => {
814
+ const bigint = createBN254('100');
815
+ const publicKey = bigint254ToPublicKey(bigint);
816
+ expect(publicKey).toBeInstanceOf(web3_js.PublicKey);
817
+ });
818
+ });
819
+ describe('PublicKeyToBigint254 function', () => {
820
+ it('should convert a PublicKey to a BN254', () => {
821
+ const publicKey = web3_js.PublicKey.unique();
822
+ const bigint = PublicKeyToBN254(publicKey);
823
+ expect(bigint).toBeInstanceOf(anchor.BN);
824
+ });
825
+ });
826
+ }
827
+
828
+ const createCompressedAccount = (owner, lamports, data, address) => ({
829
+ owner,
830
+ lamports: lamports !== null && lamports !== void 0 ? lamports : bn(0),
831
+ address: address !== null && address !== void 0 ? address : null,
832
+ data: data !== null && data !== void 0 ? data : null,
833
+ });
834
+ const createCompressedAccountWithMerkleContext = (merkleContext, owner, lamports, data, address) => (Object.assign(Object.assign({}, createCompressedAccount(owner, lamports, data, address)), merkleContext));
835
+ const createMerkleContext = (merkleTree, nullifierQueue, hash, // TODO: BN254,
836
+ leafIndex) => ({
837
+ merkleTree,
838
+ nullifierQueue,
839
+ hash,
840
+ leafIndex,
841
+ });
842
+ //@ts-ignore
843
+ if (undefined) {
844
+ //@ts-ignore
845
+ const { it, expect, describe } = undefined;
846
+ describe('createCompressedAccount function', () => {
847
+ it('should create a compressed account with default values', () => {
848
+ const owner = web3_js.PublicKey.unique();
849
+ const account = createCompressedAccount(owner);
850
+ expect(account).toEqual({
851
+ owner,
852
+ lamports: bn(0),
853
+ address: null,
854
+ data: null,
855
+ });
856
+ });
857
+ it('should create a compressed account with provided values', () => {
858
+ const owner = web3_js.PublicKey.unique();
859
+ const lamports = bn(100);
860
+ const data = {
861
+ discriminator: [0],
862
+ data: Buffer.from(new Uint8Array([1, 2, 3])),
863
+ dataHash: [0],
864
+ };
865
+ const address = web3_js.PublicKey.unique();
866
+ const account = createCompressedAccount(owner, lamports, data, address);
867
+ expect(account).toEqual({
868
+ owner,
869
+ lamports,
870
+ address,
871
+ data,
872
+ });
873
+ });
874
+ });
875
+ describe('createCompressedAccountWithMerkleContext function', () => {
876
+ it('should create a compressed account with merkle context', () => {
877
+ const owner = web3_js.PublicKey.unique();
878
+ const merkleTree = web3_js.PublicKey.unique();
879
+ const nullifierQueue = web3_js.PublicKey.unique();
880
+ const hash = new Array(32).fill(1);
881
+ const leafIndex = 0;
882
+ const merkleContext = createMerkleContext(merkleTree, nullifierQueue, hash, leafIndex);
883
+ const accountWithMerkleContext = createCompressedAccountWithMerkleContext(merkleContext, owner);
884
+ expect(accountWithMerkleContext).toEqual({
885
+ owner,
886
+ lamports: bn(0),
887
+ address: null,
888
+ data: null,
889
+ merkleTree,
890
+ nullifierQueue,
891
+ hash,
892
+ leafIndex,
893
+ });
894
+ });
895
+ });
896
+ describe('createMerkleContext function', () => {
897
+ it('should create a merkle context', () => {
898
+ const merkleTree = web3_js.PublicKey.unique();
899
+ const nullifierQueue = web3_js.PublicKey.unique();
900
+ const hash = new Array(32).fill(1);
901
+ const leafIndex = 0;
902
+ const merkleContext = createMerkleContext(merkleTree, nullifierQueue, hash, leafIndex);
903
+ expect(merkleContext).toEqual({
904
+ merkleTree,
905
+ nullifierQueue,
906
+ hash,
907
+ leafIndex,
908
+ });
909
+ });
910
+ });
911
+ }
912
+
913
+ function byteArrayToKeypair(byteArray) {
914
+ return web3_js.Keypair.fromSecretKey(Uint8Array.from(byteArray));
915
+ }
916
+ const toArray = (value) => Array.isArray(value) ? value : [value];
917
+ const bufToDecStr = (buf) => {
918
+ return createBN254(buf).toString();
919
+ };
920
+ function isSmallerThanBn254FieldSizeLe(bytes) {
921
+ const bigint = bn(bytes, undefined, 'le');
922
+ return bigint.lt(FIELD_SIZE);
923
+ }
924
+ async function hashToBn254FieldSizeLe(bytes) {
925
+ let bumpSeed = 255;
926
+ while (bumpSeed >= 0) {
927
+ const inputWithBumpSeed = buffer.Buffer.concat([
928
+ bytes,
929
+ buffer.Buffer.from([bumpSeed]),
930
+ ]);
931
+ const hash = sha3.keccak_256(inputWithBumpSeed);
932
+ if (hash.length !== 32) {
933
+ throw new Error('Invalid hash length');
934
+ }
935
+ hash[0] = 0;
936
+ hash[1] = 0;
937
+ if (isSmallerThanBn254FieldSizeLe(buffer.Buffer.from(hash))) {
938
+ return [buffer.Buffer.from(hash), bumpSeed];
939
+ }
940
+ bumpSeed -= 1;
941
+ }
942
+ return null;
943
+ }
944
+ /** Mutates array in place */
945
+ function pushUniqueItems(items, map) {
946
+ items.forEach(item => {
947
+ if (!map.includes(item)) {
948
+ map.push(item);
949
+ }
950
+ });
951
+ }
952
+ function toCamelCase(obj) {
953
+ if (Array.isArray(obj)) {
954
+ return obj.map(v => toCamelCase(v));
955
+ }
956
+ else if (obj !== null && obj.constructor === Object) {
957
+ return Object.keys(obj).reduce((result, key) => {
958
+ const camelCaseKey = key.replace(/([-_][a-z])/gi, $1 => {
959
+ return $1.toUpperCase().replace('-', '').replace('_', '');
960
+ });
961
+ result[camelCaseKey] = toCamelCase(obj[key]);
962
+ return result;
963
+ }, {});
964
+ }
965
+ return obj;
966
+ }
967
+ // FIXME: check bundling and how to resolve the type error
968
+ //@ts-ignore
969
+ if (undefined) {
970
+ //@ts-ignore
971
+ const { it, expect, describe } = undefined;
972
+ describe('toArray function', () => {
973
+ it('should convert a single item to an array', () => {
974
+ expect(toArray(1)).toEqual([1]);
975
+ });
976
+ it('should leave an array unchanged', () => {
977
+ expect(toArray([1, 2, 3])).toEqual([1, 2, 3]);
978
+ });
979
+ });
980
+ describe('isSmallerThanBn254FieldSizeLe function', () => {
981
+ it('should return true for a small number', () => {
982
+ const buf = buffer.Buffer.from('0000000000000000000000000000000000000000000000000000000000000000', 'hex');
983
+ expect(isSmallerThanBn254FieldSizeLe(buf)).toBe(true);
984
+ });
985
+ it('should return false for a large number', () => {
986
+ const buf = buffer.Buffer.from('6500000000000000000000000000000000000000000000000000000000000000', 'hex').reverse();
987
+ expect(isSmallerThanBn254FieldSizeLe(buf)).toBe(false);
988
+ });
989
+ });
990
+ describe('hashToBn254FieldSizeLe function', () => {
991
+ const bytes = [
992
+ 131, 219, 249, 246, 221, 196, 33, 3, 114, 23, 121, 235, 18, 229, 71,
993
+ 152, 39, 87, 169, 208, 143, 101, 43, 128, 245, 59, 22, 134, 182,
994
+ 231, 116, 33,
995
+ ];
996
+ const refResult = [
997
+ 0, 0, 138, 224, 71, 10, 16, 226, 30, 104, 100, 251, 232, 59, 50,
998
+ 168, 21, 78, 218, 191, 159, 16, 119, 17, 30, 55, 194, 230, 138, 128,
999
+ 18, 44,
1000
+ ];
1001
+ it('should return a valid value for initial buffer', async () => {
1002
+ const result = await hashToBn254FieldSizeLe(buffer.Buffer.from(bytes));
1003
+ expect(Array.from(result[0])).toEqual(refResult);
1004
+ });
1005
+ it('should return a valid value for initial buffer', async () => {
1006
+ const buf = buffer.Buffer.from('0000000000000000000000000000000000000000000000000000000000000000', 'hex');
1007
+ const result = await hashToBn254FieldSizeLe(buf);
1008
+ expect(result).not.toBeNull();
1009
+ if (result) {
1010
+ expect(result[0]).toBeInstanceOf(buffer.Buffer);
1011
+ expect(result[1]).toBe(254);
1012
+ }
1013
+ });
1014
+ it('should return a valid value for a buffer that can be hashed to a smaller value', async () => {
1015
+ const buf = buffer.Buffer.from('fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe', 'hex');
1016
+ const result = await hashToBn254FieldSizeLe(buf);
1017
+ expect(result).not.toBeNull();
1018
+ if (result) {
1019
+ expect(result[1]).toBeLessThanOrEqual(255);
1020
+ expect(result[0]).toBeInstanceOf(buffer.Buffer);
1021
+ // Check if the hashed value is indeed smaller than the bn254 field size
1022
+ expect(isSmallerThanBn254FieldSizeLe(result[0])).toBe(true);
1023
+ }
1024
+ });
1025
+ it('should correctly hash the input buffer', async () => {
1026
+ const buf = buffer.Buffer.from('deadbeef', 'hex');
1027
+ const result = await hashToBn254FieldSizeLe(buf);
1028
+ expect(result).not.toBeNull();
1029
+ if (result) {
1030
+ // Since the actual hash value depends on the crypto implementation and input,
1031
+ // we cannot predict the exact output. However, we can check if the output is valid.
1032
+ expect(result[0].length).toBe(32); // SHA-256 hash length
1033
+ expect(result[1]).toBeLessThanOrEqual(255);
1034
+ expect(isSmallerThanBn254FieldSizeLe(result[0])).toBe(true);
1035
+ }
1036
+ });
1037
+ });
1038
+ describe('pushUniqueItems function', () => {
1039
+ it('should add unique items', () => {
1040
+ const map = [1, 2, 3];
1041
+ const itemsToAdd = [3, 4, 5];
1042
+ pushUniqueItems(itemsToAdd, map);
1043
+ expect(map).toEqual([1, 2, 3, 4, 5]);
1044
+ });
1045
+ it('should ignore duplicates', () => {
1046
+ const map = [1, 2, 3];
1047
+ const itemsToAdd = [1, 2, 3];
1048
+ pushUniqueItems(itemsToAdd, map);
1049
+ expect(map).toEqual([1, 2, 3]);
1050
+ });
1051
+ it('should handle empty arrays', () => {
1052
+ const map = [];
1053
+ const itemsToAdd = [];
1054
+ pushUniqueItems(itemsToAdd, map);
1055
+ expect(map).toEqual([]);
1056
+ });
1057
+ });
1058
+ describe('bufToDecStr', () => {
1059
+ it("should convert buffer [0] to '0'", () => {
1060
+ expect(bufToDecStr(buffer.Buffer.from([0]))).toEqual('0');
1061
+ });
1062
+ it("should convert buffer [1] to '1'", () => {
1063
+ expect(bufToDecStr(buffer.Buffer.from([1]))).toEqual('1');
1064
+ });
1065
+ it("should convert buffer [1, 0] to '256'", () => {
1066
+ expect(bufToDecStr(buffer.Buffer.from([1, 0]))).toEqual('256');
1067
+ });
1068
+ it("should convert buffer [1, 1] to '257'", () => {
1069
+ expect(bufToDecStr(buffer.Buffer.from([1, 1]))).toEqual('257');
1070
+ });
1071
+ it("should convert buffer [7, 91, 205, 21] to '123456789'", () => {
1072
+ expect(bufToDecStr(buffer.Buffer.from([7, 91, 205, 21]))).toEqual('123456789');
1073
+ });
1074
+ });
1075
+ describe('toCamelCase', () => {
1076
+ it('should convert object keys to camelCase', () => {
1077
+ const input = { test_key: 1, 'another-testKey': 2 };
1078
+ const expected = { testKey: 1, anotherTestKey: 2 };
1079
+ expect(toCamelCase(input)).toEqual(expected);
1080
+ });
1081
+ it('should handle arrays of objects', () => {
1082
+ const input = [{ array_key: 3 }, { 'another_array-key': 4 }];
1083
+ const expected = [{ arrayKey: 3 }, { anotherArrayKey: 4 }];
1084
+ expect(toCamelCase(input)).toEqual(expected);
1085
+ });
1086
+ it('should return the input if it is neither an object nor an array', () => {
1087
+ const input = 'testString';
1088
+ expect(toCamelCase(input)).toBe(input);
1089
+ });
1090
+ });
1091
+ }
1092
+
1093
+ /** pipe function */
1094
+ function pipe(initialFunction, ...functions) {
1095
+ return (initialValue) => functions.reduce((currentValue, currentFunction) => currentFunction(currentValue), initialFunction(initialValue));
1096
+ }
1097
+ //@ts-ignore
1098
+ if (undefined) {
1099
+ //@ts-ignore
1100
+ const { it, expect, describe } = undefined;
1101
+ describe('pipe', () => {
1102
+ it('should return the result of applying all fns to the initial value', () => {
1103
+ const addOne = (x) => x + 1;
1104
+ const multiplyByTwo = (x) => x * 2;
1105
+ const subtractThree = (x) => x - 3;
1106
+ const addOneMultiplyByTwoSubtractThree = pipe(addOne, multiplyByTwo, subtractThree);
1107
+ expect(addOneMultiplyByTwoSubtractThree(5)).toBe(9);
1108
+ });
1109
+ });
1110
+ }
1111
+
1112
+ /** Sends a versioned transaction and confirms it. */
1113
+ async function sendAndConfirmTx(rpc, tx, confirmOptions) {
1114
+ const txId = await rpc.sendTransaction(tx, confirmOptions);
1115
+ const { blockhash, lastValidBlockHeight } = await rpc.getLatestBlockhash(confirmOptions === null || confirmOptions === void 0 ? void 0 : confirmOptions.commitment);
1116
+ const transactionConfirmationStrategy0 = {
1117
+ signature: txId,
1118
+ blockhash,
1119
+ lastValidBlockHeight,
1120
+ };
1121
+ await rpc.confirmTransaction(transactionConfirmationStrategy0, (confirmOptions === null || confirmOptions === void 0 ? void 0 : confirmOptions.commitment) || rpc.commitment || 'confirmed');
1122
+ return txId;
1123
+ }
1124
+ /** @internal */
1125
+ async function confirmTx(rpc, txId, blockHashCtx) {
1126
+ if (!blockHashCtx)
1127
+ blockHashCtx = await rpc.getLatestBlockhash();
1128
+ const transactionConfirmationStrategy = {
1129
+ signature: txId,
1130
+ blockhash: blockHashCtx.blockhash,
1131
+ lastValidBlockHeight: blockHashCtx.lastValidBlockHeight,
1132
+ };
1133
+ const res = await rpc.confirmTransaction(transactionConfirmationStrategy, rpc.commitment || 'confirmed');
1134
+ return res;
1135
+ }
1136
+ /**
1137
+ * Builds a versioned Transaction from instructions and signs it.
1138
+ *
1139
+ * @param instructions instructions to include in the transaction
1140
+ * @param payer payer of the transaction
1141
+ * @param blockhash recent blockhash to use in the transaction
1142
+ * @param additionalSigners non-feepayer signers to include in the transaction
1143
+ */
1144
+ function buildAndSignTx(instructions, payer, blockhash, additionalSigners = []) {
1145
+ if (additionalSigners.includes(payer))
1146
+ throw new Error('payer must not be in additionalSigners');
1147
+ const allSigners = [payer, ...additionalSigners];
1148
+ const messageV0 = new web3_js.TransactionMessage({
1149
+ payerKey: payer.publicKey,
1150
+ recentBlockhash: blockhash,
1151
+ instructions,
1152
+ }).compileToV0Message();
1153
+ const tx = new web3_js.VersionedTransaction(messageV0);
1154
+ tx.sign(allSigners);
1155
+ return tx;
1156
+ }
1157
+
1158
+ // zzz
1159
+ function sleep(ms) {
1160
+ return new Promise(resolve => setTimeout(resolve, ms));
1161
+ }
1162
+
1163
+ async function airdropSol({ connection, lamports, recipientPublicKey, }) {
1164
+ const txHash = await connection.requestAirdrop(recipientPublicKey, lamports);
1165
+ await confirmTransaction(connection, txHash);
1166
+ return txHash;
1167
+ }
1168
+ async function confirmTransaction(connection, signature, confirmation = 'confirmed') {
1169
+ const latestBlockHash = await connection.getLatestBlockhash(confirmation);
1170
+ const strategy = {
1171
+ signature: signature.toString(),
1172
+ lastValidBlockHeight: latestBlockHash.lastValidBlockHeight,
1173
+ blockhash: latestBlockHash.blockhash,
1174
+ };
1175
+ return await connection.confirmTransaction(strategy, confirmation);
1176
+ }
1177
+
1178
+ const validateSufficientBalance = (balance) => {
1179
+ if (balance.lt(bn(0))) {
1180
+ throw new Error('Not enough balance for transfer');
1181
+ }
1182
+ };
1183
+ const validateSameOwner = (compressedAccounts) => {
1184
+ if (compressedAccounts.length === 0) {
1185
+ throw new Error('No accounts provided for validation');
1186
+ }
1187
+ const zerothOwner = compressedAccounts[0].owner;
1188
+ if (!compressedAccounts.every(account => account.owner.equals(zerothOwner))) {
1189
+ throw new Error('All input accounts must have the same owner');
1190
+ }
1191
+ };
1192
+
1193
+ /**
1194
+ * @internal Finds the index of a PublicKey in an array, or adds it if not
1195
+ * present
1196
+ * */
1197
+ function getIndexOrAdd(accountsArray, key) {
1198
+ const index = accountsArray.findIndex(existingKey => existingKey.equals(key));
1199
+ if (index === -1) {
1200
+ accountsArray.push(key);
1201
+ return accountsArray.length - 1;
1202
+ }
1203
+ return index;
1204
+ }
1205
+ /** @internal */
1206
+ function padOutputStateMerkleTrees(outputStateMerkleTrees, numberOfOutputCompressedAccounts, inputCompressedAccountsWithMerkleContext) {
1207
+ if (numberOfOutputCompressedAccounts <= 0) {
1208
+ return [];
1209
+ }
1210
+ /// Default: use the 0th state tree of input state for all output accounts
1211
+ if (outputStateMerkleTrees === undefined) {
1212
+ if (inputCompressedAccountsWithMerkleContext.length === 0) {
1213
+ throw new Error('inputCompressedAccountsWithMerkleContext cannot be empty when outputStateMerkleTrees is undefined');
1214
+ }
1215
+ return new Array(numberOfOutputCompressedAccounts).fill(inputCompressedAccountsWithMerkleContext[0].merkleTree);
1216
+ /// Align the number of output state trees with the number of output
1217
+ /// accounts, and fill up with 0th output state tree
1218
+ }
1219
+ else {
1220
+ /// Into array
1221
+ const treesArray = toArray(outputStateMerkleTrees);
1222
+ if (treesArray.length >= numberOfOutputCompressedAccounts) {
1223
+ return treesArray.slice(0, numberOfOutputCompressedAccounts);
1224
+ }
1225
+ else {
1226
+ return treesArray.concat(new Array(numberOfOutputCompressedAccounts - treesArray.length).fill(treesArray[0]));
1227
+ }
1228
+ }
1229
+ }
1230
+ // TODO: include owner and lamports in packing.
1231
+ /**
1232
+ * Packs Compressed Accounts.
1233
+ *
1234
+ * Replaces PublicKey with index pointer to remaining accounts.
1235
+ *
1236
+ * @param inputCompressedAccounts ix input state to be consumed
1237
+ * @param numberOfOutputCompressedAccounts ix ouput state to be created
1238
+ * @param outputStateMerkleTrees State trees that the output should
1239
+ * be inserted into. Defaults to the
1240
+ * 0th state tree of the input state.
1241
+ * Gets padded to the length of
1242
+ * outputCompressedAccounts.
1243
+ * @param remainingAccounts Optional existing array of accounts
1244
+ * to append to.
1245
+ **/
1246
+ function packCompressedAccounts(inputCompressedAccounts, numberOfOutputCompressedAccounts, outputStateMerkleTrees, remainingAccounts = []) {
1247
+ const _remainingAccounts = remainingAccounts.slice();
1248
+ const packedInputCompressedAccounts = [];
1249
+ /// input
1250
+ inputCompressedAccounts.forEach(account => {
1251
+ const merkleTreePubkeyIndex = getIndexOrAdd(_remainingAccounts, account.merkleTree);
1252
+ const nullifierQueuePubkeyIndex = getIndexOrAdd(_remainingAccounts, account.nullifierQueue);
1253
+ packedInputCompressedAccounts.push({
1254
+ compressedAccount: {
1255
+ owner: account.owner,
1256
+ lamports: account.lamports,
1257
+ address: account.address,
1258
+ data: account.data,
1259
+ },
1260
+ merkleTreePubkeyIndex,
1261
+ nullifierQueuePubkeyIndex,
1262
+ leafIndex: account.leafIndex,
1263
+ });
1264
+ });
1265
+ /// output
1266
+ const paddedOutputStateMerkleTrees = padOutputStateMerkleTrees(outputStateMerkleTrees, numberOfOutputCompressedAccounts, inputCompressedAccounts);
1267
+ const outputStateMerkleTreeIndices = [];
1268
+ paddedOutputStateMerkleTrees.forEach(account => {
1269
+ const indexMerkleTree = getIndexOrAdd(_remainingAccounts, account);
1270
+ outputStateMerkleTreeIndices.push(indexMerkleTree);
1271
+ });
1272
+ /// to meta
1273
+ const remainingAccountMetas = _remainingAccounts.map((account) => ({
1274
+ pubkey: account,
1275
+ isWritable: true,
1276
+ isSigner: false,
1277
+ }));
1278
+ return {
1279
+ packedInputCompressedAccounts,
1280
+ outputStateMerkleTreeIndices,
1281
+ remainingAccountMetas,
1282
+ };
1283
+ }
1284
+ //@ts-ignore
1285
+ if (undefined) {
1286
+ //@ts-ignore
1287
+ const { describe, it, expect } = undefined;
1288
+ // Inline unit tests for padOutputStateMerkleTrees function
1289
+ describe('padOutputStateMerkleTrees', () => {
1290
+ const treeA = web3_js.PublicKey.unique();
1291
+ const treeB = web3_js.PublicKey.unique();
1292
+ const treeC = web3_js.PublicKey.unique();
1293
+ const accA = { merkleTree: treeA };
1294
+ const accB = { merkleTree: treeB };
1295
+ it('should use the 0th state tree of input state if no output state trees are provided', () => {
1296
+ const result = padOutputStateMerkleTrees(undefined, 3, [
1297
+ accA,
1298
+ accB,
1299
+ ]);
1300
+ expect(result).toEqual([treeA, treeA, treeA]);
1301
+ });
1302
+ it('should fill up with the first state tree if provided trees are less than required', () => {
1303
+ const result = padOutputStateMerkleTrees([treeA, treeB], 5, []);
1304
+ expect(result).toEqual([treeA, treeB, treeA, treeA, treeA]);
1305
+ });
1306
+ it('should remove extra trees if the number of output state trees is greater than the number of output accounts', () => {
1307
+ const result = padOutputStateMerkleTrees([treeA, treeB, treeC], 2, []);
1308
+ expect(result).toEqual([treeA, treeB]);
1309
+ });
1310
+ it('should return the same outputStateMerkleTrees if its length equals the number of output compressed accounts', () => {
1311
+ const result = padOutputStateMerkleTrees([treeA, treeB, treeC], 3, []);
1312
+ expect(result).toEqual([treeA, treeB, treeC]);
1313
+ });
1314
+ });
1315
+ }
1316
+
1317
+ const parseEvents = (indexerEventsTransactions, deserializeFn) => {
1318
+ const { noopProgram } = defaultStaticAccountsStruct();
1319
+ const transactions = [];
1320
+ indexerEventsTransactions.forEach(tx => {
1321
+ if (!tx ||
1322
+ !tx.meta ||
1323
+ tx.meta.err ||
1324
+ !tx.meta.innerInstructions ||
1325
+ tx.meta.innerInstructions.length <= 0) {
1326
+ return;
1327
+ }
1328
+ /// We only care about the very last inner instruction as it contains the
1329
+ /// PublicTransactionEvent
1330
+ tx.meta.innerInstructions.forEach(ix => {
1331
+ if (ix.instructions.length > 0) {
1332
+ const ixInner = ix.instructions[ix.instructions.length - 1];
1333
+ // Type guard for partially parsed web3js types.
1334
+ if ('data' in ixInner &&
1335
+ ixInner.data &&
1336
+ ixInner.programId.toBase58() === noopProgram.toBase58()) {
1337
+ const data = bytes.bs58.decode(ixInner.data);
1338
+ const decodedEvent = deserializeFn(data, tx);
1339
+ if (decodedEvent !== null && decodedEvent !== undefined) {
1340
+ transactions.push(decodedEvent);
1341
+ }
1342
+ }
1343
+ }
1344
+ });
1345
+ });
1346
+ return transactions;
1347
+ };
1348
+ // TODO: make it type safe. have to reimplement the types from the IDL.
1349
+ const parsePublicTransactionEventWithIdl = (data) => {
1350
+ const numericData = Buffer.from(data.map(byte => byte));
1351
+ try {
1352
+ return LightSystemProgram.program.coder.types.decode('PublicTransactionEvent', numericData);
1353
+ }
1354
+ catch (error) {
1355
+ console.error('Error deserializing event:', error);
1356
+ return null;
1357
+ }
1358
+ };
1359
+
1360
+ const DEFAULT_ZERO = '0';
1361
+ /**
1362
+ * @callback hashFunction
1363
+ * @param left Left leaf
1364
+ * @param right Right leaf
1365
+ */
1366
+ /**
1367
+ * Merkle tree
1368
+ */
1369
+ class MerkleTree {
1370
+ constructor(levels, lightWasm, elements = [], { zeroElement = DEFAULT_ZERO } = {}) {
1371
+ this.levels = levels;
1372
+ this.capacity = 2 ** levels;
1373
+ this.zeroElement = zeroElement;
1374
+ this._lightWasm = lightWasm;
1375
+ if (elements.length > this.capacity) {
1376
+ throw new Error('Tree is full');
1377
+ }
1378
+ this._zeros = [];
1379
+ this._layers = [];
1380
+ this._layers[0] = elements;
1381
+ this._zeros[0] = this.zeroElement;
1382
+ for (let i = 1; i <= levels; i++) {
1383
+ this._zeros[i] = this._lightWasm.poseidonHashString([
1384
+ this._zeros[i - 1],
1385
+ this._zeros[i - 1],
1386
+ ]);
1387
+ }
1388
+ this._rebuild();
1389
+ }
1390
+ _rebuild() {
1391
+ for (let level = 1; level <= this.levels; level++) {
1392
+ this._layers[level] = [];
1393
+ for (let i = 0; i < Math.ceil(this._layers[level - 1].length / 2); i++) {
1394
+ this._layers[level][i] = this._lightWasm.poseidonHashString([
1395
+ this._layers[level - 1][i * 2],
1396
+ i * 2 + 1 < this._layers[level - 1].length
1397
+ ? this._layers[level - 1][i * 2 + 1]
1398
+ : this._zeros[level - 1],
1399
+ ]);
1400
+ }
1401
+ }
1402
+ }
1403
+ /**
1404
+ * Get tree root
1405
+ * @returns {*}
1406
+ */
1407
+ root() {
1408
+ return this._layers[this.levels].length > 0
1409
+ ? this._layers[this.levels][0]
1410
+ : this._zeros[this.levels];
1411
+ }
1412
+ /**
1413
+ * Insert new element into the tree
1414
+ * @param element Element to insert
1415
+ */
1416
+ insert(element) {
1417
+ if (this._layers[0].length >= this.capacity) {
1418
+ throw new Error('Tree is full');
1419
+ }
1420
+ this.update(this._layers[0].length, element);
1421
+ }
1422
+ /**
1423
+ * Insert multiple elements into the tree. Tree will be fully rebuilt during this operation.
1424
+ * @param {Array} elements Elements to insert
1425
+ */
1426
+ bulkInsert(elements) {
1427
+ if (this._layers[0].length + elements.length > this.capacity) {
1428
+ throw new Error('Tree is full');
1429
+ }
1430
+ this._layers[0].push(...elements);
1431
+ this._rebuild();
1432
+ }
1433
+ // TODO: update does not work debug
1434
+ /**
1435
+ * Change an element in the tree
1436
+ * @param {number} index Index of element to change
1437
+ * @param element Updated element value
1438
+ */
1439
+ update(index, element) {
1440
+ // index 0 and 1 and element is the commitment hash
1441
+ if (isNaN(Number(index)) ||
1442
+ index < 0 ||
1443
+ index > this._layers[0].length ||
1444
+ index >= this.capacity) {
1445
+ throw new Error('Insert index out of bounds: ' + index);
1446
+ }
1447
+ this._layers[0][index] = element;
1448
+ for (let level = 1; level <= this.levels; level++) {
1449
+ index >>= 1;
1450
+ this._layers[level][index] = this._lightWasm.poseidonHashString([
1451
+ this._layers[level - 1][index * 2],
1452
+ index * 2 + 1 < this._layers[level - 1].length
1453
+ ? this._layers[level - 1][index * 2 + 1]
1454
+ : this._zeros[level - 1],
1455
+ ]);
1456
+ }
1457
+ }
1458
+ /**
1459
+ * Get merkle path to a leaf
1460
+ * @param {number} index Leaf index to generate path for
1461
+ * @returns {{pathElements: number[], pathIndex: number[]}} An object containing adjacent elements and left-right index
1462
+ */
1463
+ path(index) {
1464
+ if (isNaN(Number(index)) ||
1465
+ index < 0 ||
1466
+ index >= this._layers[0].length) {
1467
+ throw new Error('Index out of bounds: ' + index);
1468
+ }
1469
+ const pathElements = [];
1470
+ const pathIndices = [];
1471
+ for (let level = 0; level < this.levels; level++) {
1472
+ pathIndices[level] = index % 2;
1473
+ pathElements[level] =
1474
+ (index ^ 1) < this._layers[level].length
1475
+ ? this._layers[level][index ^ 1]
1476
+ : this._zeros[level];
1477
+ index >>= 1;
1478
+ }
1479
+ return {
1480
+ pathElements,
1481
+ pathIndices,
1482
+ };
1483
+ }
1484
+ /**
1485
+ * Find an element in the tree
1486
+ * @param element An element to find
1487
+ * @param comparator A function that checks leaf value equality
1488
+ * @returns {number} Index if element is found, otherwise -1
1489
+ */
1490
+ indexOf(element, comparator = null) {
1491
+ if (comparator) {
1492
+ return this._layers[0].findIndex((el) => comparator(element, el));
1493
+ }
1494
+ else {
1495
+ return this._layers[0].indexOf(element);
1496
+ }
1497
+ }
1498
+ /**
1499
+ * Returns a copy of non-zero tree elements
1500
+ * @returns {Object[]}
1501
+ */
1502
+ elements() {
1503
+ return this._layers[0].slice();
1504
+ }
1505
+ /**
1506
+ * Serialize entire tree state including intermediate layers into a plain object
1507
+ * Deserializing it back will not require to recompute any hashes
1508
+ * Elements are not converted to a plain type, this is responsibility of the caller
1509
+ */
1510
+ serialize() {
1511
+ return {
1512
+ levels: this.levels,
1513
+ _zeros: this._zeros,
1514
+ _layers: this._layers,
1515
+ };
1516
+ }
1517
+ /**
1518
+ * Deserialize data into a MerkleTree instance
1519
+ * Make sure to provide the same hashFunction as was used in the source tree,
1520
+ * otherwise the tree state will be invalid
1521
+ *
1522
+ * @param data
1523
+ * @param hashFunction
1524
+ * @returns {MerkleTree}
1525
+ */
1526
+ static deserialize(data, hashFunction) {
1527
+ const instance = Object.assign(Object.create(this.prototype), data);
1528
+ instance._hash = hashFunction;
1529
+ instance.capacity = 2 ** instance.levels;
1530
+ instance.zeroElement = instance._zeros[0];
1531
+ return instance;
1532
+ }
1533
+ }
1534
+
1535
+ const placeholderValidityProof = () => ({
1536
+ a: Array.from({ length: 32 }, (_, i) => i + 1),
1537
+ b: Array.from({ length: 64 }, (_, i) => i + 1),
1538
+ c: Array.from({ length: 32 }, (_, i) => i + 1),
1539
+ });
1540
+ const checkValidityProofShape = (proof) => {
1541
+ if (proof.a.length !== 32 ||
1542
+ proof.b.length !== 64 ||
1543
+ proof.c.length !== 32) {
1544
+ throw new Error('ValidityProof has invalid shape');
1545
+ }
1546
+ };
1547
+ function proofFromJsonStruct(json) {
1548
+ const proofAX = deserializeHexStringToBeBytes(json.ar[0]);
1549
+ const proofAY = deserializeHexStringToBeBytes(json.ar[1]);
1550
+ const proofA = new Uint8Array([...proofAX, ...proofAY]);
1551
+ const proofBX0 = deserializeHexStringToBeBytes(json.bs[0][0]);
1552
+ const proofBX1 = deserializeHexStringToBeBytes(json.bs[0][1]);
1553
+ const proofBY0 = deserializeHexStringToBeBytes(json.bs[1][0]);
1554
+ const proofBY1 = deserializeHexStringToBeBytes(json.bs[1][1]);
1555
+ const proofB = new Uint8Array([
1556
+ ...proofBX0,
1557
+ ...proofBX1,
1558
+ ...proofBY0,
1559
+ ...proofBY1,
1560
+ ]);
1561
+ const proofCX = deserializeHexStringToBeBytes(json.krs[0]);
1562
+ const proofCY = deserializeHexStringToBeBytes(json.krs[1]);
1563
+ const proofC = new Uint8Array([...proofCX, ...proofCY]);
1564
+ const proofABC = { a: proofA, b: proofB, c: proofC };
1565
+ return proofABC;
1566
+ }
1567
+ // TODO: add unit test for negation
1568
+ // TODO: test if LE BE issue. unit test
1569
+ function negateAndCompressProof(proof) {
1570
+ const proofA = proof.a;
1571
+ const proofB = proof.b;
1572
+ const proofC = proof.c;
1573
+ const aXElement = proofA.slice(0, 32);
1574
+ const aYElement = new anchor.BN(proofA.slice(32, 64), 32, 'be');
1575
+ /// Negate
1576
+ const proofAIsPositive = yElementIsPositiveG1(aYElement) ? false : true;
1577
+ /// First byte of proofA is the bitmask
1578
+ aXElement[0] = addBitmaskToByte(aXElement[0], proofAIsPositive);
1579
+ const bXElement = proofB.slice(0, 64);
1580
+ const bYElement = proofB.slice(64, 128);
1581
+ const proofBIsPositive = yElementIsPositiveG2(new anchor.BN(bYElement.slice(0, 32), 32, 'be'), new anchor.BN(bYElement.slice(32, 64), 32, 'be'));
1582
+ bXElement[0] = addBitmaskToByte(bXElement[0], proofBIsPositive);
1583
+ const cXElement = proofC.slice(0, 32);
1584
+ const cYElement = proofC.slice(32, 64);
1585
+ const proofCIsPositive = yElementIsPositiveG1(new anchor.BN(cYElement, 32, 'be'));
1586
+ cXElement[0] = addBitmaskToByte(cXElement[0], proofCIsPositive);
1587
+ const compressedProof = {
1588
+ a: Array.from(aXElement),
1589
+ b: Array.from(bXElement),
1590
+ c: Array.from(cXElement),
1591
+ };
1592
+ return compressedProof;
1593
+ }
1594
+ function deserializeHexStringToBeBytes(hexStr) {
1595
+ // Using BN for simpler conversion from hex string to byte array
1596
+ const bn = new anchor.BN(hexStr.startsWith('0x') ? hexStr.substring(2) : hexStr, 'hex');
1597
+ return new Uint8Array(bn.toArray('be', 32));
1598
+ }
1599
+ function yElementIsPositiveG1(yElement) {
1600
+ return yElement.lte(FIELD_SIZE.sub(yElement));
1601
+ }
1602
+ function yElementIsPositiveG2(yElement1, yElement2) {
1603
+ const fieldMidpoint = FIELD_SIZE.div(new anchor.BN(2));
1604
+ // Compare the first component of the y coordinate
1605
+ if (yElement1.lt(fieldMidpoint)) {
1606
+ return true;
1607
+ }
1608
+ else if (yElement1.gt(fieldMidpoint)) {
1609
+ return false;
1610
+ }
1611
+ // If the first component is equal to the midpoint, compare the second component
1612
+ return yElement2.lt(fieldMidpoint);
1613
+ }
1614
+ // bitmask compatible with solana altbn128 compression syscall and arkworks' implementation
1615
+ // https://github.com/arkworks-rs/algebra/blob/master/ff/src/fields/models/fp/mod.rs#L580
1616
+ // https://github.com/arkworks-rs/algebra/blob/master/serialize/src/flags.rs#L18
1617
+ // fn u8_bitmask(value: u8, inf: bool, neg: bool) -> u8 {
1618
+ // let mut mask = 0;
1619
+ // match self {
1620
+ // inf => mask |= 1 << 6,
1621
+ // neg => mask |= 1 << 7,
1622
+ // _ => (),
1623
+ // }
1624
+ // mask
1625
+ // }
1626
+ function addBitmaskToByte(byte, yIsPositive) {
1627
+ if (!yIsPositive) {
1628
+ return (byte |= 1 << 7);
1629
+ }
1630
+ else {
1631
+ return byte;
1632
+ }
1633
+ }
1634
+ //@ts-ignore
1635
+ if (undefined) {
1636
+ //@ts-ignore
1637
+ const { it, expect, describe } = undefined;
1638
+ // Unit test for addBitmaskToByte function
1639
+ describe('addBitmaskToByte', () => {
1640
+ it('should add a bitmask to the byte if yIsPositive is false', () => {
1641
+ const byte = 0b00000000;
1642
+ const yIsPositive = false;
1643
+ const result = addBitmaskToByte(byte, yIsPositive);
1644
+ expect(result).toBe(0b10000000); // 128 in binary, which is 1 << 7
1645
+ });
1646
+ it('should not modify the byte if yIsPositive is true', () => {
1647
+ const byte = 0b00000000;
1648
+ const yIsPositive = true;
1649
+ const result = addBitmaskToByte(byte, yIsPositive);
1650
+ expect(result).toBe(0b00000000);
1651
+ });
1652
+ });
1653
+ describe('test prover server', () => {
1654
+ const TEST_JSON = {
1655
+ ar: [
1656
+ '0x22bdaa3187d8fe294925a66fa0165a11bc9e07678fa2fc72402ebfd33d521c69',
1657
+ '0x2d18ff780b69898b4cdd8d7b6ac72d077799399f0f45e52665426456f3903584',
1658
+ ],
1659
+ bs: [
1660
+ [
1661
+ '0x138cc0962e49f76a701d2871d2799892c9782940095eb0429e979f336d2e162d',
1662
+ '0x2fe1bfbb15cbfb83d7e00ace23e45f890604003783eaf34affa35e0d6f4822bc',
1663
+ ],
1664
+ [
1665
+ '0x1a89264f82cc6e8ef1c696bea0b5803c28c0ba6ab61366bcb71e73a4135cae8d',
1666
+ '0xf778d857b3df01a4100265c9d014ce02d47425f0114685356165fa5ee3f3a26',
1667
+ ],
1668
+ ],
1669
+ krs: [
1670
+ '0x176b6ae9001f66832951e2d43a98a972667447bb1781f534b70cb010270dcdd3',
1671
+ '0xb748d5fac1686db28d94c02250af7eb4f28dfdabc8983305c45bcbc6e163eeb',
1672
+ ],
1673
+ };
1674
+ const COMPRESSED_PROOF_A = [
1675
+ 34, 189, 170, 49, 135, 216, 254, 41, 73, 37, 166, 111, 160, 22, 90,
1676
+ 17, 188, 158, 7, 103, 143, 162, 252, 114, 64, 46, 191, 211, 61, 82,
1677
+ 28, 105,
1678
+ ];
1679
+ const COMPRESSED_PROOF_B = [
1680
+ 147, 140, 192, 150, 46, 73, 247, 106, 112, 29, 40, 113, 210, 121,
1681
+ 152, 146, 201, 120, 41, 64, 9, 94, 176, 66, 158, 151, 159, 51, 109,
1682
+ 46, 22, 45, 47, 225, 191, 187, 21, 203, 251, 131, 215, 224, 10, 206,
1683
+ 35, 228, 95, 137, 6, 4, 0, 55, 131, 234, 243, 74, 255, 163, 94, 13,
1684
+ 111, 72, 34, 188,
1685
+ ];
1686
+ const COMPRESSED_PROOF_C = [
1687
+ 23, 107, 106, 233, 0, 31, 102, 131, 41, 81, 226, 212, 58, 152, 169,
1688
+ 114, 102, 116, 71, 187, 23, 129, 245, 52, 183, 12, 176, 16, 39, 13,
1689
+ 205, 211,
1690
+ ];
1691
+ it('should execute a compressed token mint', async () => {
1692
+ const proof = proofFromJsonStruct(TEST_JSON);
1693
+ const compressedProof = negateAndCompressProof(proof);
1694
+ expect(compressedProof.a).toEqual(COMPRESSED_PROOF_A);
1695
+ expect(compressedProof.b).toEqual(COMPRESSED_PROOF_B);
1696
+ expect(compressedProof.c).toEqual(COMPRESSED_PROOF_C);
1697
+ });
1698
+ });
1699
+ describe('Validity Proof Functions', () => {
1700
+ describe('placeholderValidityProof', () => {
1701
+ it('should create a validity proof with correct shape', () => {
1702
+ const validityProof = placeholderValidityProof();
1703
+ expect(validityProof.a.length).toBe(32);
1704
+ expect(validityProof.b.length).toBe(64);
1705
+ expect(validityProof.c.length).toBe(32);
1706
+ });
1707
+ });
1708
+ describe('checkValidityProofShape', () => {
1709
+ it('should not throw an error for valid proof shape', () => {
1710
+ const validProof = {
1711
+ a: Array.from(new Uint8Array(32)),
1712
+ b: Array.from(new Uint8Array(64)),
1713
+ c: Array.from(new Uint8Array(32)),
1714
+ };
1715
+ expect(() => checkValidityProofShape(validProof)).not.toThrow();
1716
+ });
1717
+ it('should throw an error for an invalid proof', () => {
1718
+ const invalidProof = {
1719
+ a: Array.from(new Uint8Array(31)), // incorrect length
1720
+ b: Array.from(new Uint8Array(64)),
1721
+ c: Array.from(new Uint8Array(32)),
1722
+ };
1723
+ expect(() => checkValidityProofShape(invalidProof)).toThrow('ValidityProof has invalid shape');
1724
+ });
1725
+ });
1726
+ });
1727
+ }
1728
+
1729
+ /**
1730
+ * @internal
1731
+ */
1732
+ const PublicKeyFromString = superstruct.coerce(superstruct.instance(web3_js.PublicKey), superstruct.string(), value => new web3_js.PublicKey(value));
1733
+ /**
1734
+ * @internal
1735
+ */
1736
+ // TODO: use a BN254 class here for the 1st parameter
1737
+ const BN254FromString = superstruct.coerce(superstruct.instance(anchor.BN), superstruct.string(), value => {
1738
+ return createBN254(value, 'base58');
1739
+ });
1740
+ const BNFromInt = superstruct.coerce(superstruct.instance(anchor.BN), superstruct.number(), value => bn(value));
1741
+ const BNFromBase10String = superstruct.coerce(superstruct.instance(anchor.BN), superstruct.string(), value => bn(value));
1742
+ /**
1743
+ * @internal
1744
+ */
1745
+ const Base64EncodedCompressedAccountDataResult = superstruct.coerce(superstruct.nullable(superstruct.string()), superstruct.string(), value => (value === '' ? null : value));
1746
+ /**
1747
+ * @internal
1748
+ */
1749
+ function createRpcResult(result) {
1750
+ return superstruct.union([
1751
+ superstruct.type({
1752
+ jsonrpc: superstruct.literal('2.0'),
1753
+ id: superstruct.string(),
1754
+ result,
1755
+ }),
1756
+ superstruct.type({
1757
+ jsonrpc: superstruct.literal('2.0'),
1758
+ id: superstruct.string(),
1759
+ error: superstruct.type({
1760
+ code: superstruct.unknown(),
1761
+ message: superstruct.string(),
1762
+ data: superstruct.nullable(superstruct.any()),
1763
+ }),
1764
+ }),
1765
+ ]);
1766
+ }
1767
+ /**
1768
+ * @internal
1769
+ */
1770
+ const UnknownRpcResult = createRpcResult(superstruct.unknown());
1771
+ /**
1772
+ * @internal
1773
+ */
1774
+ function jsonRpcResult(schema) {
1775
+ return superstruct.coerce(createRpcResult(schema), UnknownRpcResult, value => {
1776
+ if ('error' in value) {
1777
+ return value;
1778
+ }
1779
+ else {
1780
+ return Object.assign(Object.assign({}, value), { result: superstruct.create(value.result, schema) });
1781
+ }
1782
+ });
1783
+ }
1784
+ /**
1785
+ * @internal
1786
+ */
1787
+ function jsonRpcResultAndContext(value) {
1788
+ return jsonRpcResult(superstruct.type({
1789
+ context: superstruct.type({
1790
+ slot: superstruct.number(),
1791
+ }),
1792
+ value,
1793
+ }));
1794
+ }
1795
+ /**
1796
+ * @internal
1797
+ */
1798
+ /// Compressed Account With Merkle Context
1799
+ const CompressedAccountResult = superstruct.type({
1800
+ hash: BN254FromString,
1801
+ address: superstruct.nullable(PublicKeyFromString),
1802
+ data: Base64EncodedCompressedAccountDataResult,
1803
+ dataHash: superstruct.nullable(BN254FromString),
1804
+ discriminator: BNFromInt,
1805
+ owner: PublicKeyFromString,
1806
+ lamports: BNFromInt,
1807
+ tree: superstruct.nullable(PublicKeyFromString), // TODO: should not be nullable
1808
+ seq: superstruct.nullable(BNFromInt),
1809
+ slotUpdated: BNFromInt,
1810
+ leafIndex: superstruct.number(),
1811
+ });
1812
+ /**
1813
+ * @internal
1814
+ */
1815
+ /// TODO: update: delegatedAmount, state, programOwner/tokenOwner, data includes the values?, no closeAuth!
1816
+ const CompressedTokenAccountResult = superstruct.type({
1817
+ address: superstruct.nullable(PublicKeyFromString), // TODO: why is this here
1818
+ amount: BNFromBase10String, // why string
1819
+ delegate: superstruct.nullable(PublicKeyFromString),
1820
+ closeAuthority: superstruct.nullable(PublicKeyFromString), // TODO: remove
1821
+ isNative: superstruct.boolean(),
1822
+ frozen: superstruct.boolean(),
1823
+ mint: PublicKeyFromString,
1824
+ owner: PublicKeyFromString, // owner or user?
1825
+ //
1826
+ hash: BN254FromString,
1827
+ data: Base64EncodedCompressedAccountDataResult,
1828
+ dataHash: superstruct.nullable(BN254FromString),
1829
+ discriminator: BNFromInt,
1830
+ lamports: BNFromInt,
1831
+ tree: PublicKeyFromString,
1832
+ seq: BNFromInt,
1833
+ // slotUpdated: BNFromInt, TODO: add owner (?): TODO: check whether this
1834
+ // implicitly assumes tokenprogram as account owner
1835
+ leafIndex: superstruct.number(),
1836
+ });
1837
+ /**
1838
+ * @internal
1839
+ */
1840
+ const MultipleCompressedAccountsResult = superstruct.type({
1841
+ items: superstruct.array(CompressedAccountResult),
1842
+ });
1843
+ /**
1844
+ * @internal
1845
+ */
1846
+ const CompressedAccountsByOwnerResult = superstruct.type({
1847
+ items: superstruct.array(CompressedAccountResult),
1848
+ // cursor: array(number()), // paginated
1849
+ });
1850
+ /**
1851
+ * @internal
1852
+ */
1853
+ const CompressedTokenAccountsByOwnerOrDelegateResult = superstruct.type({
1854
+ items: superstruct.array(CompressedTokenAccountResult),
1855
+ // cursor: array(number()), // paginated TODO: add cursor to photon / docs update
1856
+ });
1857
+ /**
1858
+ * @internal
1859
+ */
1860
+ const SlotResult = superstruct.number();
1861
+ /**
1862
+ * @internal
1863
+ */
1864
+ const HealthResult = superstruct.string();
1865
+ /**
1866
+ * @internal
1867
+ */
1868
+ const MerkeProofResult = superstruct.type({
1869
+ hash: BN254FromString,
1870
+ merkleTree: PublicKeyFromString,
1871
+ leafIndex: superstruct.number(),
1872
+ proof: superstruct.array(BN254FromString),
1873
+ });
1874
+ /**
1875
+ * @internal
1876
+ */
1877
+ const MultipleMerkleProofsResult = superstruct.array(MerkeProofResult);
1878
+ /**
1879
+ * @internal
1880
+ */
1881
+ const BalanceResult = BNFromInt;
1882
+ /// TODO: we need to add: tree, nullifierQueue, leafIndex, rootIndex
1883
+ const AccountProofResult = superstruct.type({
1884
+ hash: superstruct.array(superstruct.number()),
1885
+ root: superstruct.array(superstruct.number()),
1886
+ proof: superstruct.array(superstruct.array(superstruct.number())),
1887
+ });
1888
+
1889
+ function createRpc(endpointOrWeb3JsConnection = 'http://127.0.0.1:8899', compressionApiEndpoint = 'http://localhost:8784', config) {
1890
+ if (typeof endpointOrWeb3JsConnection === 'string') {
1891
+ return new Rpc(endpointOrWeb3JsConnection, compressionApiEndpoint, undefined, config);
1892
+ }
1893
+ return new Rpc(endpointOrWeb3JsConnection.rpcEndpoint, compressionApiEndpoint, undefined, config);
1894
+ }
1895
+ const rpcRequest = async (rpcEndpoint, method, params = [], // TODO: array?
1896
+ convertToCamelCase = true) => {
1897
+ const body = JSON.stringify({
1898
+ jsonrpc: '2.0',
1899
+ id: 'test-account',
1900
+ method: method,
1901
+ params: params,
1902
+ });
1903
+ const response = await fetch(rpcEndpoint, {
1904
+ method: 'POST',
1905
+ headers: { 'Content-Type': 'application/json' },
1906
+ body: body,
1907
+ });
1908
+ if (!response.ok) {
1909
+ throw new Error(`HTTP error! status: ${response.status}`);
1910
+ }
1911
+ if (convertToCamelCase) {
1912
+ const res = await response.json();
1913
+ return toCamelCase(res);
1914
+ }
1915
+ return await response.json();
1916
+ };
1917
+ const mockNullifierQueue = defaultTestStateTreeAccounts().nullifierQueue;
1918
+ class Rpc extends web3_js.Connection {
1919
+ constructor(endpoint, compressionApiEndpoint,
1920
+ // TODO: implement
1921
+ proverEndpoint, config) {
1922
+ super(endpoint, config || 'confirmed');
1923
+ this.compressionApiEndpoint = compressionApiEndpoint;
1924
+ }
1925
+ async getCompressedAccount(hash) {
1926
+ const unsafeRes = await rpcRequest(this.compressionApiEndpoint, 'getCompressedAccount', { hash: encodeBN254toBase58(hash) });
1927
+ const res = superstruct.create(unsafeRes, jsonRpcResultAndContext(superstruct.nullable(CompressedAccountResult)));
1928
+ if ('error' in res) {
1929
+ throw new web3_js.SolanaJSONRPCError(res.error, `failed to get info for compressed account ${hash.toString()}`);
1930
+ }
1931
+ if (res.result.value === null) {
1932
+ return null;
1933
+ }
1934
+ const item = res.result.value;
1935
+ const account = createCompressedAccountWithMerkleContext(createMerkleContext(item.tree, mockNullifierQueue, item.hash.toArray(), item.leafIndex), item.owner, bn(item.lamports),
1936
+ // TODO: fix. add typesafety to the rest
1937
+ item.data
1938
+ ? {
1939
+ discriminator: item.discriminator.toArray('le'),
1940
+ data: Buffer.from(item.data, 'base64'),
1941
+ dataHash: item.dataHash.toArray('le'), //FIXME: need to calculate the hash or return from server
1942
+ }
1943
+ : undefined, item.address || undefined);
1944
+ return account;
1945
+ }
1946
+ async getCompressedBalance(hash) {
1947
+ const unsafeRes = await rpcRequest(this.compressionApiEndpoint, 'getCompressedBalance', { hash: encodeBN254toBase58(hash) });
1948
+ const res = superstruct.create(unsafeRes, jsonRpcResultAndContext(BalanceResult));
1949
+ if ('error' in res) {
1950
+ throw new web3_js.SolanaJSONRPCError(res.error, `failed to get balance for compressed account ${hash.toString()}`);
1951
+ }
1952
+ if (res.result.value === null) {
1953
+ return null;
1954
+ }
1955
+ return bn(res.result.value);
1956
+ }
1957
+ /** Retrieve the merkle proof for a compressed account */
1958
+ async getCompressedAccountProof(hash) {
1959
+ const unsafeRes = await rpcRequest(this.compressionApiEndpoint, 'getCompressedAccountProof', encodeBN254toBase58(hash));
1960
+ const res = superstruct.create(unsafeRes, jsonRpcResultAndContext(MerkeProofResult));
1961
+ if ('error' in res) {
1962
+ throw new web3_js.SolanaJSONRPCError(res.error, `failed to get proof for compressed account ${hash.toString()}`);
1963
+ }
1964
+ if (res.result.value === null) {
1965
+ throw new Error(`failed to get proof for compressed account ${hash.toString()}`);
1966
+ }
1967
+ const value = {
1968
+ hash: res.result.value.hash.toArray(),
1969
+ merkleTree: res.result.value.merkleTree,
1970
+ leafIndex: res.result.value.leafIndex,
1971
+ merkleProof: res.result.value.proof,
1972
+ nullifierQueue: mockNullifierQueue,
1973
+ rootIndex: 0, // TODO: add root index
1974
+ };
1975
+ return value;
1976
+ }
1977
+ async getMultipleCompressedAccounts(hashes) {
1978
+ const unsafeRes = await rpcRequest(this.compressionApiEndpoint, 'getMultipleCompressedAccounts', hashes.map(hash => encodeBN254toBase58(hash)));
1979
+ const res = superstruct.create(unsafeRes, jsonRpcResultAndContext(MultipleCompressedAccountsResult));
1980
+ if ('error' in res) {
1981
+ throw new web3_js.SolanaJSONRPCError(res.error, `failed to get info for compressed accounts ${hashes.map(hash => encodeBN254toBase58(hash)).join(', ')}`);
1982
+ }
1983
+ if (res.result.value === null) {
1984
+ return null;
1985
+ }
1986
+ const accounts = [];
1987
+ res.result.value.items.map((item) => {
1988
+ const account = createCompressedAccountWithMerkleContext(createMerkleContext(item.tree, mockNullifierQueue, item.hash.toArray(), item.leafIndex), item.owner, bn(item.lamports), item.data && {
1989
+ /// TODO: validate whether we need to convert to 'le' here
1990
+ discriminator: item.discriminator.toArray('le'),
1991
+ data: Buffer.from(item.data, 'base64'),
1992
+ dataHash: item.dataHash.toArray('le'), //FIXME: need to calculate the hash or return from server
1993
+ }, item.address);
1994
+ accounts.push(account);
1995
+ });
1996
+ return accounts;
1997
+ }
1998
+ /** Retrieve the merkle proof for a compressed account */
1999
+ async getMultipleCompressedAccountProofs(hashes) {
2000
+ const unsafeRes = await rpcRequest(this.compressionApiEndpoint, 'getMultipleCompressedAccountProofs', hashes.map(hash => encodeBN254toBase58(hash)));
2001
+ const res = superstruct.create(unsafeRes, jsonRpcResultAndContext(superstruct.array(MerkeProofResult)));
2002
+ if ('error' in res) {
2003
+ throw new web3_js.SolanaJSONRPCError(res.error, `failed to get proofs for compressed accounts ${hashes.map(hash => encodeBN254toBase58(hash)).join(', ')}`);
2004
+ }
2005
+ if (res.result.value === null) {
2006
+ return null;
2007
+ }
2008
+ const merkleProofs = [];
2009
+ res.result.value.map((proof) => {
2010
+ const value = {
2011
+ hash: proof.hash.toArray(), // FIXME
2012
+ merkleTree: proof.merkleTree,
2013
+ leafIndex: proof.leafIndex,
2014
+ merkleProof: proof.proof.map((proof) => createBN254(proof)),
2015
+ nullifierQueue: mockNullifierQueue,
2016
+ rootIndex: 0, // TODO: add root index
2017
+ };
2018
+ merkleProofs.push(value);
2019
+ });
2020
+ return merkleProofs;
2021
+ }
2022
+ async getCompressedAccountsByOwner(owner) {
2023
+ const unsafeRes = await rpcRequest(this.compressionApiEndpoint, 'getCompressedAccountsByOwner', { owner: owner.toBase58() });
2024
+ const res = superstruct.create(unsafeRes, jsonRpcResultAndContext(CompressedAccountsByOwnerResult));
2025
+ if ('error' in res) {
2026
+ throw new web3_js.SolanaJSONRPCError(res.error, `failed to get info for compressed accounts owned by ${owner.toBase58()}`);
2027
+ }
2028
+ if (res.result.value === null) {
2029
+ return [];
2030
+ }
2031
+ const accounts = [];
2032
+ /// TODO: clean up. Make typesafe
2033
+ res.result.value.items.map((item) => {
2034
+ const account = createCompressedAccountWithMerkleContext(createMerkleContext(item.tree, mockNullifierQueue, item.hash.toArray(), item.leafIndex), item.owner, bn(item.lamports), item.data && {
2035
+ discriminator: item.discriminator.toArray('le'),
2036
+ data: Buffer.from(item.data, 'base64'),
2037
+ dataHash: item.dataHash.toArray('le'), //FIXME: need to calculate the hash or return from server
2038
+ }, item.address);
2039
+ accounts.push(account);
2040
+ });
2041
+ return accounts;
2042
+ }
2043
+ /// TODO: Implement self
2044
+ async getValidityProof(hashes) {
2045
+ const rpc = await getTestRpc();
2046
+ const proof = await rpc.getValidityProof(hashes);
2047
+ return proof;
2048
+ }
2049
+ async getHealth() {
2050
+ const unsafeRes = await rpcRequest(this.compressionApiEndpoint, 'getHealth');
2051
+ const res = superstruct.create(unsafeRes, jsonRpcResult(HealthResult));
2052
+ if ('error' in res) {
2053
+ throw new web3_js.SolanaJSONRPCError(res.error, 'failed to get health');
2054
+ }
2055
+ return res.result;
2056
+ }
2057
+ /** TODO: use from Connection */
2058
+ async getSlot() {
2059
+ const unsafeRes = await rpcRequest(this.compressionApiEndpoint, 'getSlot');
2060
+ const res = superstruct.create(unsafeRes, jsonRpcResult(SlotResult));
2061
+ if ('error' in res) {
2062
+ throw new web3_js.SolanaJSONRPCError(res.error, 'failed to get slot');
2063
+ }
2064
+ return res.result;
2065
+ }
2066
+ async getCompressedTokenAccountsByOwner(owner, options) {
2067
+ var _a;
2068
+ const unsafeRes = await rpcRequest(this.compressionApiEndpoint, 'getCompressedTokenAccountsByOwner', { owner: owner.toBase58(), mint: (_a = options === null || options === void 0 ? void 0 : options.mint) === null || _a === void 0 ? void 0 : _a.toBase58() });
2069
+ const res = superstruct.create(unsafeRes, jsonRpcResultAndContext(CompressedTokenAccountsByOwnerOrDelegateResult));
2070
+ if ('error' in res) {
2071
+ throw new web3_js.SolanaJSONRPCError(res.error, `failed to get info for compressed accounts owned by ${owner.toBase58()}`);
2072
+ }
2073
+ if (res.result.value === null) {
2074
+ throw new Error('not implemented. NULL result');
2075
+ }
2076
+ const accounts = [];
2077
+ /// TODO: clean up. Make typesafe
2078
+ res.result.value.items.map((item) => {
2079
+ const account = createCompressedAccountWithMerkleContext(createMerkleContext(item.tree, mockNullifierQueue, item.hash.toArray(), item.leafIndex), new web3_js.PublicKey('9sixVEthz2kMSKfeApZXHwuboT6DZuT6crAYJTciUCqE'), // TODO: photon should return programOwner
2080
+ bn(item.lamports), item.data && {
2081
+ discriminator: item.discriminator.toArray('le'),
2082
+ data: Buffer.from(item.data, 'base64'),
2083
+ dataHash: item.dataHash.toArray('le'), //FIXME: need to calculate the hash or return from server
2084
+ }, item.address);
2085
+ const tokenData = {
2086
+ mint: item.mint,
2087
+ owner: item.owner,
2088
+ amount: item.amount,
2089
+ delegate: item.delegate,
2090
+ state: 1, // TODO: dynamic
2091
+ isNative: null, // TODO: dynamic
2092
+ delegatedAmount: bn(0), // TODO: dynamic
2093
+ };
2094
+ accounts.push({
2095
+ compressedAccount: account,
2096
+ parsed: tokenData,
2097
+ });
2098
+ });
2099
+ /// TODO: consider custom sort. we're returning most recent first
2100
+ /// because thats how our tests expect it currently
2101
+ return accounts.sort((a, b) => b.compressedAccount.leafIndex - a.compressedAccount.leafIndex);
2102
+ }
2103
+ /// TODO: implement delegate
2104
+ async getCompressedTokenAccountsByDelegate(delegate, options) {
2105
+ throw new Error('Method not implemented.');
2106
+ }
2107
+ async getCompressedTokenAccountBalance(hash) {
2108
+ throw new Error('Method not implemented.');
2109
+ }
2110
+ }
2111
+
2112
+ function toHex(bnString) {
2113
+ return '0x' + new anchor.BN(bnString).toString(16);
2114
+ }
2115
+ /**
2116
+ * Simple mock rpc for unit tests that simulates the compression rpc interface.
2117
+ * Fetches, parses events and builds merkletree on-demand, i.e. it does not persist state.
2118
+ * Constraints:
2119
+ * - Can only index 1 merkletree
2120
+ * - Can only index up to 1000 transactions
2121
+ *
2122
+ * For advanced testing use photon: https://github.com/helius-labs/photon
2123
+ */
2124
+ class TestRpc extends Rpc {
2125
+ /**
2126
+ * Instantiate a mock RPC simulating the compression rpc interface.
2127
+ *
2128
+ * @param endpoint endpoint to the solana cluster (use for
2129
+ * localnet only)
2130
+ * @param hasher light wasm hasher instance
2131
+ * @param testRpcConfig Config for the mock rpc
2132
+ * @param proverEndpoint Optional endpoint to the prover server.
2133
+ * defaults to endpoint
2134
+ * @param connectionConfig Optional connection config
2135
+ */
2136
+ constructor(endpoint, hasher, proverEndpoint, testRpcConfig, connectionConfig) {
2137
+ super(endpoint, proverEndpoint, connectionConfig);
2138
+ this.log = false;
2139
+ const { merkleTreeAddress, nullifierQueueAddress, depth, log } = testRpcConfig !== null && testRpcConfig !== void 0 ? testRpcConfig : {};
2140
+ const { merkleTree, nullifierQueue, merkleTreeHeight } = defaultTestStateTreeAccounts();
2141
+ this.lightWasm = hasher;
2142
+ this.merkleTreeAddress = merkleTreeAddress !== null && merkleTreeAddress !== void 0 ? merkleTreeAddress : merkleTree;
2143
+ this.nullifierQueueAddress = nullifierQueueAddress !== null && nullifierQueueAddress !== void 0 ? nullifierQueueAddress : nullifierQueue;
2144
+ this.depth = depth !== null && depth !== void 0 ? depth : merkleTreeHeight;
2145
+ this.log = log !== null && log !== void 0 ? log : false;
2146
+ }
2147
+ /**
2148
+ * @internal
2149
+ * Returns newest first
2150
+ * */
2151
+ async getParsedEvents() {
2152
+ const { noopProgram, accountCompressionProgram } = defaultStaticAccountsStruct();
2153
+ /// Get raw transactions
2154
+ const signatures = (await this.getConfirmedSignaturesForAddress2(accountCompressionProgram, undefined, 'confirmed')).map(s => s.signature);
2155
+ const txs = await this.getParsedTransactions(signatures, {
2156
+ maxSupportedTransactionVersion: 0,
2157
+ commitment: 'confirmed',
2158
+ });
2159
+ /// Filter by NOOP program
2160
+ const transactionEvents = txs.filter((tx) => {
2161
+ if (!tx) {
2162
+ return false;
2163
+ }
2164
+ const accountKeys = tx.transaction.message.accountKeys;
2165
+ const hasSplNoopAddress = accountKeys.some((item) => {
2166
+ const itemStr = typeof item === 'string'
2167
+ ? item
2168
+ : item.pubkey.toBase58();
2169
+ return itemStr === noopProgram.toBase58();
2170
+ });
2171
+ return hasSplNoopAddress;
2172
+ });
2173
+ /// Parse events
2174
+ const parsedEvents = parseEvents(transactionEvents, parsePublicTransactionEventWithIdl);
2175
+ return parsedEvents;
2176
+ }
2177
+ /** Retrieve validity proof for compressed accounts */
2178
+ async getValidityProof(compressedAccountHashes) {
2179
+ /// rebuild tree
2180
+ const events = await this.getParsedEvents().then(events => events.reverse());
2181
+ const allLeaves = [];
2182
+ const allLeafIndices = [];
2183
+ for (const event of events) {
2184
+ for (let index = 0; index < event.outputCompressedAccounts.length; index++) {
2185
+ const hash = event.outputCompressedAccountHashes[index];
2186
+ allLeaves.push(hash);
2187
+ allLeafIndices.push(event.outputLeafIndices[index]);
2188
+ }
2189
+ }
2190
+ const tree = new MerkleTree(this.depth, this.lightWasm, allLeaves.map(leaf => bn(leaf).toString()));
2191
+ /// create merkle proofs
2192
+ const leafIndices = compressedAccountHashes.map(compressedAccountHash => tree.indexOf(compressedAccountHash.toString()));
2193
+ const hexPathElementsAll = leafIndices.map(leafIndex => {
2194
+ const pathElements = tree.path(leafIndex).pathElements;
2195
+ const hexPathElements = pathElements.map(value => toHex(value));
2196
+ return hexPathElements;
2197
+ });
2198
+ const roots = new Array(compressedAccountHashes.length).fill(toHex(tree.root()));
2199
+ const inputs = {
2200
+ roots,
2201
+ inPathIndices: leafIndices,
2202
+ inPathElements: hexPathElementsAll,
2203
+ leaves: compressedAccountHashes.map(compressedAccountHash => toHex(compressedAccountHash.toString())),
2204
+ };
2205
+ /// Validate
2206
+ compressedAccountHashes.forEach((compressedAccountHash, index) => {
2207
+ const leafIndex = leafIndices[index];
2208
+ const computedHash = tree.elements()[leafIndex].toString();
2209
+ if (computedHash !== compressedAccountHash.toString()) {
2210
+ throw new Error(`Mismatch at index ${index}: expected ${compressedAccountHash.toString()}, got ${computedHash}`);
2211
+ }
2212
+ });
2213
+ const inputsData = JSON.stringify(inputs);
2214
+ let logMsg = '';
2215
+ if (this.log) {
2216
+ logMsg = `Proof generation for depth:${this.depth} n:${compressedAccountHashes.length}`;
2217
+ console.time(logMsg);
2218
+ }
2219
+ // TODO: pass url into rpc constructor
2220
+ const SERVER_URL = 'http://localhost:3001';
2221
+ const INCLUSION_PROOF_URL = `${SERVER_URL}/inclusion`;
2222
+ const response = await axios.post(INCLUSION_PROOF_URL, inputsData);
2223
+ const parsed = proofFromJsonStruct(response.data);
2224
+ const compressedProof = negateAndCompressProof(parsed);
2225
+ if (this.log)
2226
+ console.timeEnd(logMsg);
2227
+ // TODO: in prover server, fix property names
2228
+ const value = {
2229
+ compressedProof,
2230
+ roots: roots,
2231
+ // TODO: temporary
2232
+ rootIndices: leafIndices.map(_ => allLeafIndices.length),
2233
+ leafIndices,
2234
+ leaves: compressedAccountHashes,
2235
+ merkleTree: this.merkleTreeAddress,
2236
+ nullifierQueue: this.nullifierQueueAddress,
2237
+ };
2238
+ return value;
2239
+ }
2240
+ }
2241
+
2242
+ let c = 1;
2243
+ const ALICE = getTestKeypair(255);
2244
+ const BOB = getTestKeypair(254);
2245
+ const CHARLIE = getTestKeypair(253);
2246
+ const DAVE = getTestKeypair(252);
2247
+ async function newAccountWithLamports(rpc, lamports = 1000000000, counter = undefined) {
2248
+ const account = getTestKeypair(counter);
2249
+ const sig = await rpc.requestAirdrop(account.publicKey, lamports);
2250
+ await confirmTx(rpc, sig);
2251
+ return account;
2252
+ }
2253
+ function getConnection() {
2254
+ const url = 'http://127.0.0.1:8899';
2255
+ const connection = new web3_js.Connection(url, 'confirmed');
2256
+ return connection;
2257
+ }
2258
+ /**
2259
+ * Returns a mock RPC instance for use in unit tests.
2260
+ *
2261
+ * @param endpoint RPC endpoint URL. Defaults to
2262
+ * 'http://127.0.0.1:8899'.
2263
+ * @param proverEndpoint Prover server endpoint URL. Defaults to
2264
+ * 'http://localhost:3001'.
2265
+ * @param lightWasm Wasm hasher instance.
2266
+ * @param merkleTreeAddress Address of the merkle tree to index. Defaults
2267
+ * to the public default test state tree.
2268
+ * @param nullifierQueueAddress Optional address of the associated nullifier
2269
+ * queue.
2270
+ * @param depth Depth of the merkle tree.
2271
+ * @param log Log proof generation time.
2272
+ */
2273
+ async function getTestRpc(endpoint = 'http://127.0.0.1:8899', proverEndpoint = 'http://localhost:3001', lightWasm, merkleTreeAddress, nullifierQueueAddress, depth, log = false) {
2274
+ lightWasm = lightWasm || (await hasher_rs.WasmFactory.getInstance());
2275
+ const defaultAccounts = defaultTestStateTreeAccounts();
2276
+ return new TestRpc(endpoint, lightWasm, proverEndpoint, {
2277
+ merkleTreeAddress: merkleTreeAddress || defaultAccounts.merkleTree,
2278
+ nullifierQueueAddress: nullifierQueueAddress || defaultAccounts.nullifierQueue,
2279
+ depth: depth || defaultAccounts.merkleTreeHeight,
2280
+ log,
2281
+ });
2282
+ }
2283
+ /**
2284
+ * For use in tests.
2285
+ * Generate a unique keypair by passing in a counter <255. If no counter
2286
+ * is supplied, it uses and increments a global counter.
2287
+ */
2288
+ function getTestKeypair(counter = undefined) {
2289
+ if (!counter) {
2290
+ counter = c;
2291
+ c++;
2292
+ }
2293
+ if (counter > 255) {
2294
+ throw new Error('Counter must be <= 255');
2295
+ }
2296
+ const seed = new Uint8Array(32);
2297
+ seed[0] = counter;
2298
+ return web3_js.Keypair.fromSeed(seed);
2299
+ }
2300
+ //@ts-ignore
2301
+ if (undefined) {
2302
+ //@ts-ignore
2303
+ const { describe, it, expect } = undefined;
2304
+ describe('getTestKeypair', () => {
2305
+ it('should generate a keypair with a specific counter', () => {
2306
+ const keypair = getTestKeypair(10);
2307
+ expect(keypair).toBeInstanceOf(web3_js.Keypair);
2308
+ expect(keypair.publicKey).toBeDefined();
2309
+ expect(keypair.secretKey).toBeDefined();
2310
+ });
2311
+ it('should throw an error if counter is greater than 255', () => {
2312
+ const testFn = () => getTestKeypair(256);
2313
+ expect(testFn).toThrow('Counter must be <= 255');
2314
+ });
2315
+ it('should increment the global counter if no counter is provided', () => {
2316
+ const initialKeypair = getTestKeypair();
2317
+ const nextKeypair = getTestKeypair();
2318
+ expect(initialKeypair).not.toEqual(nextKeypair);
2319
+ });
2320
+ });
2321
+ }
2322
+
2323
+ const sumUpLamports = (accounts) => {
2324
+ return accounts.reduce((acc, account) => acc.add(bn(account.lamports)), bn(0));
2325
+ };
2326
+ const COMPRESSED_SOL_PDA_SEED = Buffer.from('compressed_sol_pda');
2327
+ class LightSystemProgram {
2328
+ /**
2329
+ * @internal
2330
+ */
2331
+ constructor() { }
2332
+ static get program() {
2333
+ if (!this._program) {
2334
+ this.initializeProgram();
2335
+ }
2336
+ return this._program;
2337
+ }
2338
+ /**
2339
+ * @internal
2340
+ * Cwct1kQLwJm8Z3HetLu8m4SXkhD6FZ5fXbJQCxTxPnGY
2341
+ */
2342
+ static deriveCompressedSolPda() {
2343
+ const seeds = [COMPRESSED_SOL_PDA_SEED];
2344
+ const [address, _] = web3_js.PublicKey.findProgramAddressSync(seeds, this.programId);
2345
+ return address;
2346
+ }
2347
+ /**
2348
+ * Initializes the program statically if not already initialized.
2349
+ */
2350
+ static initializeProgram() {
2351
+ if (!this._program) {
2352
+ const mockKeypair = web3_js.Keypair.generate();
2353
+ const mockConnection = new web3_js.Connection('http://127.0.0.1:8899', 'confirmed');
2354
+ const mockProvider = new anchor.AnchorProvider(mockConnection, useWallet(mockKeypair), {
2355
+ commitment: 'confirmed',
2356
+ preflightCommitment: 'confirmed',
2357
+ });
2358
+ anchor.setProvider(mockProvider);
2359
+ this._program = new anchor.Program(IDL$3, this.programId, mockProvider);
2360
+ }
2361
+ }
2362
+ static createTransferOutputState(inputCompressedAccounts, toAddress, lamports) {
2363
+ lamports = bn(lamports);
2364
+ const inputLamports = sumUpLamports(inputCompressedAccounts);
2365
+ const changeLamports = inputLamports.sub(lamports);
2366
+ validateSufficientBalance(changeLamports);
2367
+ if (changeLamports.eq(bn(0))) {
2368
+ return [createCompressedAccount(toAddress, lamports)];
2369
+ }
2370
+ validateSameOwner(inputCompressedAccounts);
2371
+ const outputCompressedAccounts = [
2372
+ createCompressedAccount(toAddress, lamports),
2373
+ createCompressedAccount(inputCompressedAccounts[0].owner, changeLamports),
2374
+ ];
2375
+ return outputCompressedAccounts;
2376
+ }
2377
+ static createDecompressOutputState(inputCompressedAccounts, lamports) {
2378
+ lamports = bn(lamports);
2379
+ const inputLamports = sumUpLamports(inputCompressedAccounts);
2380
+ const changeLamports = inputLamports.sub(lamports);
2381
+ validateSufficientBalance(changeLamports);
2382
+ /// lamports gets decompressed
2383
+ if (changeLamports.eq(bn(0))) {
2384
+ return [];
2385
+ }
2386
+ validateSameOwner(inputCompressedAccounts);
2387
+ const outputCompressedAccounts = [
2388
+ createCompressedAccount(inputCompressedAccounts[0].owner, changeLamports),
2389
+ ];
2390
+ return outputCompressedAccounts;
2391
+ }
2392
+ /**
2393
+ * Creates a transaction instruction that transfers compressed lamports from
2394
+ * one owner to another.
2395
+ */
2396
+ static async transfer(params) {
2397
+ const { payer, recentValidityProof, recentInputStateRootIndices, inputCompressedAccounts, lamports, outputStateTrees, } = params;
2398
+ /// Create output state
2399
+ const outputCompressedAccounts = this.createTransferOutputState(inputCompressedAccounts, params.toAddress, lamports);
2400
+ /// Pack accounts
2401
+ const { packedInputCompressedAccounts, outputStateMerkleTreeIndices, remainingAccountMetas, } = packCompressedAccounts(inputCompressedAccounts, outputCompressedAccounts.length, outputStateTrees);
2402
+ /// Encode instruction data
2403
+ const data = this.program.coder.types.encode('InstructionDataTransfer', {
2404
+ proof: recentValidityProof,
2405
+ inputRootIndices: recentInputStateRootIndices,
2406
+ /// TODO: here and on-chain: option<newAddressInputs> or similar.
2407
+ newAddressParams: [],
2408
+ inputCompressedAccountsWithMerkleContext: packedInputCompressedAccounts,
2409
+ outputCompressedAccounts,
2410
+ outputStateMerkleTreeAccountIndices: Buffer.from(outputStateMerkleTreeIndices),
2411
+ relayFee: null,
2412
+ compressionLamports: null,
2413
+ isCompress: false,
2414
+ });
2415
+ /// Build anchor instruction
2416
+ const instruction = await this.program.methods
2417
+ .executeCompressedTransaction(data)
2418
+ .accounts(Object.assign(Object.assign({}, defaultStaticAccountsStruct()), { signer: payer, invokingProgram: this.programId, compressedSolPda: null, compressionRecipient: null, systemProgram: null }))
2419
+ .remainingAccounts(remainingAccountMetas)
2420
+ .instruction();
2421
+ const instructions = [
2422
+ web3_js.ComputeBudgetProgram.setComputeUnitLimit({ units: 1000000 }),
2423
+ instruction,
2424
+ ];
2425
+ return instructions;
2426
+ }
2427
+ /**
2428
+ * Initialize the compressed sol pda
2429
+ */
2430
+ static async initCompressedSolPda(feePayer) {
2431
+ const accounts = {
2432
+ feePayer,
2433
+ compressedSolPda: this.deriveCompressedSolPda(),
2434
+ systemProgram: web3_js.SystemProgram.programId,
2435
+ };
2436
+ const instruction = await this.program.methods
2437
+ .initCompressSolPda()
2438
+ .accounts(accounts)
2439
+ .instruction();
2440
+ return instruction;
2441
+ }
2442
+ /**
2443
+ * Creates a transaction instruction that transfers compressed lamports from
2444
+ * one owner to another.
2445
+ */
2446
+ // TODO: add support for non-fee-payer owner
2447
+ static async compress(params) {
2448
+ const { payer, outputStateTree, toAddress } = params;
2449
+ /// Create output state
2450
+ const lamports = bn(params.lamports);
2451
+ const outputCompressedAccount = createCompressedAccount(toAddress, lamports);
2452
+ /// Pack accounts
2453
+ const { packedInputCompressedAccounts, outputStateMerkleTreeIndices, remainingAccountMetas, } = packCompressedAccounts([], 1, outputStateTree);
2454
+ /// Encode instruction data
2455
+ const data = this.program.coder.types.encode('InstructionDataTransfer', {
2456
+ proof: placeholderValidityProof(),
2457
+ inputRootIndices: [],
2458
+ /// TODO: here and on-chain: option<newAddressInputs> or similar.
2459
+ newAddressParams: [],
2460
+ inputCompressedAccountsWithMerkleContext: packedInputCompressedAccounts,
2461
+ outputCompressedAccounts: [outputCompressedAccount],
2462
+ outputStateMerkleTreeAccountIndices: Buffer.from(new Uint8Array(outputStateMerkleTreeIndices)),
2463
+ relayFee: null,
2464
+ compressionLamports: lamports,
2465
+ isCompress: true,
2466
+ });
2467
+ /// Build anchor instruction
2468
+ const instruction = await this.program.methods
2469
+ .executeCompressedTransaction(data)
2470
+ .accounts(Object.assign(Object.assign({}, defaultStaticAccountsStruct()), { signer: payer, invokingProgram: this.programId, compressedSolPda: this.deriveCompressedSolPda(), compressionRecipient: null, systemProgram: web3_js.SystemProgram.programId }))
2471
+ .remainingAccounts(remainingAccountMetas)
2472
+ .instruction();
2473
+ const instructions = [
2474
+ web3_js.ComputeBudgetProgram.setComputeUnitLimit({ units: 1000000 }),
2475
+ instruction,
2476
+ ];
2477
+ return instructions;
2478
+ }
2479
+ /**
2480
+ * Creates a transaction instruction that transfers compressed lamports from
2481
+ * one owner to another.
2482
+ */
2483
+ /// TODO: add check that outputStateTree is provided or supplemented if change exists
2484
+ static async decompress(params) {
2485
+ const { payer, outputStateTree, toAddress } = params;
2486
+ /// Create output state
2487
+ const lamports = bn(params.lamports);
2488
+ const outputCompressedAccounts = this.createDecompressOutputState(params.inputCompressedAccounts, lamports);
2489
+ /// Pack accounts
2490
+ const { packedInputCompressedAccounts, outputStateMerkleTreeIndices, remainingAccountMetas, } = packCompressedAccounts(params.inputCompressedAccounts, outputCompressedAccounts.length, outputStateTree);
2491
+ /// Encode instruction data
2492
+ const data = this.program.coder.types.encode('InstructionDataTransfer', {
2493
+ proof: params.recentValidityProof,
2494
+ inputRootIndices: params.recentInputStateRootIndices,
2495
+ /// TODO: here and on-chain: option<newAddressInputs> or similar.
2496
+ newAddressParams: [],
2497
+ inputCompressedAccountsWithMerkleContext: packedInputCompressedAccounts,
2498
+ outputCompressedAccounts: outputCompressedAccounts,
2499
+ outputStateMerkleTreeAccountIndices: Buffer.from(new Uint8Array(outputStateMerkleTreeIndices)),
2500
+ relayFee: null,
2501
+ compressionLamports: lamports,
2502
+ isCompress: false,
2503
+ });
2504
+ /// Build anchor instruction
2505
+ const instruction = await this.program.methods
2506
+ .executeCompressedTransaction(data)
2507
+ .accounts(Object.assign(Object.assign({}, defaultStaticAccountsStruct()), { signer: payer, invokingProgram: this.programId, compressedSolPda: this.deriveCompressedSolPda(), compressionRecipient: toAddress, systemProgram: web3_js.SystemProgram.programId }))
2508
+ .remainingAccounts(remainingAccountMetas)
2509
+ .instruction();
2510
+ const instructions = [
2511
+ web3_js.ComputeBudgetProgram.setComputeUnitLimit({ units: 1000000 }),
2512
+ instruction,
2513
+ ];
2514
+ return instructions;
2515
+ }
2516
+ }
2517
+ /**
2518
+ * Public key that identifies the CompressedPda program
2519
+ */
2520
+ LightSystemProgram.programId = new web3_js.PublicKey(
2521
+ // TODO: can add check to ensure its consistent with the idl
2522
+ '6UqiSPd2mRCTTwkzhcs1M6DGYsqHWd5jiPueX3LwDMXQ');
2523
+ LightSystemProgram._program = null;
2524
+ // /**
2525
+ // * @internal
2526
+ // *
2527
+ // * Selects the minimal number of compressed accounts for a transfer
2528
+ // * 1. Sorts the accounts by amount in descending order
2529
+ // * 2. Accumulates the lamports amount until it is greater than or equal to the transfer
2530
+ // * amount
2531
+ // */
2532
+ // function _selectMinCompressedAccountsForTransfer(
2533
+ // compressedAccounts: (UtxoWithMerkleContext | UtxoWithMerkleProof)[],
2534
+ // transferAmount: BN,
2535
+ // ): {
2536
+ // selectedAccounts: (UtxoWithMerkleContext | UtxoWithMerkleProof)[];
2537
+ // total: BN;
2538
+ // } {
2539
+ // let accumulatedAmount = bn(0);
2540
+ // const selectedAccounts: (UtxoWithMerkleContext | UtxoWithMerkleProof)[] =
2541
+ // [];
2542
+ // compressedAccounts.sort((a, b) =>
2543
+ // Number(bn(b.lamports).sub(bn(a.lamports))),
2544
+ // );
2545
+ // for (const utxo of compressedAccounts) {
2546
+ // if (accumulatedAmount.gte(bn(transferAmount))) break;
2547
+ // accumulatedAmount = accumulatedAmount.add(bn(utxo.lamports));
2548
+ // selectedAccounts.push(utxo);
2549
+ // }
2550
+ // if (accumulatedAmount.lt(bn(transferAmount))) {
2551
+ // throw new Error('Not enough balance for transfer');
2552
+ // }
2553
+ // return { selectedAccounts, total: accumulatedAmount };
2554
+ // }
2555
+
2556
+ /**
2557
+ * Init the SOL omnibus account for Light
2558
+ *
2559
+ * @param rpc RPC to use
2560
+ * @param payer Payer of the transaction and initialization fees
2561
+ * @param lamports Amount of lamports to compress
2562
+ * @param toAddress Address of the recipient compressed account
2563
+ * @param outputStateTree Optional output state tree. Defaults to a current shared state tree.
2564
+ * @param confirmOptions Options for confirming the transaction
2565
+ *
2566
+ * @return Transaction signature
2567
+ */
2568
+ /// TODO: add multisig support
2569
+ /// TODO: add support for payer != owner
2570
+ async function compressLamports(rpc, payer, lamports, toAddress, outputStateTree, confirmOptions) {
2571
+ const { blockhash } = await rpc.getLatestBlockhash();
2572
+ const ixs = await LightSystemProgram.compress({
2573
+ payer: payer.publicKey,
2574
+ toAddress,
2575
+ lamports,
2576
+ outputStateTree: outputStateTree
2577
+ ? outputStateTree
2578
+ : defaultTestStateTreeAccounts().merkleTree, // TODO: should fetch the current shared state tree
2579
+ });
2580
+ const tx = buildAndSignTx(ixs, payer, blockhash, []);
2581
+ const txId = await sendAndConfirmTx(rpc, tx, confirmOptions);
2582
+ return txId;
2583
+ }
2584
+
2585
+ /**
2586
+ * Init the SOL omnibus account for Light
2587
+ *
2588
+ * @param rpc RPC to use
2589
+ * @param payer Payer of the transaction and initialization fees
2590
+ * @param lamports Amount of lamports to compress
2591
+ * @param toAddress Address of the recipient compressed account
2592
+ * @param outputStateTree Optional output state tree. Defaults to a current shared state tree.
2593
+ * @param confirmOptions Options for confirming the transaction
2594
+ *
2595
+ * @return Transaction signature
2596
+ */
2597
+ /// TODO: add multisig support
2598
+ /// TODO: add support for payer != owner
2599
+ async function decompressLamports(rpc, payer, lamports, recipient, outputStateTree, confirmOptions) {
2600
+ /// TODO: use dynamic state tree and nullifier queue
2601
+ const userCompressedAccountsWithMerkleContext = await rpc.getCompressedAccountsByOwner(payer.publicKey);
2602
+ lamports = bn(lamports);
2603
+ const inputLamports = sumUpLamports(userCompressedAccountsWithMerkleContext);
2604
+ if (lamports.gt(inputLamports)) {
2605
+ throw new Error(`Not enough compressed lamports. Expected ${lamports}, got ${inputLamports}`);
2606
+ }
2607
+ const proof = await rpc.getValidityProof(userCompressedAccountsWithMerkleContext.map(x => bn(x.hash)));
2608
+ const { blockhash } = await rpc.getLatestBlockhash();
2609
+ const ixs = await LightSystemProgram.decompress({
2610
+ payer: payer.publicKey,
2611
+ toAddress: recipient,
2612
+ outputStateTree: outputStateTree,
2613
+ inputCompressedAccounts: userCompressedAccountsWithMerkleContext,
2614
+ recentValidityProof: proof.compressedProof,
2615
+ recentInputStateRootIndices: proof.rootIndices,
2616
+ lamports,
2617
+ });
2618
+ const tx = buildAndSignTx(ixs, payer, blockhash, []);
2619
+ const txId = await sendAndConfirmTx(rpc, tx, confirmOptions);
2620
+ return txId;
2621
+ }
2622
+
2623
+ /** @internal remove signer from signers if part of signers */
2624
+ function dedupeSigner(signer, signers) {
2625
+ if (signers.includes(signer)) {
2626
+ return signers.filter(s => s.publicKey.toString() !== signer.publicKey.toString());
2627
+ }
2628
+ return signers;
2629
+ }
2630
+
2631
+ /**
2632
+ * Init the SOL omnibus account for Light
2633
+ *
2634
+ * @param rpc RPC to use
2635
+ * @param payer Payer of the transaction and initialization fees
2636
+ * @param initAuthority Init authority.
2637
+ * @param confirmOptions Options for confirming the transaction
2638
+ *
2639
+ * @return Transaction signature
2640
+ */
2641
+ /// TODO: add multisig support
2642
+ async function initSolOmnibusAccount(rpc, payer, initAuthority, confirmOptions) {
2643
+ const { blockhash } = await rpc.getLatestBlockhash();
2644
+ const additionalSigners = dedupeSigner(payer, initAuthority ? [initAuthority] : []);
2645
+ const ix = await LightSystemProgram.initCompressedSolPda(initAuthority ? initAuthority.publicKey : payer.publicKey);
2646
+ const tx = buildAndSignTx([ix], payer, blockhash, additionalSigners);
2647
+ const txId = await sendAndConfirmTx(rpc, tx, confirmOptions);
2648
+ return txId;
2649
+ }
2650
+
2651
+ const IDL$2 = {
2652
+ version: '0.3.1',
2653
+ name: 'account_compression',
2654
+ constants: [
2655
+ {
2656
+ name: 'GROUP_AUTHORITY_SEED',
2657
+ type: 'bytes',
2658
+ value: '[103, 114, 111, 117, 112, 95, 97, 117, 116, 104, 111, 114, 105, 116, 121]',
2659
+ },
2660
+ {
2661
+ name: 'STATE_MERKLE_TREE_HEIGHT',
2662
+ type: 'u64',
2663
+ value: '26',
2664
+ },
2665
+ {
2666
+ name: 'STATE_MERKLE_TREE_CHANGELOG',
2667
+ type: 'u64',
2668
+ value: '1400',
2669
+ },
2670
+ {
2671
+ name: 'STATE_MERKLE_TREE_ROOTS',
2672
+ type: 'u64',
2673
+ value: '2400',
2674
+ },
2675
+ {
2676
+ name: 'STATE_MERKLE_TREE_CANOPY_DEPTH',
2677
+ type: 'u64',
2678
+ value: '10',
2679
+ },
2680
+ {
2681
+ name: 'STATE_INDEXED_ARRAY_INDICES',
2682
+ type: 'u16',
2683
+ value: '6857',
2684
+ },
2685
+ {
2686
+ name: 'STATE_INDEXED_ARRAY_VALUES',
2687
+ type: 'u16',
2688
+ value: '4800',
2689
+ },
2690
+ {
2691
+ name: 'STATE_INDEXED_ARRAY_SEQUENCE_THRESHOLD',
2692
+ type: 'u64',
2693
+ value: '2400',
2694
+ },
2695
+ {
2696
+ name: 'ADDRESS_MERKLE_TREE_HEIGHT',
2697
+ type: 'u64',
2698
+ value: '26',
2699
+ },
2700
+ {
2701
+ name: 'ADDRESS_MERKLE_TREE_CHANGELOG',
2702
+ type: 'u64',
2703
+ value: '1400',
2704
+ },
2705
+ {
2706
+ name: 'ADDRESS_MERKLE_TREE_ROOTS',
2707
+ type: 'u64',
2708
+ value: '2400',
2709
+ },
2710
+ {
2711
+ name: 'ADDRESS_MERKLE_TREE_CANOPY_DEPTH',
2712
+ type: 'u64',
2713
+ value: '10',
2714
+ },
2715
+ {
2716
+ name: 'ADDRESS_QUEUE_INDICES',
2717
+ type: 'u16',
2718
+ value: '6857',
2719
+ },
2720
+ {
2721
+ name: 'ADDRESS_QUEUE_VALUES',
2722
+ type: 'u16',
2723
+ value: '4800',
2724
+ },
2725
+ {
2726
+ name: 'ADDRESS_QUEUE_SEQUENCE_THRESHOLD',
2727
+ type: 'u64',
2728
+ value: '2400',
2729
+ },
2730
+ {
2731
+ name: 'PROGRAM_ID',
2732
+ type: 'string',
2733
+ value: '"5QPEJ5zDsVou9FQS3KCauKswM3VwBEBu4dpL9xTqkWwN"',
2734
+ },
2735
+ ],
2736
+ instructions: [
2737
+ {
2738
+ name: 'initializeAddressQueue',
2739
+ accounts: [
2740
+ {
2741
+ name: 'authority',
2742
+ isMut: true,
2743
+ isSigner: true,
2744
+ },
2745
+ {
2746
+ name: 'queue',
2747
+ isMut: true,
2748
+ isSigner: false,
2749
+ },
2750
+ ],
2751
+ args: [
2752
+ {
2753
+ name: 'index',
2754
+ type: 'u64',
2755
+ },
2756
+ {
2757
+ name: 'owner',
2758
+ type: 'publicKey',
2759
+ },
2760
+ {
2761
+ name: 'delegate',
2762
+ type: {
2763
+ option: 'publicKey',
2764
+ },
2765
+ },
2766
+ {
2767
+ name: 'associatedMerkleTree',
2768
+ type: {
2769
+ option: 'publicKey',
2770
+ },
2771
+ },
2772
+ {
2773
+ name: 'capacityIndices',
2774
+ type: 'u16',
2775
+ },
2776
+ {
2777
+ name: 'capacityValues',
2778
+ type: 'u16',
2779
+ },
2780
+ {
2781
+ name: 'sequenceThreshold',
2782
+ type: 'u64',
2783
+ },
2784
+ ],
2785
+ },
2786
+ {
2787
+ name: 'initializeAddressMerkleTree',
2788
+ accounts: [
2789
+ {
2790
+ name: 'authority',
2791
+ isMut: true,
2792
+ isSigner: true,
2793
+ },
2794
+ {
2795
+ name: 'merkleTree',
2796
+ isMut: true,
2797
+ isSigner: false,
2798
+ },
2799
+ ],
2800
+ args: [
2801
+ {
2802
+ name: 'index',
2803
+ type: 'u64',
2804
+ },
2805
+ {
2806
+ name: 'owner',
2807
+ type: 'publicKey',
2808
+ },
2809
+ {
2810
+ name: 'delegate',
2811
+ type: {
2812
+ option: 'publicKey',
2813
+ },
2814
+ },
2815
+ {
2816
+ name: 'height',
2817
+ type: 'u64',
2818
+ },
2819
+ {
2820
+ name: 'changelogSize',
2821
+ type: 'u64',
2822
+ },
2823
+ {
2824
+ name: 'rootsSize',
2825
+ type: 'u64',
2826
+ },
2827
+ {
2828
+ name: 'canopyDepth',
2829
+ type: 'u64',
2830
+ },
2831
+ ],
2832
+ },
2833
+ {
2834
+ name: 'insertAddresses',
2835
+ accounts: [
2836
+ {
2837
+ name: 'authority',
2838
+ isMut: true,
2839
+ isSigner: true,
2840
+ },
2841
+ {
2842
+ name: 'registeredProgramPda',
2843
+ isMut: false,
2844
+ isSigner: false,
2845
+ isOptional: true,
2846
+ },
2847
+ ],
2848
+ args: [
2849
+ {
2850
+ name: 'addresses',
2851
+ type: {
2852
+ vec: {
2853
+ array: ['u8', 32],
2854
+ },
2855
+ },
2856
+ },
2857
+ ],
2858
+ },
2859
+ {
2860
+ name: 'updateAddressMerkleTree',
2861
+ accounts: [
2862
+ {
2863
+ name: 'authority',
2864
+ isMut: true,
2865
+ isSigner: true,
2866
+ },
2867
+ {
2868
+ name: 'queue',
2869
+ isMut: true,
2870
+ isSigner: false,
2871
+ },
2872
+ {
2873
+ name: 'merkleTree',
2874
+ isMut: true,
2875
+ isSigner: false,
2876
+ },
2877
+ ],
2878
+ args: [
2879
+ {
2880
+ name: 'changelogIndex',
2881
+ type: 'u16',
2882
+ },
2883
+ {
2884
+ name: 'value',
2885
+ type: {
2886
+ array: ['u8', 32],
2887
+ },
2888
+ },
2889
+ {
2890
+ name: 'nextIndex',
2891
+ type: 'u64',
2892
+ },
2893
+ {
2894
+ name: 'nextValue',
2895
+ type: {
2896
+ array: ['u8', 32],
2897
+ },
2898
+ },
2899
+ {
2900
+ name: 'lowAddressIndex',
2901
+ type: 'u64',
2902
+ },
2903
+ {
2904
+ name: 'lowAddressValue',
2905
+ type: {
2906
+ array: ['u8', 32],
2907
+ },
2908
+ },
2909
+ {
2910
+ name: 'lowAddressNextIndex',
2911
+ type: 'u64',
2912
+ },
2913
+ {
2914
+ name: 'lowAddressNextValue',
2915
+ type: {
2916
+ array: ['u8', 32],
2917
+ },
2918
+ },
2919
+ {
2920
+ name: 'lowAddressProof',
2921
+ type: {
2922
+ array: [
2923
+ {
2924
+ array: ['u8', 32],
2925
+ },
2926
+ 16,
2927
+ ],
2928
+ },
2929
+ },
2930
+ {
2931
+ name: 'nextAddressProof',
2932
+ type: {
2933
+ array: ['u8', 128],
2934
+ },
2935
+ },
2936
+ ],
2937
+ },
2938
+ {
2939
+ name: 'initializeGroupAuthority',
2940
+ docs: [
2941
+ 'initialize group (a group can be used to give multiple programs acess to the same Merkle trees by registering the programs to the group)',
2942
+ ],
2943
+ accounts: [
2944
+ {
2945
+ name: 'authority',
2946
+ isMut: true,
2947
+ isSigner: true,
2948
+ },
2949
+ {
2950
+ name: 'groupAuthority',
2951
+ isMut: true,
2952
+ isSigner: false,
2953
+ },
2954
+ {
2955
+ name: 'systemProgram',
2956
+ isMut: false,
2957
+ isSigner: false,
2958
+ },
2959
+ ],
2960
+ args: [
2961
+ {
2962
+ name: 'seed',
2963
+ type: {
2964
+ array: ['u8', 32],
2965
+ },
2966
+ },
2967
+ {
2968
+ name: 'authority',
2969
+ type: 'publicKey',
2970
+ },
2971
+ ],
2972
+ },
2973
+ {
2974
+ name: 'updateGroupAuthority',
2975
+ accounts: [
2976
+ {
2977
+ name: 'authority',
2978
+ isMut: true,
2979
+ isSigner: true,
2980
+ },
2981
+ {
2982
+ name: 'groupAuthority',
2983
+ isMut: true,
2984
+ isSigner: false,
2985
+ },
2986
+ ],
2987
+ args: [
2988
+ {
2989
+ name: 'authority',
2990
+ type: 'publicKey',
2991
+ },
2992
+ ],
2993
+ },
2994
+ {
2995
+ name: 'registerProgramToGroup',
2996
+ accounts: [
2997
+ {
2998
+ name: 'authority',
2999
+ isMut: true,
3000
+ isSigner: true,
3001
+ },
3002
+ {
3003
+ name: 'registeredProgramPda',
3004
+ isMut: true,
3005
+ isSigner: false,
3006
+ },
3007
+ {
3008
+ name: 'groupAuthorityPda',
3009
+ isMut: true,
3010
+ isSigner: false,
3011
+ },
3012
+ {
3013
+ name: 'systemProgram',
3014
+ isMut: false,
3015
+ isSigner: false,
3016
+ },
3017
+ ],
3018
+ args: [
3019
+ {
3020
+ name: 'programId',
3021
+ type: 'publicKey',
3022
+ },
3023
+ ],
3024
+ },
3025
+ {
3026
+ name: 'initializeStateMerkleTree',
3027
+ docs: [
3028
+ 'Initializes a new Merkle tree from config bytes.',
3029
+ 'Index is an optional identifier and not checked by the program.',
3030
+ 'TODO: think the index over',
3031
+ ],
3032
+ accounts: [
3033
+ {
3034
+ name: 'authority',
3035
+ isMut: true,
3036
+ isSigner: true,
3037
+ },
3038
+ {
3039
+ name: 'merkleTree',
3040
+ isMut: true,
3041
+ isSigner: false,
3042
+ },
3043
+ {
3044
+ name: 'systemProgram',
3045
+ isMut: false,
3046
+ isSigner: false,
3047
+ },
3048
+ ],
3049
+ args: [
3050
+ {
3051
+ name: 'index',
3052
+ type: 'u64',
3053
+ },
3054
+ {
3055
+ name: 'owner',
3056
+ type: 'publicKey',
3057
+ },
3058
+ {
3059
+ name: 'delegate',
3060
+ type: {
3061
+ option: 'publicKey',
3062
+ },
3063
+ },
3064
+ {
3065
+ name: 'height',
3066
+ type: 'u64',
3067
+ },
3068
+ {
3069
+ name: 'changelogSize',
3070
+ type: 'u64',
3071
+ },
3072
+ {
3073
+ name: 'rootsSize',
3074
+ type: 'u64',
3075
+ },
3076
+ {
3077
+ name: 'canopyDepth',
3078
+ type: 'u64',
3079
+ },
3080
+ {
3081
+ name: 'associatedQueue',
3082
+ type: {
3083
+ option: 'publicKey',
3084
+ },
3085
+ },
3086
+ ],
3087
+ },
3088
+ {
3089
+ name: 'appendLeavesToMerkleTrees',
3090
+ accounts: [
3091
+ {
3092
+ name: 'authority',
3093
+ isMut: true,
3094
+ isSigner: true,
3095
+ },
3096
+ {
3097
+ name: 'registeredProgramPda',
3098
+ isMut: false,
3099
+ isSigner: false,
3100
+ isOptional: true,
3101
+ },
3102
+ {
3103
+ name: 'logWrapper',
3104
+ isMut: false,
3105
+ isSigner: false,
3106
+ },
3107
+ ],
3108
+ args: [
3109
+ {
3110
+ name: 'leaves',
3111
+ type: {
3112
+ vec: {
3113
+ array: ['u8', 32],
3114
+ },
3115
+ },
3116
+ },
3117
+ ],
3118
+ },
3119
+ {
3120
+ name: 'nullifyLeaves',
3121
+ accounts: [
3122
+ {
3123
+ name: 'authority',
3124
+ isMut: true,
3125
+ isSigner: true,
3126
+ },
3127
+ {
3128
+ name: 'registeredProgramPda',
3129
+ isMut: false,
3130
+ isSigner: false,
3131
+ isOptional: true,
3132
+ },
3133
+ {
3134
+ name: 'logWrapper',
3135
+ isMut: false,
3136
+ isSigner: false,
3137
+ },
3138
+ {
3139
+ name: 'merkleTree',
3140
+ isMut: true,
3141
+ isSigner: false,
3142
+ },
3143
+ {
3144
+ name: 'indexedArray',
3145
+ isMut: true,
3146
+ isSigner: false,
3147
+ },
3148
+ ],
3149
+ args: [
3150
+ {
3151
+ name: 'changeLogIndices',
3152
+ type: {
3153
+ vec: 'u64',
3154
+ },
3155
+ },
3156
+ {
3157
+ name: 'leavesQueueIndices',
3158
+ type: {
3159
+ vec: 'u16',
3160
+ },
3161
+ },
3162
+ {
3163
+ name: 'indices',
3164
+ type: {
3165
+ vec: 'u64',
3166
+ },
3167
+ },
3168
+ {
3169
+ name: 'proofs',
3170
+ type: {
3171
+ vec: {
3172
+ vec: {
3173
+ array: ['u8', 32],
3174
+ },
3175
+ },
3176
+ },
3177
+ },
3178
+ ],
3179
+ },
3180
+ {
3181
+ name: 'initializeIndexedArray',
3182
+ accounts: [
3183
+ {
3184
+ name: 'authority',
3185
+ isMut: false,
3186
+ isSigner: true,
3187
+ },
3188
+ {
3189
+ name: 'indexedArray',
3190
+ isMut: true,
3191
+ isSigner: false,
3192
+ },
3193
+ {
3194
+ name: 'systemProgram',
3195
+ isMut: false,
3196
+ isSigner: false,
3197
+ },
3198
+ ],
3199
+ args: [
3200
+ {
3201
+ name: 'index',
3202
+ type: 'u64',
3203
+ },
3204
+ {
3205
+ name: 'owner',
3206
+ type: 'publicKey',
3207
+ },
3208
+ {
3209
+ name: 'delegate',
3210
+ type: {
3211
+ option: 'publicKey',
3212
+ },
3213
+ },
3214
+ {
3215
+ name: 'associatedMerkleTree',
3216
+ type: {
3217
+ option: 'publicKey',
3218
+ },
3219
+ },
3220
+ {
3221
+ name: 'capacityIndices',
3222
+ type: 'u16',
3223
+ },
3224
+ {
3225
+ name: 'capacityValues',
3226
+ type: 'u16',
3227
+ },
3228
+ {
3229
+ name: 'sequenceThreshold',
3230
+ type: 'u64',
3231
+ },
3232
+ ],
3233
+ },
3234
+ {
3235
+ name: 'insertIntoIndexedArrays',
3236
+ accounts: [
3237
+ {
3238
+ name: 'authority',
3239
+ isMut: true,
3240
+ isSigner: true,
3241
+ },
3242
+ {
3243
+ name: 'registeredProgramPda',
3244
+ isMut: false,
3245
+ isSigner: false,
3246
+ isOptional: true,
3247
+ },
3248
+ ],
3249
+ args: [
3250
+ {
3251
+ name: 'elements',
3252
+ type: {
3253
+ vec: {
3254
+ array: ['u8', 32],
3255
+ },
3256
+ },
3257
+ },
3258
+ ],
3259
+ },
3260
+ ],
3261
+ accounts: [
3262
+ {
3263
+ name: 'groupAuthority',
3264
+ type: {
3265
+ kind: 'struct',
3266
+ fields: [
3267
+ {
3268
+ name: 'authority',
3269
+ type: 'publicKey',
3270
+ },
3271
+ {
3272
+ name: 'seed',
3273
+ type: {
3274
+ array: ['u8', 32],
3275
+ },
3276
+ },
3277
+ ],
3278
+ },
3279
+ },
3280
+ {
3281
+ name: 'indexedArrayAccount',
3282
+ type: {
3283
+ kind: 'struct',
3284
+ fields: [
3285
+ {
3286
+ name: 'index',
3287
+ type: 'u64',
3288
+ },
3289
+ {
3290
+ name: 'owner',
3291
+ type: 'publicKey',
3292
+ },
3293
+ {
3294
+ name: 'delegate',
3295
+ type: 'publicKey',
3296
+ },
3297
+ {
3298
+ name: 'associatedMerkleTree',
3299
+ type: 'publicKey',
3300
+ },
3301
+ ],
3302
+ },
3303
+ },
3304
+ {
3305
+ name: 'registeredProgram',
3306
+ type: {
3307
+ kind: 'struct',
3308
+ fields: [
3309
+ {
3310
+ name: 'pubkey',
3311
+ type: 'publicKey',
3312
+ },
3313
+ ],
3314
+ },
3315
+ },
3316
+ {
3317
+ name: 'addressQueueAccount',
3318
+ type: {
3319
+ kind: 'struct',
3320
+ fields: [
3321
+ {
3322
+ name: 'index',
3323
+ type: 'u64',
3324
+ },
3325
+ {
3326
+ name: 'owner',
3327
+ type: 'publicKey',
3328
+ },
3329
+ {
3330
+ name: 'delegate',
3331
+ type: 'publicKey',
3332
+ },
3333
+ {
3334
+ name: 'associatedMerkleTree',
3335
+ type: 'publicKey',
3336
+ },
3337
+ ],
3338
+ },
3339
+ },
3340
+ {
3341
+ name: 'addressMerkleTreeAccount',
3342
+ type: {
3343
+ kind: 'struct',
3344
+ fields: [
3345
+ {
3346
+ name: 'index',
3347
+ docs: ['Unique index.'],
3348
+ type: 'u64',
3349
+ },
3350
+ {
3351
+ name: 'nextMerkleTree',
3352
+ docs: ['Public key of the next Merkle tree.'],
3353
+ type: 'publicKey',
3354
+ },
3355
+ {
3356
+ name: 'owner',
3357
+ docs: ['Owner of the Merkle tree.'],
3358
+ type: 'publicKey',
3359
+ },
3360
+ {
3361
+ name: 'delegate',
3362
+ docs: [
3363
+ 'Delegate of the Merkle tree. This will be used for program owned Merkle trees.',
3364
+ ],
3365
+ type: 'publicKey',
3366
+ },
3367
+ {
3368
+ name: 'merkleTreeStruct',
3369
+ type: {
3370
+ array: ['u8', 256],
3371
+ },
3372
+ },
3373
+ {
3374
+ name: 'merkleTreeFilledSubtrees',
3375
+ type: {
3376
+ array: ['u8', 832],
3377
+ },
3378
+ },
3379
+ {
3380
+ name: 'merkleTreeChangelog',
3381
+ type: {
3382
+ array: ['u8', 1220800],
3383
+ },
3384
+ },
3385
+ {
3386
+ name: 'merkleTreeRoots',
3387
+ type: {
3388
+ array: ['u8', 76800],
3389
+ },
3390
+ },
3391
+ {
3392
+ name: 'merkleTreeCanopy',
3393
+ type: {
3394
+ array: ['u8', 65472],
3395
+ },
3396
+ },
3397
+ ],
3398
+ },
3399
+ },
3400
+ {
3401
+ name: 'stateMerkleTreeAccount',
3402
+ docs: [
3403
+ 'Concurrent state Merkle tree used for public compressed transactions.',
3404
+ ],
3405
+ type: {
3406
+ kind: 'struct',
3407
+ fields: [
3408
+ {
3409
+ name: 'index',
3410
+ docs: ['Unique index.'],
3411
+ type: 'u64',
3412
+ },
3413
+ {
3414
+ name: 'nextMerkleTree',
3415
+ docs: ['Public key of the next Merkle tree.'],
3416
+ type: 'publicKey',
3417
+ },
3418
+ {
3419
+ name: 'owner',
3420
+ docs: ['Owner of the Merkle tree.'],
3421
+ type: 'publicKey',
3422
+ },
3423
+ {
3424
+ name: 'delegate',
3425
+ docs: [
3426
+ 'Delegate of the Merkle tree. This will be used for program owned Merkle trees.',
3427
+ ],
3428
+ type: 'publicKey',
3429
+ },
3430
+ {
3431
+ name: 'associatedQueue',
3432
+ type: 'publicKey',
3433
+ },
3434
+ {
3435
+ name: 'stateMerkleTreeStruct',
3436
+ docs: ['Merkle tree for the transaction state.'],
3437
+ type: {
3438
+ array: ['u8', 256],
3439
+ },
3440
+ },
3441
+ {
3442
+ name: 'stateMerkleTreeFilledSubtrees',
3443
+ type: {
3444
+ array: ['u8', 832],
3445
+ },
3446
+ },
3447
+ {
3448
+ name: 'stateMerkleTreeChangelog',
3449
+ type: {
3450
+ array: ['u8', 1220800],
3451
+ },
3452
+ },
3453
+ {
3454
+ name: 'stateMerkleTreeRoots',
3455
+ type: {
3456
+ array: ['u8', 76800],
3457
+ },
3458
+ },
3459
+ {
3460
+ name: 'stateMerkleTreeCanopy',
3461
+ type: {
3462
+ array: ['u8', 65472],
3463
+ },
3464
+ },
3465
+ ],
3466
+ },
3467
+ },
3468
+ ],
3469
+ errors: [
3470
+ {
3471
+ code: 6000,
3472
+ name: 'AddressQueueInsert',
3473
+ msg: 'Failed to insert an element into indexing queue',
3474
+ },
3475
+ {
3476
+ code: 6001,
3477
+ name: 'AddressQueueDequeue',
3478
+ msg: 'Failed to dequeue an element from indexing queue',
3479
+ },
3480
+ {
3481
+ code: 6002,
3482
+ name: 'AddressMerkleTreeInitialize',
3483
+ msg: 'Failed to initialize address Merkle tree',
3484
+ },
3485
+ {
3486
+ code: 6003,
3487
+ name: 'AddressMerkleTreeUpdate',
3488
+ msg: 'Failed to update the address Merkle tree',
3489
+ },
3490
+ {
3491
+ code: 6004,
3492
+ name: 'InvalidIndex',
3493
+ msg: 'No element found under the given index in the queue',
3494
+ },
3495
+ {
3496
+ code: 6005,
3497
+ name: 'BytesToBigint',
3498
+ msg: 'Failed to convert bytes to big integer',
3499
+ },
3500
+ {
3501
+ code: 6006,
3502
+ name: 'IntegerOverflow',
3503
+ msg: 'Integer overflow',
3504
+ },
3505
+ {
3506
+ code: 6007,
3507
+ name: 'InvalidAuthority',
3508
+ msg: 'InvalidAuthority',
3509
+ },
3510
+ {
3511
+ code: 6008,
3512
+ name: 'InvalidVerifier',
3513
+ msg: 'InvalidVerifier',
3514
+ },
3515
+ {
3516
+ code: 6009,
3517
+ name: 'NumberOfLeavesMismatch',
3518
+ msg: 'Leaves <> remaining accounts missmatch. The number of remaining accounts must match the number of leaves.',
3519
+ },
3520
+ {
3521
+ code: 6010,
3522
+ name: 'InvalidNoopPubkey',
3523
+ msg: 'Provided noop program public key is invalid',
3524
+ },
3525
+ {
3526
+ code: 6011,
3527
+ name: 'EventNoChangelogEntry',
3528
+ msg: 'Emitting an event requires at least one changelog entry',
3529
+ },
3530
+ {
3531
+ code: 6012,
3532
+ name: 'NumberOfChangeLogIndicesMismatch',
3533
+ msg: 'Number of change log indices mismatch',
3534
+ },
3535
+ {
3536
+ code: 6013,
3537
+ name: 'NumberOfIndicesMismatch',
3538
+ msg: 'Number of indices mismatch',
3539
+ },
3540
+ {
3541
+ code: 6014,
3542
+ name: 'IndexOutOfBounds',
3543
+ msg: 'IndexOutOfBounds',
3544
+ },
3545
+ {
3546
+ code: 6015,
3547
+ name: 'ElementAlreadyExists',
3548
+ msg: 'ElementAlreadyExists',
3549
+ },
3550
+ {
3551
+ code: 6016,
3552
+ name: 'HashSetFull',
3553
+ msg: 'HashSetFull',
3554
+ },
3555
+ {
3556
+ code: 6017,
3557
+ name: 'NumberOfProofsMismatch',
3558
+ msg: 'NumberOfProofsMismatch',
3559
+ },
3560
+ {
3561
+ code: 6018,
3562
+ name: 'InvalidMerkleProof',
3563
+ msg: 'InvalidMerkleProof',
3564
+ },
3565
+ {
3566
+ code: 6019,
3567
+ name: 'InvalidIndexedArray',
3568
+ msg: 'InvalidIndexedArray',
3569
+ },
3570
+ {
3571
+ code: 6020,
3572
+ name: 'InvalidMerkleTree',
3573
+ msg: 'InvalidMerkleTree',
3574
+ },
3575
+ {
3576
+ code: 6021,
3577
+ name: 'LeafNotFound',
3578
+ msg: 'Could not find the leaf in the queue',
3579
+ },
3580
+ ],
3581
+ };
3582
+
3583
+ const IDL$1 = {
3584
+ version: '0.3.0',
3585
+ name: 'light',
3586
+ constants: [
3587
+ {
3588
+ name: 'AUTHORITY_PDA_SEED',
3589
+ type: 'bytes',
3590
+ value: '[97, 117, 116, 104, 111, 114, 105, 116, 121]',
3591
+ },
3592
+ {
3593
+ name: 'CPI_AUTHORITY_PDA_SEED',
3594
+ type: 'bytes',
3595
+ value: '[99, 112, 105, 95, 97, 117, 116, 104, 111, 114, 105, 116, 121]',
3596
+ },
3597
+ ],
3598
+ instructions: [
3599
+ {
3600
+ name: 'initializeGovernanceAuthority',
3601
+ accounts: [
3602
+ {
3603
+ name: 'authority',
3604
+ isMut: true,
3605
+ isSigner: true,
3606
+ },
3607
+ {
3608
+ name: 'authorityPda',
3609
+ isMut: true,
3610
+ isSigner: false,
3611
+ },
3612
+ {
3613
+ name: 'systemProgram',
3614
+ isMut: false,
3615
+ isSigner: false,
3616
+ },
3617
+ ],
3618
+ args: [
3619
+ {
3620
+ name: 'authority',
3621
+ type: 'publicKey',
3622
+ },
3623
+ {
3624
+ name: 'rewards',
3625
+ type: {
3626
+ vec: 'u64',
3627
+ },
3628
+ },
3629
+ {
3630
+ name: 'bump',
3631
+ type: 'u8',
3632
+ },
3633
+ ],
3634
+ },
3635
+ {
3636
+ name: 'updateGovernanceAuthorityReward',
3637
+ accounts: [
3638
+ {
3639
+ name: 'authority',
3640
+ isMut: true,
3641
+ isSigner: true,
3642
+ },
3643
+ {
3644
+ name: 'authorityPda',
3645
+ isMut: true,
3646
+ isSigner: false,
3647
+ },
3648
+ ],
3649
+ args: [
3650
+ {
3651
+ name: 'reward',
3652
+ type: 'u64',
3653
+ },
3654
+ {
3655
+ name: 'index',
3656
+ type: 'u64',
3657
+ },
3658
+ ],
3659
+ },
3660
+ {
3661
+ name: 'updateGovernanceAuthority',
3662
+ accounts: [
3663
+ {
3664
+ name: 'authority',
3665
+ isMut: true,
3666
+ isSigner: true,
3667
+ },
3668
+ {
3669
+ name: 'authorityPda',
3670
+ isMut: true,
3671
+ isSigner: false,
3672
+ },
3673
+ ],
3674
+ args: [
3675
+ {
3676
+ name: 'bump',
3677
+ type: 'u8',
3678
+ },
3679
+ {
3680
+ name: 'newAuthority',
3681
+ type: 'publicKey',
3682
+ },
3683
+ ],
3684
+ },
3685
+ {
3686
+ name: 'registerSystemProgram',
3687
+ accounts: [
3688
+ {
3689
+ name: 'authority',
3690
+ isMut: true,
3691
+ isSigner: true,
3692
+ },
3693
+ {
3694
+ name: 'authorityPda',
3695
+ isMut: true,
3696
+ isSigner: false,
3697
+ },
3698
+ {
3699
+ name: 'cpiAuthority',
3700
+ isMut: true,
3701
+ isSigner: false,
3702
+ },
3703
+ {
3704
+ name: 'groupPda',
3705
+ isMut: true,
3706
+ isSigner: false,
3707
+ },
3708
+ {
3709
+ name: 'accountCompressionProgram',
3710
+ isMut: false,
3711
+ isSigner: false,
3712
+ },
3713
+ {
3714
+ name: 'systemProgram',
3715
+ isMut: false,
3716
+ isSigner: false,
3717
+ },
3718
+ {
3719
+ name: 'registeredProgramPda',
3720
+ isMut: false,
3721
+ isSigner: false,
3722
+ },
3723
+ ],
3724
+ args: [
3725
+ {
3726
+ name: 'bump',
3727
+ type: 'u8',
3728
+ },
3729
+ {
3730
+ name: 'programId',
3731
+ type: 'publicKey',
3732
+ },
3733
+ ],
3734
+ },
3735
+ ],
3736
+ accounts: [
3737
+ {
3738
+ name: 'lightGovernanceAuthority',
3739
+ type: {
3740
+ kind: 'struct',
3741
+ fields: [
3742
+ {
3743
+ name: 'authority',
3744
+ type: 'publicKey',
3745
+ },
3746
+ {
3747
+ name: 'bump',
3748
+ type: 'u8',
3749
+ },
3750
+ {
3751
+ name: 'padding',
3752
+ type: {
3753
+ array: ['u8', 7],
3754
+ },
3755
+ },
3756
+ {
3757
+ name: 'rewards',
3758
+ type: {
3759
+ vec: 'u64',
3760
+ },
3761
+ },
3762
+ ],
3763
+ },
3764
+ },
3765
+ ],
3766
+ errors: [
3767
+ {
3768
+ code: 6000,
3769
+ name: 'SumCheckFailed',
3770
+ msg: 'Sum check failed',
3771
+ },
3772
+ ],
3773
+ };
3774
+
3775
+ const IDL = {
3776
+ version: '0.3.0',
3777
+ name: 'user_registry',
3778
+ instructions: [
3779
+ {
3780
+ name: 'initializeUserEntry',
3781
+ accounts: [
3782
+ {
3783
+ name: 'signer',
3784
+ isMut: true,
3785
+ isSigner: true,
3786
+ },
3787
+ {
3788
+ name: 'systemProgram',
3789
+ isMut: false,
3790
+ isSigner: false,
3791
+ },
3792
+ {
3793
+ name: 'userEntry',
3794
+ isMut: true,
3795
+ isSigner: false,
3796
+ },
3797
+ ],
3798
+ args: [
3799
+ {
3800
+ name: 'lightPubkey',
3801
+ type: {
3802
+ array: ['u8', 32],
3803
+ },
3804
+ },
3805
+ {
3806
+ name: 'lightEncryptionPubkey',
3807
+ type: {
3808
+ array: ['u8', 32],
3809
+ },
3810
+ },
3811
+ ],
3812
+ },
3813
+ ],
3814
+ accounts: [
3815
+ {
3816
+ name: 'userEntry',
3817
+ type: {
3818
+ kind: 'struct',
3819
+ fields: [
3820
+ {
3821
+ name: 'solanaPubkey',
3822
+ type: {
3823
+ array: ['u8', 32],
3824
+ },
3825
+ },
3826
+ {
3827
+ name: 'lightPubkey',
3828
+ type: {
3829
+ array: ['u8', 32],
3830
+ },
3831
+ },
3832
+ {
3833
+ name: 'lightEncryptionPubkey',
3834
+ type: {
3835
+ array: ['u8', 32],
3836
+ },
3837
+ },
3838
+ ],
3839
+ },
3840
+ },
3841
+ ],
3842
+ };
3843
+
3844
+ // TODO: Clean up
3845
+ exports.UtxoErrorCode = void 0;
3846
+ (function (UtxoErrorCode) {
3847
+ UtxoErrorCode["NEGATIVE_LAMPORTS"] = "NEGATIVE_LAMPORTS";
3848
+ UtxoErrorCode["NOT_U64"] = "NOT_U64";
3849
+ UtxoErrorCode["BLINDING_EXCEEDS_FIELD_SIZE"] = "BLINDING_EXCEEDS_FIELD_SIZE";
3850
+ })(exports.UtxoErrorCode || (exports.UtxoErrorCode = {}));
3851
+ exports.SelectInUtxosErrorCode = void 0;
3852
+ (function (SelectInUtxosErrorCode) {
3853
+ SelectInUtxosErrorCode["FAILED_TO_FIND_UTXO_COMBINATION"] = "FAILED_TO_FIND_UTXO_COMBINATION";
3854
+ SelectInUtxosErrorCode["INVALID_NUMBER_OF_IN_UTXOS"] = "INVALID_NUMBER_OF_IN_UTXOS";
3855
+ })(exports.SelectInUtxosErrorCode || (exports.SelectInUtxosErrorCode = {}));
3856
+ exports.CreateUtxoErrorCode = void 0;
3857
+ (function (CreateUtxoErrorCode) {
3858
+ CreateUtxoErrorCode["OWNER_UNDEFINED"] = "OWNER_UNDEFINED";
3859
+ CreateUtxoErrorCode["INVALID_OUTPUT_UTXO_LENGTH"] = "INVALID_OUTPUT_UTXO_LENGTH";
3860
+ CreateUtxoErrorCode["UTXO_DATA_UNDEFINED"] = "UTXO_DATA_UNDEFINED";
3861
+ })(exports.CreateUtxoErrorCode || (exports.CreateUtxoErrorCode = {}));
3862
+ exports.RpcErrorCode = void 0;
3863
+ (function (RpcErrorCode) {
3864
+ RpcErrorCode["CONNECTION_UNDEFINED"] = "CONNECTION_UNDEFINED";
3865
+ RpcErrorCode["RPC_PUBKEY_UNDEFINED"] = "RPC_PUBKEY_UNDEFINED";
3866
+ RpcErrorCode["RPC_METHOD_NOT_IMPLEMENTED"] = "RPC_METHOD_NOT_IMPLEMENTED";
3867
+ RpcErrorCode["RPC_INVALID"] = "RPC_INVALID";
3868
+ })(exports.RpcErrorCode || (exports.RpcErrorCode = {}));
3869
+ exports.LookupTableErrorCode = void 0;
3870
+ (function (LookupTableErrorCode) {
3871
+ LookupTableErrorCode["LOOK_UP_TABLE_UNDEFINED"] = "LOOK_UP_TABLE_UNDEFINED";
3872
+ LookupTableErrorCode["LOOK_UP_TABLE_NOT_INITIALIZED"] = "LOOK_UP_TABLE_NOT_INITIALIZED";
3873
+ })(exports.LookupTableErrorCode || (exports.LookupTableErrorCode = {}));
3874
+ exports.HashErrorCode = void 0;
3875
+ (function (HashErrorCode) {
3876
+ HashErrorCode["NO_POSEIDON_HASHER_PROVIDED"] = "NO_POSEIDON_HASHER_PROVIDED";
3877
+ })(exports.HashErrorCode || (exports.HashErrorCode = {}));
3878
+ exports.ProofErrorCode = void 0;
3879
+ (function (ProofErrorCode) {
3880
+ ProofErrorCode["INVALID_PROOF"] = "INVALID_PROOF";
3881
+ ProofErrorCode["PROOF_INPUT_UNDEFINED"] = "PROOF_INPUT_UNDEFINED";
3882
+ ProofErrorCode["PROOF_GENERATION_FAILED"] = "PROOF_GENERATION_FAILED";
3883
+ })(exports.ProofErrorCode || (exports.ProofErrorCode = {}));
3884
+ exports.MerkleTreeErrorCode = void 0;
3885
+ (function (MerkleTreeErrorCode) {
3886
+ MerkleTreeErrorCode["MERKLE_TREE_NOT_INITIALIZED"] = "MERKLE_TREE_NOT_INITIALIZED";
3887
+ MerkleTreeErrorCode["SOL_MERKLE_TREE_UNDEFINED"] = "SOL_MERKLE_TREE_UNDEFINED";
3888
+ MerkleTreeErrorCode["MERKLE_TREE_UNDEFINED"] = "MERKLE_TREE_UNDEFINED";
3889
+ MerkleTreeErrorCode["INPUT_UTXO_NOT_INSERTED_IN_MERKLE_TREE"] = "INPUT_UTXO_NOT_INSERTED_IN_MERKLE_TREE";
3890
+ MerkleTreeErrorCode["MERKLE_TREE_INDEX_UNDEFINED"] = "MERKLE_TREE_INDEX_UNDEFINED";
3891
+ MerkleTreeErrorCode["MERKLE_TREE_SET_SPACE_UNDEFINED"] = "MERKLE_TREE_SET_SPACE_UNDEFINED";
3892
+ })(exports.MerkleTreeErrorCode || (exports.MerkleTreeErrorCode = {}));
3893
+ exports.UtilsErrorCode = void 0;
3894
+ (function (UtilsErrorCode) {
3895
+ UtilsErrorCode["ACCOUNT_NAME_UNDEFINED_IN_IDL"] = "ACCOUNT_NAME_UNDEFINED_IN_IDL";
3896
+ UtilsErrorCode["PROPERTY_UNDEFINED"] = "PROPERTY_UNDEFINED";
3897
+ UtilsErrorCode["LOOK_UP_TABLE_CREATION_FAILED"] = "LOOK_UP_TABLE_CREATION_FAILED";
3898
+ UtilsErrorCode["UNSUPPORTED_ARCHITECTURE"] = "UNSUPPORTED_ARCHITECTURE";
3899
+ UtilsErrorCode["UNSUPPORTED_PLATFORM"] = "UNSUPPORTED_PLATFORM";
3900
+ UtilsErrorCode["ACCOUNTS_UNDEFINED"] = "ACCOUNTS_UNDEFINED";
3901
+ UtilsErrorCode["INVALID_NUMBER"] = "INVALID_NUMBER";
3902
+ })(exports.UtilsErrorCode || (exports.UtilsErrorCode = {}));
3903
+ class MetaError extends Error {
3904
+ constructor(code, functionName, codeMessage) {
3905
+ super(`${code}: ${codeMessage}`);
3906
+ this.code = code;
3907
+ this.functionName = functionName;
3908
+ this.codeMessage = codeMessage;
3909
+ }
3910
+ }
3911
+ class UtxoError extends MetaError {
3912
+ }
3913
+ class SelectInUtxosError extends MetaError {
3914
+ }
3915
+ class CreateUtxoError extends MetaError {
3916
+ }
3917
+ class RpcError extends MetaError {
3918
+ }
3919
+ class LookupTableError extends MetaError {
3920
+ }
3921
+ class HashError extends MetaError {
3922
+ }
3923
+ class ProofError extends MetaError {
3924
+ }
3925
+ class MerkleTreeError extends MetaError {
3926
+ }
3927
+ class UtilsError extends MetaError {
3928
+ }
3929
+
3930
+ exports.ALICE = ALICE;
3931
+ exports.AccountCompressionIDL = IDL$2;
3932
+ exports.AccountProofResult = AccountProofResult;
3933
+ exports.BOB = BOB;
3934
+ exports.BalanceResult = BalanceResult;
3935
+ exports.CHARLIE = CHARLIE;
3936
+ exports.CompressedAccountResult = CompressedAccountResult;
3937
+ exports.CompressedAccountsByOwnerResult = CompressedAccountsByOwnerResult;
3938
+ exports.CompressedTokenAccountResult = CompressedTokenAccountResult;
3939
+ exports.CompressedTokenAccountsByOwnerOrDelegateResult = CompressedTokenAccountsByOwnerOrDelegateResult;
3940
+ exports.CreateUtxoError = CreateUtxoError;
3941
+ exports.DAVE = DAVE;
3942
+ exports.DEFAULT_MERKLE_TREE_HEIGHT = DEFAULT_MERKLE_TREE_HEIGHT;
3943
+ exports.DEFAULT_MERKLE_TREE_ROOTS = DEFAULT_MERKLE_TREE_ROOTS;
3944
+ exports.DEFAULT_ZERO = DEFAULT_ZERO;
3945
+ exports.FIELD_SIZE = FIELD_SIZE;
3946
+ exports.HashError = HashError;
3947
+ exports.HealthResult = HealthResult;
3948
+ exports.LightIDL = IDL$1;
3949
+ exports.LightSystemProgram = LightSystemProgram;
3950
+ exports.LookupTableError = LookupTableError;
3951
+ exports.MerkeProofResult = MerkeProofResult;
3952
+ exports.MerkleTree = MerkleTree;
3953
+ exports.MerkleTreeError = MerkleTreeError;
3954
+ exports.MultipleCompressedAccountsResult = MultipleCompressedAccountsResult;
3955
+ exports.MultipleMerkleProofsResult = MultipleMerkleProofsResult;
3956
+ exports.ProofError = ProofError;
3957
+ exports.PspCompressedPdaIDL = IDL$3;
3958
+ exports.PublicKeyToBN254 = PublicKeyToBN254;
3959
+ exports.Rpc = Rpc;
3960
+ exports.RpcError = RpcError;
3961
+ exports.SelectInUtxosError = SelectInUtxosError;
3962
+ exports.SlotResult = SlotResult;
3963
+ exports.TRANSACTION_MERKLE_TREE_ROLLOVER_THRESHOLD = TRANSACTION_MERKLE_TREE_ROLLOVER_THRESHOLD;
3964
+ exports.TestRpc = TestRpc;
3965
+ exports.UTXO_MERGE_MAXIMUM = UTXO_MERGE_MAXIMUM;
3966
+ exports.UTXO_MERGE_THRESHOLD = UTXO_MERGE_THRESHOLD;
3967
+ exports.UserRegistryIDL = IDL;
3968
+ exports.UtilsError = UtilsError;
3969
+ exports.UtxoError = UtxoError;
3970
+ exports.accountCompressionProgram = accountCompressionProgram;
3971
+ exports.airdropSol = airdropSol;
3972
+ exports.bigint254ToPublicKey = bigint254ToPublicKey;
3973
+ exports.bn = bn;
3974
+ exports.bufToDecStr = bufToDecStr;
3975
+ exports.buildAndSignTx = buildAndSignTx;
3976
+ exports.byteArrayToKeypair = byteArrayToKeypair;
3977
+ exports.checkValidityProofShape = checkValidityProofShape;
3978
+ exports.compressLamports = compressLamports;
3979
+ exports.confirmConfig = confirmConfig;
3980
+ exports.confirmTransaction = confirmTransaction;
3981
+ exports.confirmTx = confirmTx;
3982
+ exports.createBN254 = createBN254;
3983
+ exports.createCompressedAccount = createCompressedAccount;
3984
+ exports.createCompressedAccountWithMerkleContext = createCompressedAccountWithMerkleContext;
3985
+ exports.createMerkleContext = createMerkleContext;
3986
+ exports.createRpc = createRpc;
3987
+ exports.createRpcResult = createRpcResult;
3988
+ exports.decompressLamports = decompressLamports;
3989
+ exports.dedupeSigner = dedupeSigner;
3990
+ exports.defaultStaticAccounts = defaultStaticAccounts;
3991
+ exports.defaultStaticAccountsStruct = defaultStaticAccountsStruct;
3992
+ exports.defaultTestStateTreeAccounts = defaultTestStateTreeAccounts;
3993
+ exports.encodeBN254toBase58 = encodeBN254toBase58;
3994
+ exports.getConnection = getConnection;
3995
+ exports.getIndexOrAdd = getIndexOrAdd;
3996
+ exports.getPspAccountCompressionAuthority = getPspAccountCompressionAuthority;
3997
+ exports.getRegisteredProgramPda = getRegisteredProgramPda;
3998
+ exports.getTestKeypair = getTestKeypair;
3999
+ exports.getTestRpc = getTestRpc;
4000
+ exports.hashToBn254FieldSizeLe = hashToBn254FieldSizeLe;
4001
+ exports.initSolOmnibusAccount = initSolOmnibusAccount;
4002
+ exports.jsonRpcResult = jsonRpcResult;
4003
+ exports.jsonRpcResultAndContext = jsonRpcResultAndContext;
4004
+ exports.lightProgram = lightProgram;
4005
+ exports.merkletreePubkey = merkletreePubkey;
4006
+ exports.negateAndCompressProof = negateAndCompressProof;
4007
+ exports.newAccountWithLamports = newAccountWithLamports;
4008
+ exports.noopProgram = noopProgram;
4009
+ exports.nullifierQueuePubkey = nullifierQueuePubkey;
4010
+ exports.packCompressedAccounts = packCompressedAccounts;
4011
+ exports.padOutputStateMerkleTrees = padOutputStateMerkleTrees;
4012
+ exports.parseEvents = parseEvents;
4013
+ exports.parsePublicTransactionEventWithIdl = parsePublicTransactionEventWithIdl;
4014
+ exports.pipe = pipe;
4015
+ exports.placeholderValidityProof = placeholderValidityProof;
4016
+ exports.proofFromJsonStruct = proofFromJsonStruct;
4017
+ exports.pushUniqueItems = pushUniqueItems;
4018
+ exports.sendAndConfirmTx = sendAndConfirmTx;
4019
+ exports.sleep = sleep;
4020
+ exports.sumUpLamports = sumUpLamports;
4021
+ exports.toArray = toArray;
4022
+ exports.toCamelCase = toCamelCase;
4023
+ exports.useWallet = useWallet;
4024
+ exports.validateSameOwner = validateSameOwner;
4025
+ exports.validateSufficientBalance = validateSufficientBalance;
4026
+
4027
+ }));