@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.
- package/dist/index.js +23 -9
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +23 -9
- package/dist/index.mjs.map +1 -1
- package/dist/utils/decrypt.d.ts +2 -2
- package/dist/utils/decrypt.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/entities/keypair.spec.ts +102 -0
- package/src/utils/decrypt.ts +30 -16
package/dist/utils/decrypt.d.ts
CHANGED
|
@@ -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,
|
|
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
|
+
"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/
|
|
41
|
-
"@interest-protocol/
|
|
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();
|
package/src/utils/decrypt.ts
CHANGED
|
@@ -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
|
-
|
|
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 =
|
|
42
|
-
(utxo) =>
|
|
43
|
-
new Utxo({
|
|
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
|
|
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
|
-
|
|
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 =
|
|
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
|
|
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
|
-
|
|
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 =
|
|
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
|
})
|