@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.
- package/README.md +58 -0
- package/dist/cjs/index.cjs +4031 -0
- package/dist/es/index.js +3988 -0
- package/dist/types/actions/common.d.ts +3 -0
- package/dist/types/actions/compress-lamports.d.ts +16 -0
- package/dist/types/actions/decompress-lamports.d.ts +16 -0
- package/dist/types/actions/index.d.ts +4 -0
- package/dist/types/actions/init-sol-omnibus-account.d.ts +13 -0
- package/dist/types/constants.d.ts +34 -0
- package/dist/types/errors.d.ts +74 -0
- package/dist/types/idls/account_compression.d.ts +932 -0
- package/dist/types/idls/index.d.ts +5 -0
- package/dist/types/idls/light.d.ts +192 -0
- package/dist/types/idls/psp_compressed_pda.d.ts +607 -0
- package/dist/types/idls/user_registry.d.ts +69 -0
- package/dist/types/index.d.ts +12 -0
- package/dist/types/instruction/index.d.ts +1 -0
- package/dist/types/instruction/pack-compressed-accounts.d.ts +30 -0
- package/dist/types/programs/compressed-pda.d.ts +148 -0
- package/dist/types/programs/index.d.ts +1 -0
- package/dist/types/rpc-interface.d.ts +430 -0
- package/dist/types/rpc.d.ts +26 -0
- package/dist/types/state/BN254.d.ts +20 -0
- package/dist/types/state/compressed-account.d.ts +35 -0
- package/dist/types/state/index.d.ts +3 -0
- package/dist/types/state/types.d.ts +108 -0
- package/dist/types/test-utils/common.d.ts +32 -0
- package/dist/types/test-utils/index.d.ts +5 -0
- package/dist/types/test-utils/merkle-tree.d.ts +92 -0
- package/dist/types/test-utils/parse-event.d.ts +7 -0
- package/dist/types/test-utils/parse-validity-proof.d.ts +20 -0
- package/dist/types/test-utils/test-rpc.d.ts +51 -0
- package/dist/types/utils/airdrop.d.ts +7 -0
- package/dist/types/utils/conversion.d.ts +10 -0
- package/dist/types/utils/index.d.ts +6 -0
- package/dist/types/utils/pipe.d.ts +2 -0
- package/dist/types/utils/send-and-confirm.d.ts +18 -0
- package/dist/types/utils/sleep.d.ts +1 -0
- package/dist/types/utils/validation.d.ts +4 -0
- package/dist/types/wallet/index.d.ts +1 -0
- package/dist/types/wallet/interface.d.ts +25 -0
- package/dist/types/wallet/use-wallet.d.ts +9 -0
- package/dist/umd/index.js +4027 -0
- 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
|
+
}));
|