@interest-protocol/vortex-sdk 12.0.3 → 12.0.4

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.
@@ -18,7 +18,7 @@ interface GetUnspentUtxosWithApiArgs {
18
18
  vortexPool: string | VortexPool;
19
19
  }
20
20
  interface GetUnspentUtxosWithApiAndCommitmentsArgs {
21
- commitments: Pick<Commitment, 'coinType' | 'encryptedOutput'>[];
21
+ commitments: Pick<Commitment, 'coinType' | 'encryptedOutput' | 'index'>[];
22
22
  vortexKeypair: VortexKeypair;
23
23
  vortexSdk: Vortex;
24
24
  vortexPool: string | VortexPool;
@@ -26,7 +26,7 @@ interface GetUnspentUtxosWithApiAndCommitmentsArgs {
26
26
  export declare const getUnspentUtxosWithApi: ({ commitments, vortexKeypair, vortexSdk, vortexPool, }: GetUnspentUtxosWithApiArgs) => Promise<Utxo[]>;
27
27
  export declare const getUnspentUtxosWithApiAndCommitments: ({ commitments, vortexKeypair, vortexSdk, vortexPool, }: GetUnspentUtxosWithApiAndCommitmentsArgs) => Promise<{
28
28
  unspentUtxos: Utxo[];
29
- userCommitments: Pick<Commitment, "coinType" | "encryptedOutput">[];
29
+ userCommitments: Pick<Commitment, "index" | "coinType" | "encryptedOutput">[];
30
30
  }>;
31
31
  export {};
32
32
  //# sourceMappingURL=decrypt.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"decrypt.d.ts","sourceRoot":"","sources":["../../src/utils/decrypt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAe,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGlD,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAIxC,UAAU,mBAAmB;IAC3B,gBAAgB,EAAE,eAAe,CAAC;IAClC,aAAa,EAAE,aAAa,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,UAAU,CAAC;CACjC;AAED,eAAO,MAAM,eAAe,GAAU,6DAKnC,mBAAmB,oBAkCrB,CAAC;AAEF,UAAU,0BAA0B;IAClC,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,aAAa,EAAE,aAAa,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,UAAU,CAAC;CACjC;AAED,UAAU,wCAAwC;IAChD,WAAW,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,iBAAiB,CAAC,EAAE,CAAC;IAChE,aAAa,EAAE,aAAa,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,UAAU,CAAC;CACjC;AAED,eAAO,MAAM,sBAAsB,GAAU,wDAK1C,0BAA0B,oBA2C5B,CAAC;AAEF,eAAO,MAAM,oCAAoC,GAAU,wDAKxD,wCAAwC;;;EAgD1C,CAAC"}
1
+ {"version":3,"file":"decrypt.d.ts","sourceRoot":"","sources":["../../src/utils/decrypt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAe,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGlD,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAIxC,UAAU,mBAAmB;IAC3B,gBAAgB,EAAE,eAAe,CAAC;IAClC,aAAa,EAAE,aAAa,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,UAAU,CAAC;CACjC;AAED,eAAO,MAAM,eAAe,GAAU,6DAKnC,mBAAmB,oBAyCrB,CAAC;AAEF,UAAU,0BAA0B;IAClC,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,aAAa,EAAE,aAAa,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,UAAU,CAAC;CACjC;AAED,UAAU,wCAAwC;IAChD,WAAW,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,iBAAiB,GAAG,OAAO,CAAC,EAAE,CAAC;IAC1E,aAAa,EAAE,aAAa,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,UAAU,CAAC;CACjC;AAED,eAAO,MAAM,sBAAsB,GAAU,wDAK1C,0BAA0B,oBA8C5B,CAAC;AAEF,eAAO,MAAM,oCAAoC,GAAU,wDAKxD,wCAAwC;;;EAoD1C,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@interest-protocol/vortex-sdk",
3
- "version": "12.0.3",
3
+ "version": "12.0.4",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "module": "./dist/index.mjs",
@@ -37,8 +37,8 @@
37
37
  "rimraf": "^6.1.2",
38
38
  "ts-jest": "^29.4.6",
39
39
  "tsup": "^8.5.1",
40
- "@interest-protocol/typescript-config": "1.0.0",
41
- "@interest-protocol/prettier-config": "1.0.0"
40
+ "@interest-protocol/prettier-config": "1.0.0",
41
+ "@interest-protocol/typescript-config": "1.0.0"
42
42
  },
43
43
  "publishConfig": {
44
44
  "access": "public",
@@ -270,6 +270,108 @@ describe(VortexKeypair.name, () => {
270
270
  });
271
271
  });
272
272
 
273
+ describe('BigInt encryption/decryption', () => {
274
+ it('should encrypt and decrypt a BigInt value', () => {
275
+ const keypair = VortexKeypair.generate();
276
+ const originalValue = 123456n;
277
+
278
+ const encrypted = VortexKeypair.encryptBigIntFor(
279
+ originalValue,
280
+ keypair.encryptionKey
281
+ );
282
+ const decrypted = keypair.decryptBigInt(encrypted);
283
+
284
+ expect(decrypted).toBe(originalValue);
285
+ });
286
+
287
+ it('should handle zero', () => {
288
+ const keypair = VortexKeypair.generate();
289
+ const originalValue = 0n;
290
+
291
+ const encrypted = VortexKeypair.encryptBigIntFor(
292
+ originalValue,
293
+ keypair.encryptionKey
294
+ );
295
+ const decrypted = keypair.decryptBigInt(encrypted);
296
+
297
+ expect(decrypted).toBe(originalValue);
298
+ });
299
+
300
+ it('should handle large BigInt values', () => {
301
+ const keypair = VortexKeypair.generate();
302
+ const originalValue = BigInt(
303
+ '21888242871839275222246405745257275088548364400416034343698204186575808495616'
304
+ );
305
+
306
+ const encrypted = VortexKeypair.encryptBigIntFor(
307
+ originalValue,
308
+ keypair.encryptionKey
309
+ );
310
+ const decrypted = keypair.decryptBigInt(encrypted);
311
+
312
+ expect(decrypted).toBe(originalValue);
313
+ });
314
+
315
+ it('should fail to decrypt with wrong keypair', () => {
316
+ const keypair1 = VortexKeypair.generate();
317
+ const keypair2 = VortexKeypair.generate();
318
+ const originalValue = 123456n;
319
+
320
+ const encrypted = VortexKeypair.encryptBigIntFor(
321
+ originalValue,
322
+ keypair1.encryptionKey
323
+ );
324
+
325
+ expect(() => keypair2.decryptBigInt(encrypted)).toThrow(
326
+ 'Decryption failed: HMAC verification failed'
327
+ );
328
+ });
329
+
330
+ it('should produce different ciphertexts for same value (random nonce)', () => {
331
+ const keypair = VortexKeypair.generate();
332
+ const value = 999999n;
333
+
334
+ const encrypted1 = VortexKeypair.encryptBigIntFor(
335
+ value,
336
+ keypair.encryptionKey
337
+ );
338
+ const encrypted2 = VortexKeypair.encryptBigIntFor(
339
+ value,
340
+ keypair.encryptionKey
341
+ );
342
+
343
+ expect(encrypted1).not.toBe(encrypted2);
344
+
345
+ // But both decrypt to the same value
346
+ expect(keypair.decryptBigInt(encrypted1)).toBe(value);
347
+ expect(keypair.decryptBigInt(encrypted2)).toBe(value);
348
+ });
349
+
350
+ it('should ALWAYS fail with wrong keypair - 100 iterations', () => {
351
+ const correctKeypair = VortexKeypair.generate();
352
+ const value = BigInt('12345678901234567890');
353
+
354
+ const encrypted = VortexKeypair.encryptBigIntFor(
355
+ value,
356
+ correctKeypair.encryptionKey
357
+ );
358
+
359
+ let failureCount = 0;
360
+ const iterations = 100;
361
+
362
+ for (let i = 0; i < iterations; i++) {
363
+ const wrongKeypair = VortexKeypair.generate();
364
+ try {
365
+ wrongKeypair.decryptBigInt(encrypted);
366
+ } catch {
367
+ failureCount++;
368
+ }
369
+ }
370
+
371
+ expect(failureCount).toBe(iterations);
372
+ });
373
+ });
374
+
273
375
  describe('toString/address', () => {
274
376
  it('should produce consistent string representation', () => {
275
377
  const keypair = VortexKeypair.generate();
@@ -24,23 +24,30 @@ export const getUnspentUtxos = async ({
24
24
  }: GetUnspentUtxosArgs) => {
25
25
  const commitments = parseNewCommitmentEvent(commitmentEvents);
26
26
 
27
- const allUtxos = [] as UtxoPayload[];
28
-
29
27
  const vortexObjectId =
30
28
  typeof vortexPool === 'string' ? vortexPool : vortexPool.objectId;
31
29
 
30
+ const decryptedWithIndex: { utxo: UtxoPayload; chainIndex: bigint }[] = [];
31
+
32
32
  commitments.forEach((commitment) => {
33
33
  try {
34
34
  const utxo = vortexKeypair.decryptUtxo(commitment.encryptedOutput);
35
- allUtxos.push(utxo);
35
+ // Use index from chain (commitment.index) instead of decrypted index
36
+ // to avoid concurrency/latency issues where encrypted index can be stale
37
+ decryptedWithIndex.push({ utxo, chainIndex: commitment.index });
36
38
  } catch {
37
39
  // HMAC verification failed - wrong keypair
38
40
  }
39
41
  });
40
42
 
41
- const utxos = allUtxos.map(
42
- (utxo) =>
43
- new Utxo({ ...utxo, keypair: vortexKeypair, vortexPool: vortexObjectId })
43
+ const utxos = decryptedWithIndex.map(
44
+ ({ utxo, chainIndex }) =>
45
+ new Utxo({
46
+ ...utxo,
47
+ index: chainIndex, // Override with on-chain index
48
+ keypair: vortexKeypair,
49
+ vortexPool: vortexObjectId,
50
+ })
44
51
  );
45
52
 
46
53
  const nullifiers = utxos.map((utxo) => utxo.nullifier());
@@ -65,7 +72,7 @@ interface GetUnspentUtxosWithApiArgs {
65
72
  }
66
73
 
67
74
  interface GetUnspentUtxosWithApiAndCommitmentsArgs {
68
- commitments: Pick<Commitment, 'coinType' | 'encryptedOutput'>[];
75
+ commitments: Pick<Commitment, 'coinType' | 'encryptedOutput' | 'index'>[];
69
76
  vortexKeypair: VortexKeypair;
70
77
  vortexSdk: Vortex;
71
78
  vortexPool: string | VortexPool;
@@ -77,7 +84,7 @@ export const getUnspentUtxosWithApi = async ({
77
84
  vortexSdk,
78
85
  vortexPool,
79
86
  }: GetUnspentUtxosWithApiArgs) => {
80
- const allUtxos = [] as UtxoPayload[];
87
+ const decryptedWithIndex: { utxo: UtxoPayload; chainIndex: bigint }[] = [];
81
88
 
82
89
  const vortexObject = await vortexSdk.resolveVortexPool(vortexPool);
83
90
 
@@ -92,16 +99,19 @@ export const getUnspentUtxosWithApi = async ({
92
99
  Uint8Array.from(commitment.encryptedOutput)
93
100
  );
94
101
  const utxo = vortexKeypair.decryptUtxo(encryptedOutputHex);
95
- allUtxos.push(utxo);
102
+ // Use index from chain (commitment.index) instead of decrypted index
103
+ // to avoid concurrency/latency issues where encrypted index can be stale
104
+ decryptedWithIndex.push({ utxo, chainIndex: BigInt(commitment.index) });
96
105
  } catch {
97
106
  // HMAC verification failed - wrong keypair
98
107
  }
99
108
  });
100
109
 
101
- const utxos = allUtxos.map(
102
- (utxo) =>
110
+ const utxos = decryptedWithIndex.map(
111
+ ({ utxo, chainIndex }) =>
103
112
  new Utxo({
104
113
  ...utxo,
114
+ index: chainIndex, // Override with on-chain index
105
115
  keypair: vortexKeypair,
106
116
  vortexPool: vortexObject.objectId,
107
117
  })
@@ -127,8 +137,8 @@ export const getUnspentUtxosWithApiAndCommitments = async ({
127
137
  vortexSdk,
128
138
  vortexPool,
129
139
  }: GetUnspentUtxosWithApiAndCommitmentsArgs) => {
130
- const allUtxos = [] as UtxoPayload[];
131
- const userCommitments = [] as Pick<Commitment, 'coinType' | 'encryptedOutput'>[];
140
+ const decryptedWithIndex: { utxo: UtxoPayload; chainIndex: bigint }[] = [];
141
+ const userCommitments = [] as Pick<Commitment, 'coinType' | 'encryptedOutput' | 'index'>[];
132
142
 
133
143
  const vortexObject = await vortexSdk.resolveVortexPool(vortexPool);
134
144
 
@@ -146,17 +156,21 @@ export const getUnspentUtxosWithApiAndCommitments = async ({
146
156
  userCommitments.push({
147
157
  coinType: commitment.coinType,
148
158
  encryptedOutput: commitment.encryptedOutput,
159
+ index: commitment.index,
149
160
  });
150
- allUtxos.push(utxo);
161
+ // Use index from chain (commitment.index) instead of decrypted index
162
+ // to avoid concurrency/latency issues where encrypted index can be stale
163
+ decryptedWithIndex.push({ utxo, chainIndex: BigInt(commitment.index) });
151
164
  } catch {
152
165
  // HMAC verification failed - wrong keypair
153
166
  }
154
167
  });
155
168
 
156
- const utxos = allUtxos.map(
157
- (utxo) =>
169
+ const utxos = decryptedWithIndex.map(
170
+ ({ utxo, chainIndex }) =>
158
171
  new Utxo({
159
172
  ...utxo,
173
+ index: chainIndex, // Override with on-chain index
160
174
  keypair: vortexKeypair,
161
175
  vortexPool: vortexObject.objectId,
162
176
  })