@ocash/sdk 0.1.4-rc.2 → 0.1.4-rc.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/browser.cjs +103 -70
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.js +97 -64
- package/dist/browser.js.map +1 -1
- package/dist/index.cjs +103 -70
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +97 -64
- package/dist/index.js.map +1 -1
- package/dist/node.cjs +136 -92
- package/dist/node.cjs.map +1 -1
- package/dist/node.js +130 -86
- package/dist/node.js.map +1 -1
- package/package.json +1 -1
package/dist/node.cjs
CHANGED
|
@@ -3421,7 +3421,7 @@ var MemoryStore = class {
|
|
|
3421
3421
|
async getMerkleLeaf(chainId, cid) {
|
|
3422
3422
|
const rows = this.merkleLeavesByChain.get(chainId);
|
|
3423
3423
|
const row = rows?.[cid];
|
|
3424
|
-
if (!row) return void 0;
|
|
3424
|
+
if (!row || row.cid !== cid) return void 0;
|
|
3425
3425
|
return { chainId, cid: row.cid, commitment: row.commitment };
|
|
3426
3426
|
}
|
|
3427
3427
|
/**
|
|
@@ -4438,7 +4438,7 @@ var KeyValueStore = class {
|
|
|
4438
4438
|
if (!this.merkleLeafCids[String(chainId)]?.has(cid)) return void 0;
|
|
4439
4439
|
const raw = await this.options.client.get(this.sharedRecordKey("merkleLeaves", chainId, cid));
|
|
4440
4440
|
const row = this.parseJson(raw, null);
|
|
4441
|
-
if (!row) return void 0;
|
|
4441
|
+
if (!row || row.cid !== cid) return void 0;
|
|
4442
4442
|
return { chainId, cid: row.cid, commitment: row.commitment };
|
|
4443
4443
|
}
|
|
4444
4444
|
async appendMerkleLeaves(chainId, leaves) {
|
|
@@ -5200,10 +5200,10 @@ var ProofEngine = class {
|
|
|
5200
5200
|
merkle_root_index: parsed.merkle_root_index ?? context.merkle_root_index,
|
|
5201
5201
|
relayer: parsed.relayer ?? context.relayer,
|
|
5202
5202
|
recipient: parsed.recipient ?? context.recipient,
|
|
5203
|
-
withdraw_amount: parsed.withdraw_amount ? BigInt(parsed.withdraw_amount) : context.withdraw_amount,
|
|
5203
|
+
withdraw_amount: parsed.withdraw_amount != null ? BigInt(parsed.withdraw_amount) : context.withdraw_amount,
|
|
5204
5204
|
extra_data: parsed.extra_data ?? context.extra_data,
|
|
5205
|
-
relayer_fee: parsed.relayer_fee ? BigInt(parsed.relayer_fee) : context.relayer_fee,
|
|
5206
|
-
gas_drop_value: parsed.gas_drop_value ? BigInt(parsed.gas_drop_value) : context.gas_drop_value,
|
|
5205
|
+
relayer_fee: parsed.relayer_fee != null ? BigInt(parsed.relayer_fee) : context.relayer_fee,
|
|
5206
|
+
gas_drop_value: parsed.gas_drop_value != null ? BigInt(parsed.gas_drop_value) : context.gas_drop_value,
|
|
5207
5207
|
array_hash_digest: parsed.array_hash_digest ?? context.array_hash_digest,
|
|
5208
5208
|
gnark_output: parsed.gnark_output,
|
|
5209
5209
|
witness_json: parsed.witness_json,
|
|
@@ -6326,11 +6326,32 @@ var SyncEngine = class {
|
|
|
6326
6326
|
};
|
|
6327
6327
|
|
|
6328
6328
|
// src/planner/planner.ts
|
|
6329
|
+
var import_viem8 = require("viem");
|
|
6330
|
+
|
|
6331
|
+
// src/utils/validators.ts
|
|
6329
6332
|
var import_viem7 = require("viem");
|
|
6330
6333
|
var requireHex = (value, name) => {
|
|
6331
6334
|
if (isHexStrict(value, { minBytes: 1 })) return value;
|
|
6332
6335
|
throw new SdkError("CONFIG", `${name} must be a hex string starting with 0x`);
|
|
6333
6336
|
};
|
|
6337
|
+
var requireNumber = (value, name) => {
|
|
6338
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
6339
|
+
throw new SdkError("CONFIG", `${name} must be a finite number`);
|
|
6340
|
+
};
|
|
6341
|
+
var requireAddress = (value, name) => {
|
|
6342
|
+
if (typeof value !== "string") {
|
|
6343
|
+
throw new SdkError("CONFIG", `${name} must be a string address`);
|
|
6344
|
+
}
|
|
6345
|
+
return (0, import_viem7.getAddress)(value);
|
|
6346
|
+
};
|
|
6347
|
+
var requireBigint = (value, name) => {
|
|
6348
|
+
if (typeof value === "bigint") return value;
|
|
6349
|
+
if (typeof value === "string" && value.length) return BigInt(value);
|
|
6350
|
+
if (typeof value === "number" && Number.isSafeInteger(value)) return BigInt(value);
|
|
6351
|
+
throw new SdkError("CONFIG", `${name} must be a bigint-compatible value`);
|
|
6352
|
+
};
|
|
6353
|
+
|
|
6354
|
+
// src/planner/planner.ts
|
|
6334
6355
|
var parsePlanInput = (input) => {
|
|
6335
6356
|
const action = input.action;
|
|
6336
6357
|
if (action !== "transfer" && action !== "withdraw") {
|
|
@@ -6359,7 +6380,7 @@ var parsePlanInput = (input) => {
|
|
|
6359
6380
|
if (gasDropValue != null && typeof gasDropValue !== "bigint") throw new SdkError("CONFIG", "gasDropValue must be bigint");
|
|
6360
6381
|
return { action, chainId, assetId, amount, recipient, gasDropValue, payIncludesFee, relayerUrl: relayerUrl ?? void 0 };
|
|
6361
6382
|
};
|
|
6362
|
-
var tokenFeeKey = (token) => (0,
|
|
6383
|
+
var tokenFeeKey = (token) => (0, import_viem8.toHex)(BigInt(token.id), { size: 32 }).toLowerCase();
|
|
6363
6384
|
var selectTransferInputs = (utxos, required, maxInputs = 3) => {
|
|
6364
6385
|
const sorted = [...utxos].sort((a, b) => b.amount > a.amount ? 1 : b.amount < a.amount ? -1 : 0);
|
|
6365
6386
|
const selected = [];
|
|
@@ -6399,7 +6420,7 @@ var recordsFee = (input, _records, expectedOutput, action, relayerFee, expectedI
|
|
|
6399
6420
|
total = records.reduce((acc, cur) => acc + cur, 0n);
|
|
6400
6421
|
fee = BigInt(feeCount) * relayerFee.transfer;
|
|
6401
6422
|
relayFee = fee;
|
|
6402
|
-
if (
|
|
6423
|
+
if (import_viem8.maxUint256 === expectedOutput) {
|
|
6403
6424
|
cost = total;
|
|
6404
6425
|
outputAmount = total - fee;
|
|
6405
6426
|
if (outputAmount < 0n) {
|
|
@@ -6408,9 +6429,12 @@ var recordsFee = (input, _records, expectedOutput, action, relayerFee, expectedI
|
|
|
6408
6429
|
}
|
|
6409
6430
|
} else {
|
|
6410
6431
|
cost = expectedIsWithFee ? expectedOutput : expectedOutput + fee;
|
|
6432
|
+
outputAmount = expectedIsWithFee ? expectedOutput - fee : expectedOutput;
|
|
6433
|
+
if (outputAmount < 0n) outputAmount = 0n;
|
|
6411
6434
|
}
|
|
6412
6435
|
if (total < cost) {
|
|
6413
6436
|
cost = 0n;
|
|
6437
|
+
outputAmount = 0n;
|
|
6414
6438
|
}
|
|
6415
6439
|
break;
|
|
6416
6440
|
}
|
|
@@ -6421,7 +6445,7 @@ var recordsFee = (input, _records, expectedOutput, action, relayerFee, expectedI
|
|
|
6421
6445
|
const withdrawFeeDenominator = bpsBase + withdrawFeeBps;
|
|
6422
6446
|
total = records.reduce((acc, cur) => acc + cur, 0n);
|
|
6423
6447
|
fee = BigInt(feeCount - 1) * relayerFee.transfer;
|
|
6424
|
-
if (
|
|
6448
|
+
if (import_viem8.maxUint256 === expectedOutput) {
|
|
6425
6449
|
const withdrawBase = (total - fee) * bpsBase / withdrawFeeDenominator;
|
|
6426
6450
|
outputAmount = withdrawBase - relayFeePay;
|
|
6427
6451
|
relayFee = fee + relayFeePay;
|
|
@@ -6492,7 +6516,7 @@ var estimateRecords = (input) => {
|
|
|
6492
6516
|
const payRecords = [];
|
|
6493
6517
|
let payInfo = recordsFee({ withdrawFeeBps: input.withdrawFeeBps }, [...payRecords], input.expectedOutput, input.action, input.relayerFee, input.expectedIsWithFee);
|
|
6494
6518
|
const maxRecords = [];
|
|
6495
|
-
let maxInfo = recordsFee({ withdrawFeeBps: input.withdrawFeeBps }, [...maxRecords],
|
|
6519
|
+
let maxInfo = recordsFee({ withdrawFeeBps: input.withdrawFeeBps }, [...maxRecords], import_viem8.maxUint256, input.action, input.relayerFee, input.expectedIsWithFee);
|
|
6496
6520
|
for (const record of sorted) {
|
|
6497
6521
|
const isExceedPay = input.expectedIsWithFee ? payInfo.cost >= input.expectedOutput : payInfo.outputAmount >= input.expectedOutput;
|
|
6498
6522
|
if (payInfo.cost === 0n || !isExceedPay) {
|
|
@@ -6500,7 +6524,7 @@ var estimateRecords = (input) => {
|
|
|
6500
6524
|
payInfo = recordsFee({ withdrawFeeBps: input.withdrawFeeBps }, [...payRecords], input.expectedOutput, input.action, input.relayerFee, input.expectedIsWithFee);
|
|
6501
6525
|
}
|
|
6502
6526
|
maxRecords.push(record);
|
|
6503
|
-
const tempMax = recordsFee({ withdrawFeeBps: input.withdrawFeeBps }, [...maxRecords],
|
|
6527
|
+
const tempMax = recordsFee({ withdrawFeeBps: input.withdrawFeeBps }, [...maxRecords], import_viem8.maxUint256, input.action, input.relayerFee, input.expectedIsWithFee);
|
|
6504
6528
|
if (maxInfo.cost === 0n || tempMax.outputAmount > maxInfo.outputAmount) {
|
|
6505
6529
|
maxInfo = tempMax;
|
|
6506
6530
|
}
|
|
@@ -6665,7 +6689,7 @@ var Planner = class {
|
|
|
6665
6689
|
const records = utxos.map((u) => u.amount).filter((v) => v > 0n);
|
|
6666
6690
|
const estimates = estimateRecords({
|
|
6667
6691
|
records,
|
|
6668
|
-
expectedOutput:
|
|
6692
|
+
expectedOutput: import_viem8.maxUint256,
|
|
6669
6693
|
action: input.action,
|
|
6670
6694
|
relayerFee: { transfer: transferFee, withdraw: relayerFee },
|
|
6671
6695
|
withdrawFeeBps: token.withdrawFeeBps,
|
|
@@ -6896,27 +6920,6 @@ var Planner = class {
|
|
|
6896
6920
|
};
|
|
6897
6921
|
|
|
6898
6922
|
// src/tx/txBuilder.ts
|
|
6899
|
-
var import_viem8 = require("viem");
|
|
6900
|
-
var requireNumber = (value, name) => {
|
|
6901
|
-
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
6902
|
-
throw new SdkError("CONFIG", `Missing ${name}`);
|
|
6903
|
-
};
|
|
6904
|
-
var requireHex2 = (value, name) => {
|
|
6905
|
-
if (isHexStrict(value, { minBytes: 1 })) return value;
|
|
6906
|
-
throw new SdkError("CONFIG", `Missing ${name}`);
|
|
6907
|
-
};
|
|
6908
|
-
var requireAddress = (value, name) => {
|
|
6909
|
-
if (typeof value !== "string") {
|
|
6910
|
-
throw new SdkError("CONFIG", `Missing ${name}`);
|
|
6911
|
-
}
|
|
6912
|
-
return (0, import_viem8.getAddress)(value);
|
|
6913
|
-
};
|
|
6914
|
-
var requireBigint = (value, name) => {
|
|
6915
|
-
if (typeof value === "bigint") return value;
|
|
6916
|
-
if (typeof value === "string" && value.length) return BigInt(value);
|
|
6917
|
-
if (typeof value === "number" && Number.isSafeInteger(value)) return BigInt(value);
|
|
6918
|
-
throw new SdkError("CONFIG", `Missing ${name}`);
|
|
6919
|
-
};
|
|
6920
6923
|
var TxBuilder = class {
|
|
6921
6924
|
/**
|
|
6922
6925
|
* Build relayer request for transfer proofs.
|
|
@@ -6930,7 +6933,7 @@ var TxBuilder = class {
|
|
|
6930
6933
|
if (!Array.isArray(extraData) || extraData.length !== 3) {
|
|
6931
6934
|
throw new SdkError("CONFIG", "Transfer requires extra_data as bytes[3]");
|
|
6932
6935
|
}
|
|
6933
|
-
extraData.forEach((entry, idx) =>
|
|
6936
|
+
extraData.forEach((entry, idx) => requireHex(entry, `extra_data[${idx}]`));
|
|
6934
6937
|
const request = {
|
|
6935
6938
|
kind: "relayer",
|
|
6936
6939
|
method: "POST",
|
|
@@ -6963,7 +6966,7 @@ var TxBuilder = class {
|
|
|
6963
6966
|
if (Array.isArray(extraData)) {
|
|
6964
6967
|
throw new SdkError("CONFIG", "Withdraw requires extra_data as bytes");
|
|
6965
6968
|
}
|
|
6966
|
-
const extraDataHex =
|
|
6969
|
+
const extraDataHex = requireHex(extraData, "extra_data");
|
|
6967
6970
|
const request = {
|
|
6968
6971
|
kind: "relayer",
|
|
6969
6972
|
method: "POST",
|
|
@@ -7364,7 +7367,7 @@ var MerkleEngine = class _MerkleEngine {
|
|
|
7364
7367
|
const isZero = BigInt(onChainNorm) === 0n;
|
|
7365
7368
|
if (!isZero && onChainNorm !== result.rootHash) {
|
|
7366
7369
|
const target = state.mergedElements;
|
|
7367
|
-
await this.
|
|
7370
|
+
await this._rollback(chainId, target);
|
|
7368
7371
|
throw new SdkError("MERKLE", "Local merkle root mismatch with on-chain root \u2014 rolled back", {
|
|
7369
7372
|
chainId,
|
|
7370
7373
|
rootIndex,
|
|
@@ -7397,21 +7400,31 @@ var MerkleEngine = class _MerkleEngine {
|
|
|
7397
7400
|
}
|
|
7398
7401
|
// ── Rollback (tree O(1) + sync cursor reset) ──
|
|
7399
7402
|
/**
|
|
7400
|
-
*
|
|
7401
|
-
*
|
|
7403
|
+
* Public rollback: step back one batch (32 elements) from the current position.
|
|
7404
|
+
* Upper-layer code calls this on any error to reset and retry.
|
|
7402
7405
|
*
|
|
7403
7406
|
* What gets rolled back:
|
|
7404
7407
|
* - ChairmanMerkle tree version pointer (O(1) — old nodes still in storage)
|
|
7405
7408
|
* - Pending leaves buffer (cleared)
|
|
7406
7409
|
* - Sync cursor: memo + merkle fields (nullifier left unchanged — independent)
|
|
7407
7410
|
*
|
|
7411
|
+
* @returns true if rollback succeeded, false if already at 0 or target version doesn't exist.
|
|
7412
|
+
*/
|
|
7413
|
+
async rollback(chainId) {
|
|
7414
|
+
const state = this.ensureChainState(chainId);
|
|
7415
|
+
const target = Math.max(0, state.mergedElements - SUBTREE_SIZE);
|
|
7416
|
+
return this._rollback(chainId, target);
|
|
7417
|
+
}
|
|
7418
|
+
/**
|
|
7419
|
+
* Internal rollback to an exact batch boundary.
|
|
7420
|
+
*
|
|
7408
7421
|
* @param targetMergedElements Must be a non-negative multiple of 32.
|
|
7409
7422
|
* Pass 0 to reset to the empty tree.
|
|
7410
7423
|
* @returns true if rollback succeeded, false if the target version doesn't exist.
|
|
7411
7424
|
*/
|
|
7412
|
-
async
|
|
7425
|
+
async _rollback(chainId, targetMergedElements) {
|
|
7413
7426
|
if (targetMergedElements < 0 || targetMergedElements % SUBTREE_SIZE !== 0) {
|
|
7414
|
-
throw new SdkError("MERKLE", "
|
|
7427
|
+
throw new SdkError("MERKLE", "_rollback target must be a non-negative multiple of 32", { targetMergedElements });
|
|
7415
7428
|
}
|
|
7416
7429
|
const state = this.ensureChainState(chainId);
|
|
7417
7430
|
const pending = this.ensurePendingLeaves(chainId);
|
|
@@ -7462,44 +7475,64 @@ var MerkleEngine = class _MerkleEngine {
|
|
|
7462
7475
|
await this.hydrateFromStorage(input.chainId);
|
|
7463
7476
|
const canUseLocal = this.mode !== "remote";
|
|
7464
7477
|
if (canUseLocal) {
|
|
7465
|
-
const
|
|
7466
|
-
const
|
|
7467
|
-
if (
|
|
7478
|
+
const hasMerkleLeaf = typeof this.storage?.getMerkleLeaf === "function";
|
|
7479
|
+
const hasChairmanNode = typeof this.storage?.getChairmanMerkleNode === "function";
|
|
7480
|
+
if (hasMerkleLeaf && hasChairmanNode) {
|
|
7468
7481
|
const state = this.ensureChainState(input.chainId);
|
|
7469
|
-
|
|
7470
|
-
|
|
7471
|
-
|
|
7472
|
-
|
|
7473
|
-
|
|
7474
|
-
|
|
7475
|
-
|
|
7476
|
-
|
|
7477
|
-
|
|
7478
|
-
} else {
|
|
7479
|
-
try {
|
|
7480
|
-
const proof = [];
|
|
7481
|
-
for (const cid of cids) {
|
|
7482
|
-
if (cid >= contractTreeElements) {
|
|
7483
|
-
proof.push({ leaf_index: cid, path: new Array(this.treeDepth + 1).fill("0") });
|
|
7484
|
-
continue;
|
|
7485
|
-
}
|
|
7486
|
-
const path2 = await this.buildLocalProofPath(input.chainId, cid, version);
|
|
7487
|
-
proof.push({ leaf_index: cid, path: path2 });
|
|
7482
|
+
let version = contractTreeElements > 0 ? await this.storage?.getChairmanMerkleVersion?.(input.chainId, contractTreeElements) : void 0;
|
|
7483
|
+
let effectiveTreeElements = contractTreeElements;
|
|
7484
|
+
if (!version && contractTreeElements > 0 && state.mergedElements > 0) {
|
|
7485
|
+
const latest = await this.storage?.getLatestChairmanMerkleVersion?.(input.chainId);
|
|
7486
|
+
if (latest && latest.version > 0) {
|
|
7487
|
+
const allCovered = needsTreeProof.every((cid) => cid < latest.version);
|
|
7488
|
+
if (allCovered) {
|
|
7489
|
+
version = latest;
|
|
7490
|
+
effectiveTreeElements = latest.version;
|
|
7488
7491
|
}
|
|
7489
|
-
|
|
7490
|
-
|
|
7491
|
-
|
|
7492
|
-
|
|
7493
|
-
|
|
7494
|
-
};
|
|
7495
|
-
} catch (error) {
|
|
7492
|
+
}
|
|
7493
|
+
}
|
|
7494
|
+
const hasDb = contractTreeElements === 0 || !!version;
|
|
7495
|
+
if (hasDb) {
|
|
7496
|
+
if (effectiveTreeElements > 0 && state.mergedElements < effectiveTreeElements) {
|
|
7496
7497
|
if (this.mode === "local") {
|
|
7497
|
-
throw new SdkError("MERKLE", "Local merkle
|
|
7498
|
+
throw new SdkError("MERKLE", "Local merkle db is behind contract", {
|
|
7499
|
+
chainId: input.chainId,
|
|
7500
|
+
cids,
|
|
7501
|
+
localMergedElements: state.mergedElements,
|
|
7502
|
+
contractTreeElements: effectiveTreeElements
|
|
7503
|
+
});
|
|
7504
|
+
}
|
|
7505
|
+
} else {
|
|
7506
|
+
try {
|
|
7507
|
+
const proof = [];
|
|
7508
|
+
for (const cid of cids) {
|
|
7509
|
+
if (cid >= effectiveTreeElements) {
|
|
7510
|
+
proof.push({ leaf_index: cid, path: new Array(this.treeDepth + 1).fill("0") });
|
|
7511
|
+
continue;
|
|
7512
|
+
}
|
|
7513
|
+
const path2 = await this.buildLocalProofPath(input.chainId, cid, version);
|
|
7514
|
+
proof.push({ leaf_index: cid, path: path2 });
|
|
7515
|
+
}
|
|
7516
|
+
const effectiveRoot = effectiveTreeElements > 0 ? _MerkleEngine.normalizeHex32(version.rootHash, "version.rootHash") : getZeroHash(this.treeDepth);
|
|
7517
|
+
const effectiveLatestCid = effectiveTreeElements > 0 ? effectiveTreeElements - 1 : -1;
|
|
7518
|
+
return {
|
|
7519
|
+
proof,
|
|
7520
|
+
merkle_root: effectiveRoot,
|
|
7521
|
+
latest_cid: effectiveLatestCid
|
|
7522
|
+
};
|
|
7523
|
+
} catch (error) {
|
|
7524
|
+
if (this.mode === "local") {
|
|
7525
|
+
throw new SdkError("MERKLE", "Local merkle proof build failed", { chainId: input.chainId, cids }, error);
|
|
7526
|
+
}
|
|
7498
7527
|
}
|
|
7499
7528
|
}
|
|
7529
|
+
} else {
|
|
7530
|
+
if (this.mode === "local" && needsTreeProof.length) {
|
|
7531
|
+
throw new SdkError("MERKLE", "Local merkle db unavailable", { chainId: input.chainId, cids, reason: "missing_adapter_or_version" });
|
|
7532
|
+
}
|
|
7500
7533
|
}
|
|
7501
7534
|
} else if (this.mode === "local" && needsTreeProof.length) {
|
|
7502
|
-
throw new SdkError("MERKLE", "Local merkle db unavailable", { chainId: input.chainId, cids, reason: "
|
|
7535
|
+
throw new SdkError("MERKLE", "Local merkle db unavailable", { chainId: input.chainId, cids, reason: "missing_adapter" });
|
|
7503
7536
|
}
|
|
7504
7537
|
}
|
|
7505
7538
|
if (needsTreeProof.length === 0) {
|
|
@@ -8778,6 +8811,9 @@ function hydrateWalletState(state) {
|
|
|
8778
8811
|
}
|
|
8779
8812
|
|
|
8780
8813
|
// src/store/fileStore.ts
|
|
8814
|
+
function isEnoent(err) {
|
|
8815
|
+
return !!err && typeof err === "object" && "code" in err && err.code === "ENOENT";
|
|
8816
|
+
}
|
|
8781
8817
|
var FileStore = class {
|
|
8782
8818
|
/**
|
|
8783
8819
|
* Create a FileStore with a base directory and optional limits.
|
|
@@ -8840,26 +8876,28 @@ var FileStore = class {
|
|
|
8840
8876
|
return import_node_path.default.join(this.options.baseDir, `shared.merkle.${chainId}.jsonl`);
|
|
8841
8877
|
}
|
|
8842
8878
|
async readMerkleFile(filePath) {
|
|
8879
|
+
let raw;
|
|
8843
8880
|
try {
|
|
8844
|
-
|
|
8845
|
-
|
|
8846
|
-
|
|
8847
|
-
for (const line of lines) {
|
|
8848
|
-
try {
|
|
8849
|
-
const row = JSON.parse(line);
|
|
8850
|
-
const cid = Number(row?.cid);
|
|
8851
|
-
const commitment2 = row?.commitment;
|
|
8852
|
-
if (!Number.isFinite(cid) || cid < 0) continue;
|
|
8853
|
-
if (typeof commitment2 !== "string" || !commitment2.startsWith("0x")) continue;
|
|
8854
|
-
out.push({ cid: Math.floor(cid), commitment: commitment2 });
|
|
8855
|
-
} catch {
|
|
8856
|
-
}
|
|
8857
|
-
}
|
|
8858
|
-
out.sort((a, b) => a.cid - b.cid);
|
|
8859
|
-
return out.length ? out : void 0;
|
|
8860
|
-
} catch {
|
|
8881
|
+
raw = await (0, import_promises.readFile)(filePath, "utf8");
|
|
8882
|
+
} catch (err) {
|
|
8883
|
+
if (!isEnoent(err)) throw err;
|
|
8861
8884
|
return void 0;
|
|
8862
8885
|
}
|
|
8886
|
+
const out = [];
|
|
8887
|
+
const lines = raw.split("\n").filter((l) => l.trim().length > 0);
|
|
8888
|
+
for (const line of lines) {
|
|
8889
|
+
try {
|
|
8890
|
+
const row = JSON.parse(line);
|
|
8891
|
+
const cid = Number(row?.cid);
|
|
8892
|
+
const commitment2 = row?.commitment;
|
|
8893
|
+
if (!Number.isFinite(cid) || cid < 0) continue;
|
|
8894
|
+
if (typeof commitment2 !== "string" || !commitment2.startsWith("0x")) continue;
|
|
8895
|
+
out.push({ cid: Math.floor(cid), commitment: commitment2 });
|
|
8896
|
+
} catch {
|
|
8897
|
+
}
|
|
8898
|
+
}
|
|
8899
|
+
out.sort((a, b) => a.cid - b.cid);
|
|
8900
|
+
return out.length ? out : void 0;
|
|
8863
8901
|
}
|
|
8864
8902
|
/**
|
|
8865
8903
|
* Infer the next merkle cid from the tail of the jsonl file.
|
|
@@ -8876,10 +8914,14 @@ var FileStore = class {
|
|
|
8876
8914
|
}
|
|
8877
8915
|
const last = JSON.parse(lines[lines.length - 1]);
|
|
8878
8916
|
const cid = Number(last?.cid);
|
|
8879
|
-
|
|
8917
|
+
if (!Number.isFinite(cid)) {
|
|
8918
|
+
throw new Error(`corrupted merkle jsonl: missing or non-numeric cid in tail of ${this.merkleFilePath(chainId)}`);
|
|
8919
|
+
}
|
|
8920
|
+
const next = Math.max(0, Math.floor(cid) + 1);
|
|
8880
8921
|
this.merkleNextCid.set(chainId, next);
|
|
8881
8922
|
return next;
|
|
8882
|
-
} catch {
|
|
8923
|
+
} catch (err) {
|
|
8924
|
+
if (!isEnoent(err)) throw err;
|
|
8883
8925
|
this.merkleNextCid.set(chainId, 0);
|
|
8884
8926
|
return 0;
|
|
8885
8927
|
}
|
|
@@ -8906,7 +8948,8 @@ var FileStore = class {
|
|
|
8906
8948
|
for (const [k, v] of hydrated.utxos.entries()) this.utxos.set(k, v);
|
|
8907
8949
|
const operations = Array.isArray(parsed.operations) ? parsed.operations : [];
|
|
8908
8950
|
this.operations = operations;
|
|
8909
|
-
} catch {
|
|
8951
|
+
} catch (err) {
|
|
8952
|
+
if (!isEnoent(err)) throw err;
|
|
8910
8953
|
}
|
|
8911
8954
|
try {
|
|
8912
8955
|
const raw = await (0, import_promises.readFile)(this.sharedFilePath(), "utf8");
|
|
@@ -8938,7 +8981,8 @@ var FileStore = class {
|
|
|
8938
8981
|
if (entryNullifiersRaw && typeof entryNullifiersRaw === "object") {
|
|
8939
8982
|
this.entryNullifiers = entryNullifiersRaw;
|
|
8940
8983
|
}
|
|
8941
|
-
} catch {
|
|
8984
|
+
} catch (err) {
|
|
8985
|
+
if (!isEnoent(err)) throw err;
|
|
8942
8986
|
}
|
|
8943
8987
|
const pruned = this.pruneOperations();
|
|
8944
8988
|
if (pruned) void this.saveWallet().catch(() => void 0);
|
|
@@ -9209,7 +9253,7 @@ var FileStore = class {
|
|
|
9209
9253
|
async getMerkleLeaf(chainId, cid) {
|
|
9210
9254
|
const rows = await this.getMerkleLeaves(chainId);
|
|
9211
9255
|
const row = rows?.[cid];
|
|
9212
|
-
if (!row) return void 0;
|
|
9256
|
+
if (!row || row.cid !== cid) return void 0;
|
|
9213
9257
|
return { chainId, cid: row.cid, commitment: row.commitment };
|
|
9214
9258
|
}
|
|
9215
9259
|
/**
|