@cloak.dev/sdk 0.1.8 → 0.2.1
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/LICENSE +202 -0
- package/README.md +573 -205
- package/dist/chunk-KNM6K5NG.js +507 -0
- package/dist/index.cjs +6039 -4624
- package/dist/index.d.cts +1817 -862
- package/dist/index.d.ts +1817 -862
- package/dist/index.js +4624 -3525
- package/dist/{utxo-LSTVI4HH.js → utxo-XPEGGWZ6.js} +5 -3
- package/package.json +51 -20
- package/dist/chunk-2SOX3JNO.js +0 -255
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
NATIVE_SOL_MINT,
|
|
3
|
-
bigintToBytes32,
|
|
3
|
+
bigintToBytes322 as bigintToBytes32,
|
|
4
4
|
bigintToHex,
|
|
5
5
|
computeCommitment,
|
|
6
6
|
computeNullifier,
|
|
@@ -11,14 +11,15 @@ import {
|
|
|
11
11
|
deriveUtxoKeypairFromSpendKey,
|
|
12
12
|
deserializeUtxo,
|
|
13
13
|
generateUtxoKeypair,
|
|
14
|
-
hexToBigint,
|
|
14
|
+
hexToBigint2 as hexToBigint,
|
|
15
15
|
pubkeyToFieldElement,
|
|
16
|
+
pubkeyToFieldLimbs,
|
|
16
17
|
randomFieldElement,
|
|
17
18
|
selectUtxos,
|
|
18
19
|
serializeUtxo,
|
|
19
20
|
sumUtxoAmounts,
|
|
20
21
|
utxoEquals
|
|
21
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-KNM6K5NG.js";
|
|
22
23
|
export {
|
|
23
24
|
NATIVE_SOL_MINT,
|
|
24
25
|
bigintToBytes32,
|
|
@@ -34,6 +35,7 @@ export {
|
|
|
34
35
|
generateUtxoKeypair,
|
|
35
36
|
hexToBigint,
|
|
36
37
|
pubkeyToFieldElement,
|
|
38
|
+
pubkeyToFieldLimbs,
|
|
37
39
|
randomFieldElement,
|
|
38
40
|
selectUtxos,
|
|
39
41
|
serializeUtxo,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloak.dev/sdk",
|
|
3
3
|
"description": "Shield, send, and swap on Solana privately — TypeScript SDK with UTXO-based zero-knowledge transactions",
|
|
4
|
-
"version": "0.1
|
|
4
|
+
"version": "0.2.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
7
7
|
"module": "dist/index.js",
|
|
@@ -17,25 +17,28 @@
|
|
|
17
17
|
"build": "tsup src/index.ts --clean --format cjs,esm --dts --external fs --external path --external crypto",
|
|
18
18
|
"lint": "tsc --noEmit",
|
|
19
19
|
"test": "NODE_OPTIONS=--experimental-vm-modules jest",
|
|
20
|
-
"test:examples": "CLOAK_EXAMPLE_DRY_RUN=1 tsx examples/fast-send.ts && CLOAK_EXAMPLE_DRY_RUN=1 tsx examples/fast-usdc-send.ts && CLOAK_EXAMPLE_DRY_RUN=1 tsx examples/usdc-pool-transfer.ts && CLOAK_EXAMPLE_DRY_RUN=1 tsx examples/transfer.ts && CLOAK_EXAMPLE_DRY_RUN=1 tsx examples/swap.ts && CLOAK_EXAMPLE_DRY_RUN=1 tsx examples/swap-recovery.ts && CLOAK_EXAMPLE_DRY_RUN=1 tsx examples/history-scan.ts",
|
|
21
20
|
"test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch",
|
|
22
21
|
"test:coverage": "NODE_OPTIONS=--experimental-vm-modules jest --coverage",
|
|
23
22
|
"test:verbose": "NODE_OPTIONS=--experimental-vm-modules jest --verbose",
|
|
24
23
|
"prepare": "npm run build",
|
|
25
|
-
"prepublishOnly": "npm run build",
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"example:
|
|
32
|
-
"example:
|
|
33
|
-
"example:
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"example:
|
|
37
|
-
"
|
|
38
|
-
"
|
|
24
|
+
"prepublishOnly": "npm run build && node scripts/verify-dist-matches-src.mjs",
|
|
25
|
+
"verify:dist": "node scripts/verify-dist-matches-src.mjs",
|
|
26
|
+
"script:admin-compliance": "tsx scripts/admin-compliance.ts",
|
|
27
|
+
"script:compliance-smoke": "tsx scripts/compliance-smoke.ts",
|
|
28
|
+
"fixture:chain-note": "tsx scripts/gen-chain-note-v3-fixture.ts",
|
|
29
|
+
"test:examples": "CLOAK_EXAMPLE_DRY_RUN=1 tsx examples/sol/deposit.ts && CLOAK_EXAMPLE_DRY_RUN=1 tsx examples/sol/private-send.ts && CLOAK_EXAMPLE_DRY_RUN=1 tsx examples/sol/withdraw.ts && CLOAK_EXAMPLE_DRY_RUN=1 tsx examples/sol/swap.ts && CLOAK_EXAMPLE_DRY_RUN=1 tsx examples/spl/deposit.ts && CLOAK_EXAMPLE_DRY_RUN=1 tsx examples/spl/private-send.ts && CLOAK_EXAMPLE_DRY_RUN=1 tsx examples/spl/withdraw.ts && CLOAK_EXAMPLE_DRY_RUN=1 tsx examples/viewing-keys.ts",
|
|
30
|
+
"example:deposit": "tsx examples/sol/deposit.ts",
|
|
31
|
+
"example:private-send": "tsx examples/sol/private-send.ts",
|
|
32
|
+
"example:withdraw": "tsx examples/sol/withdraw.ts",
|
|
33
|
+
"example:swap": "tsx examples/sol/swap.ts",
|
|
34
|
+
"example:spl-deposit": "tsx examples/spl/deposit.ts",
|
|
35
|
+
"example:spl-private-send": "tsx examples/spl/private-send.ts",
|
|
36
|
+
"example:spl-withdraw": "tsx examples/spl/withdraw.ts",
|
|
37
|
+
"example:viewing-keys": "tsx examples/viewing-keys.ts",
|
|
38
|
+
"example:swap-usdc": "OUTPUT_TOKEN_MINT=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v SWAP_MARKER_TAG=swap-usdc tsx examples/sol/swap.ts",
|
|
39
|
+
"example:swap-brz": "TRY_BRZ_FIRST=true OUTPUT_TOKEN_MINT=FtgGSFADXBtroxq8VCausXRr2of47QBf5AS1NtZCu4GD FALLBACK_OUTPUT_TOKEN_MINT=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v SWAP_MARKER_TAG=swap-brz tsx examples/sol/swap.ts",
|
|
40
|
+
"soak:swap": "CLOAK_SOAK_NAME=swap CLOAK_SOAK_RUN_CMD='npx tsx examples/sol/swap.ts' CLOAK_FORCE_RELAY_MERKLE_TREE=1 tsx scripts/soak-runner.ts",
|
|
41
|
+
"soak:withdraw": "CLOAK_SOAK_NAME=withdraw CLOAK_SOAK_RUN_CMD='npx tsx examples/sol/withdraw.ts' CLOAK_FORCE_RELAY_MERKLE_TREE=1 tsx scripts/soak-runner.ts"
|
|
39
42
|
},
|
|
40
43
|
"keywords": [
|
|
41
44
|
"solana",
|
|
@@ -68,8 +71,7 @@
|
|
|
68
71
|
"ffjavascript": "^0.3.0",
|
|
69
72
|
"snarkjs": "0.7.6",
|
|
70
73
|
"tweetnacl": "^1.0.3",
|
|
71
|
-
"tweetnacl-util": "^0.15.1"
|
|
72
|
-
"yaml": "^2.8.3"
|
|
74
|
+
"tweetnacl-util": "^0.15.1"
|
|
73
75
|
},
|
|
74
76
|
"devDependencies": {
|
|
75
77
|
"@coral-xyz/anchor": "^0.32.1",
|
|
@@ -113,9 +115,38 @@
|
|
|
113
115
|
},
|
|
114
116
|
"overrides": {
|
|
115
117
|
"glob": "^10.5.0",
|
|
116
|
-
"js-yaml": "^3.
|
|
118
|
+
"js-yaml": "^3.15.1",
|
|
117
119
|
"diff": "^4.0.4",
|
|
118
120
|
"bigint-buffer": "npm:bigint-buffer-fixed@^1.1.6",
|
|
119
|
-
"tar": "^7.5.
|
|
121
|
+
"tar": "^7.5.21",
|
|
122
|
+
"handlebars": "^4.7.9",
|
|
123
|
+
"underscore": "^1.13.8",
|
|
124
|
+
"ip-address": "^10.4.0",
|
|
125
|
+
"@tootallnate/once": "^2.0.1",
|
|
126
|
+
"@babel/core": "^7.29.7",
|
|
127
|
+
"ws": "^8.21.0",
|
|
128
|
+
"picomatch@2": "^2.3.2",
|
|
129
|
+
"picomatch@4": "^4.0.7",
|
|
130
|
+
"brace-expansion@1": "^1.1.18",
|
|
131
|
+
"brace-expansion@2": "^2.1.4"
|
|
132
|
+
},
|
|
133
|
+
"resolutions": {
|
|
134
|
+
"glob": "^10.5.0",
|
|
135
|
+
"js-yaml": "^3.15.1",
|
|
136
|
+
"diff": "^4.0.4",
|
|
137
|
+
"bigint-buffer": "npm:bigint-buffer-fixed@^1.1.6",
|
|
138
|
+
"tar": "^7.5.21",
|
|
139
|
+
"handlebars": "^4.7.9",
|
|
140
|
+
"underscore": "^1.13.8",
|
|
141
|
+
"ip-address": "^10.4.0",
|
|
142
|
+
"@tootallnate/once": "^2.0.1",
|
|
143
|
+
"@babel/core": "^7.29.7",
|
|
144
|
+
"ws": "^8.21.0",
|
|
145
|
+
"jest-util/picomatch": "^2.3.2",
|
|
146
|
+
"anymatch/picomatch": "^2.3.2",
|
|
147
|
+
"micromatch/picomatch": "^2.3.2",
|
|
148
|
+
"picomatch": "^4.0.7",
|
|
149
|
+
"test-exclude/**/brace-expansion": "^1.1.18",
|
|
150
|
+
"brace-expansion": "^2.1.4"
|
|
120
151
|
}
|
|
121
152
|
}
|
package/dist/chunk-2SOX3JNO.js
DELETED
|
@@ -1,255 +0,0 @@
|
|
|
1
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
-
}) : x)(function(x) {
|
|
4
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
-
});
|
|
7
|
-
|
|
8
|
-
// src/core/utxo.ts
|
|
9
|
-
import { PublicKey } from "@solana/web3.js";
|
|
10
|
-
import { buildPoseidon } from "circomlibjs";
|
|
11
|
-
import { blake3 } from "@noble/hashes/blake3";
|
|
12
|
-
var FIELD_MODULUS = BigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
|
13
|
-
var UTXO_KEY_DOMAIN = new TextEncoder().encode("cloak_utxo_priv_v1");
|
|
14
|
-
var NATIVE_SOL_MINT = new PublicKey("So11111111111111111111111111111111111111112");
|
|
15
|
-
var poseidonInstance = null;
|
|
16
|
-
async function getPoseidon() {
|
|
17
|
-
if (!poseidonInstance) {
|
|
18
|
-
poseidonInstance = await buildPoseidon();
|
|
19
|
-
}
|
|
20
|
-
return poseidonInstance;
|
|
21
|
-
}
|
|
22
|
-
function randomFieldElement() {
|
|
23
|
-
const bytes = new Uint8Array(32);
|
|
24
|
-
if (typeof crypto !== "undefined" && crypto.getRandomValues) {
|
|
25
|
-
crypto.getRandomValues(bytes);
|
|
26
|
-
} else {
|
|
27
|
-
const { randomBytes } = __require("crypto");
|
|
28
|
-
const nodeBytes = randomBytes(32);
|
|
29
|
-
for (let i = 0; i < 32; i++) {
|
|
30
|
-
bytes[i] = nodeBytes[i];
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
let value = BigInt(0);
|
|
34
|
-
for (let i = 0; i < 32; i++) {
|
|
35
|
-
value = value << BigInt(8) | BigInt(bytes[i]);
|
|
36
|
-
}
|
|
37
|
-
return value % (FIELD_MODULUS >> BigInt(4));
|
|
38
|
-
}
|
|
39
|
-
async function generateUtxoKeypair() {
|
|
40
|
-
const poseidon = await getPoseidon();
|
|
41
|
-
const privateKey = randomFieldElement();
|
|
42
|
-
const publicKeyHash = poseidon([privateKey, BigInt(0)]);
|
|
43
|
-
const publicKey = poseidon.F.toObject(publicKeyHash);
|
|
44
|
-
return { privateKey, publicKey };
|
|
45
|
-
}
|
|
46
|
-
async function deriveUtxoKeypairFromSpendKey(skSpend) {
|
|
47
|
-
if (!skSpend || !(skSpend instanceof Uint8Array) || skSpend.length !== 32) {
|
|
48
|
-
throw new Error("skSpend must be 32 bytes");
|
|
49
|
-
}
|
|
50
|
-
const preimage = new Uint8Array(UTXO_KEY_DOMAIN.length + skSpend.length);
|
|
51
|
-
preimage.set(UTXO_KEY_DOMAIN, 0);
|
|
52
|
-
preimage.set(skSpend, UTXO_KEY_DOMAIN.length);
|
|
53
|
-
const hash = blake3(preimage);
|
|
54
|
-
let value = BigInt(0);
|
|
55
|
-
for (let i = 0; i < 32; i++) {
|
|
56
|
-
value = value << BigInt(8) | BigInt(hash[i]);
|
|
57
|
-
}
|
|
58
|
-
const privateKey = value % (FIELD_MODULUS >> BigInt(4));
|
|
59
|
-
const publicKey = await derivePublicKey(privateKey);
|
|
60
|
-
return { privateKey, publicKey };
|
|
61
|
-
}
|
|
62
|
-
async function derivePublicKey(privateKey) {
|
|
63
|
-
const poseidon = await getPoseidon();
|
|
64
|
-
const hash = poseidon([privateKey, BigInt(0)]);
|
|
65
|
-
return poseidon.F.toObject(hash);
|
|
66
|
-
}
|
|
67
|
-
async function createUtxo(amount, keypair, mintAddress = NATIVE_SOL_MINT) {
|
|
68
|
-
const blinding = randomFieldElement();
|
|
69
|
-
const utxo = {
|
|
70
|
-
amount,
|
|
71
|
-
keypair,
|
|
72
|
-
blinding,
|
|
73
|
-
mintAddress
|
|
74
|
-
};
|
|
75
|
-
utxo.commitment = await computeCommitment(utxo);
|
|
76
|
-
return utxo;
|
|
77
|
-
}
|
|
78
|
-
async function createZeroUtxo(mintAddress = NATIVE_SOL_MINT, salt) {
|
|
79
|
-
const poseidon = await getPoseidon();
|
|
80
|
-
const effectiveSalt = salt ?? randomFieldElement();
|
|
81
|
-
const publicKeyHash = poseidon([effectiveSalt, BigInt(0)]);
|
|
82
|
-
const publicKey = poseidon.F.toObject(publicKeyHash);
|
|
83
|
-
const keypair = { privateKey: effectiveSalt, publicKey };
|
|
84
|
-
const utxo = {
|
|
85
|
-
amount: BigInt(0),
|
|
86
|
-
keypair,
|
|
87
|
-
blinding: BigInt(0),
|
|
88
|
-
mintAddress
|
|
89
|
-
};
|
|
90
|
-
utxo.commitment = await computeCommitment(utxo);
|
|
91
|
-
utxo.index = 0;
|
|
92
|
-
return utxo;
|
|
93
|
-
}
|
|
94
|
-
function pubkeyToFieldElement(pubkey) {
|
|
95
|
-
const bytes = pubkey.toBytes();
|
|
96
|
-
let value = BigInt(0);
|
|
97
|
-
for (let i = 0; i < 32; i++) {
|
|
98
|
-
value = value << BigInt(8) | BigInt(bytes[i]);
|
|
99
|
-
}
|
|
100
|
-
return value % FIELD_MODULUS;
|
|
101
|
-
}
|
|
102
|
-
async function computeCommitment(utxo) {
|
|
103
|
-
const poseidon = await getPoseidon();
|
|
104
|
-
const mintField = pubkeyToFieldElement(utxo.mintAddress);
|
|
105
|
-
const hash = poseidon([
|
|
106
|
-
utxo.amount,
|
|
107
|
-
utxo.keypair.publicKey,
|
|
108
|
-
utxo.blinding,
|
|
109
|
-
mintField
|
|
110
|
-
]);
|
|
111
|
-
return poseidon.F.toObject(hash);
|
|
112
|
-
}
|
|
113
|
-
async function computeSignature(privateKey, commitment, pathIndex) {
|
|
114
|
-
const poseidon = await getPoseidon();
|
|
115
|
-
const hash = poseidon([privateKey, commitment, pathIndex]);
|
|
116
|
-
return poseidon.F.toObject(hash);
|
|
117
|
-
}
|
|
118
|
-
async function computeNullifier(utxo) {
|
|
119
|
-
if (utxo.index === void 0) {
|
|
120
|
-
throw new Error("UTXO must have an index to compute nullifier");
|
|
121
|
-
}
|
|
122
|
-
const poseidon = await getPoseidon();
|
|
123
|
-
const commitment = utxo.commitment ?? await computeCommitment(utxo);
|
|
124
|
-
const pathIndex = BigInt(utxo.index);
|
|
125
|
-
const signature = await computeSignature(
|
|
126
|
-
utxo.keypair.privateKey,
|
|
127
|
-
commitment,
|
|
128
|
-
pathIndex
|
|
129
|
-
);
|
|
130
|
-
const hash = poseidon([commitment, pathIndex, signature]);
|
|
131
|
-
return poseidon.F.toObject(hash);
|
|
132
|
-
}
|
|
133
|
-
function serializeUtxo(utxo) {
|
|
134
|
-
const buffer = new ArrayBuffer(128);
|
|
135
|
-
const view = new DataView(buffer);
|
|
136
|
-
const amountBytes = bigintToBytes(utxo.amount, 8);
|
|
137
|
-
for (let i = 0; i < 8; i++) {
|
|
138
|
-
view.setUint8(i, amountBytes[i]);
|
|
139
|
-
}
|
|
140
|
-
const privkeyBytes = bigintToBytes(utxo.keypair.privateKey, 32);
|
|
141
|
-
for (let i = 0; i < 32; i++) {
|
|
142
|
-
view.setUint8(8 + i, privkeyBytes[i]);
|
|
143
|
-
}
|
|
144
|
-
const blindingBytes = bigintToBytes(utxo.blinding, 32);
|
|
145
|
-
for (let i = 0; i < 32; i++) {
|
|
146
|
-
view.setUint8(40 + i, blindingBytes[i]);
|
|
147
|
-
}
|
|
148
|
-
const mintBytes = utxo.mintAddress.toBytes();
|
|
149
|
-
for (let i = 0; i < 32; i++) {
|
|
150
|
-
view.setUint8(72 + i, mintBytes[i]);
|
|
151
|
-
}
|
|
152
|
-
view.setUint32(104, utxo.index ?? 0, true);
|
|
153
|
-
return new Uint8Array(buffer);
|
|
154
|
-
}
|
|
155
|
-
async function deserializeUtxo(bytes) {
|
|
156
|
-
const view = new DataView(bytes.buffer, bytes.byteOffset);
|
|
157
|
-
const amountBytes = bytes.slice(0, 8);
|
|
158
|
-
const amount = bytesToBigint(amountBytes);
|
|
159
|
-
const privkeyBytes = bytes.slice(8, 40);
|
|
160
|
-
const privateKey = bytesToBigint(privkeyBytes);
|
|
161
|
-
const publicKey = await derivePublicKey(privateKey);
|
|
162
|
-
const blindingBytes = bytes.slice(40, 72);
|
|
163
|
-
const blinding = bytesToBigint(blindingBytes);
|
|
164
|
-
const mintBytes = bytes.slice(72, 104);
|
|
165
|
-
const mintAddress = new PublicKey(mintBytes);
|
|
166
|
-
const index = view.getUint32(104, true);
|
|
167
|
-
const utxo = {
|
|
168
|
-
amount,
|
|
169
|
-
keypair: { privateKey, publicKey },
|
|
170
|
-
blinding,
|
|
171
|
-
mintAddress,
|
|
172
|
-
index: index > 0 ? index : void 0
|
|
173
|
-
};
|
|
174
|
-
utxo.commitment = await computeCommitment(utxo);
|
|
175
|
-
return utxo;
|
|
176
|
-
}
|
|
177
|
-
function bigintToBytes(value, length) {
|
|
178
|
-
const result = new Uint8Array(length);
|
|
179
|
-
let remaining = value;
|
|
180
|
-
for (let i = 0; i < length; i++) {
|
|
181
|
-
result[i] = Number(remaining & BigInt(255));
|
|
182
|
-
remaining >>= BigInt(8);
|
|
183
|
-
}
|
|
184
|
-
return result;
|
|
185
|
-
}
|
|
186
|
-
function bytesToBigint(bytes) {
|
|
187
|
-
let result = BigInt(0);
|
|
188
|
-
for (let i = bytes.length - 1; i >= 0; i--) {
|
|
189
|
-
result = result << BigInt(8) | BigInt(bytes[i]);
|
|
190
|
-
}
|
|
191
|
-
return result;
|
|
192
|
-
}
|
|
193
|
-
function bigintToHex(value) {
|
|
194
|
-
return value.toString(16).padStart(64, "0");
|
|
195
|
-
}
|
|
196
|
-
function hexToBigint(hex) {
|
|
197
|
-
const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
198
|
-
return BigInt("0x" + cleanHex);
|
|
199
|
-
}
|
|
200
|
-
function bigintToBytes32(value) {
|
|
201
|
-
const result = new Uint8Array(32);
|
|
202
|
-
let remaining = value;
|
|
203
|
-
for (let i = 31; i >= 0; i--) {
|
|
204
|
-
result[i] = Number(remaining & BigInt(255));
|
|
205
|
-
remaining >>= BigInt(8);
|
|
206
|
-
}
|
|
207
|
-
return result;
|
|
208
|
-
}
|
|
209
|
-
async function utxoEquals(a, b) {
|
|
210
|
-
const commitmentA = a.commitment ?? await computeCommitment(a);
|
|
211
|
-
const commitmentB = b.commitment ?? await computeCommitment(b);
|
|
212
|
-
return commitmentA === commitmentB;
|
|
213
|
-
}
|
|
214
|
-
function sumUtxoAmounts(utxos) {
|
|
215
|
-
return utxos.reduce((sum, utxo) => sum + utxo.amount, BigInt(0));
|
|
216
|
-
}
|
|
217
|
-
function selectUtxos(available, targetAmount) {
|
|
218
|
-
const sorted = [...available].sort(
|
|
219
|
-
(a, b) => Number(b.amount - a.amount)
|
|
220
|
-
);
|
|
221
|
-
const selected = [];
|
|
222
|
-
let total = BigInt(0);
|
|
223
|
-
for (const utxo of sorted) {
|
|
224
|
-
if (total >= targetAmount) break;
|
|
225
|
-
selected.push(utxo);
|
|
226
|
-
total += utxo.amount;
|
|
227
|
-
}
|
|
228
|
-
if (total < targetAmount) {
|
|
229
|
-
return null;
|
|
230
|
-
}
|
|
231
|
-
return selected;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
export {
|
|
235
|
-
__require,
|
|
236
|
-
NATIVE_SOL_MINT,
|
|
237
|
-
randomFieldElement,
|
|
238
|
-
generateUtxoKeypair,
|
|
239
|
-
deriveUtxoKeypairFromSpendKey,
|
|
240
|
-
derivePublicKey,
|
|
241
|
-
createUtxo,
|
|
242
|
-
createZeroUtxo,
|
|
243
|
-
pubkeyToFieldElement,
|
|
244
|
-
computeCommitment,
|
|
245
|
-
computeSignature,
|
|
246
|
-
computeNullifier,
|
|
247
|
-
serializeUtxo,
|
|
248
|
-
deserializeUtxo,
|
|
249
|
-
bigintToHex,
|
|
250
|
-
hexToBigint,
|
|
251
|
-
bigintToBytes32,
|
|
252
|
-
utxoEquals,
|
|
253
|
-
sumUtxoAmounts,
|
|
254
|
-
selectUtxos
|
|
255
|
-
};
|