@ocash/sdk 0.1.4-rc.3 → 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/index.js CHANGED
@@ -3352,7 +3352,7 @@ var MemoryStore = class {
3352
3352
  async getMerkleLeaf(chainId, cid) {
3353
3353
  const rows = this.merkleLeavesByChain.get(chainId);
3354
3354
  const row = rows?.[cid];
3355
- if (!row) return void 0;
3355
+ if (!row || row.cid !== cid) return void 0;
3356
3356
  return { chainId, cid: row.cid, commitment: row.commitment };
3357
3357
  }
3358
3358
  /**
@@ -4369,7 +4369,7 @@ var KeyValueStore = class {
4369
4369
  if (!this.merkleLeafCids[String(chainId)]?.has(cid)) return void 0;
4370
4370
  const raw = await this.options.client.get(this.sharedRecordKey("merkleLeaves", chainId, cid));
4371
4371
  const row = this.parseJson(raw, null);
4372
- if (!row) return void 0;
4372
+ if (!row || row.cid !== cid) return void 0;
4373
4373
  return { chainId, cid: row.cid, commitment: row.commitment };
4374
4374
  }
4375
4375
  async appendMerkleLeaves(chainId, leaves) {
@@ -5131,10 +5131,10 @@ var ProofEngine = class {
5131
5131
  merkle_root_index: parsed.merkle_root_index ?? context.merkle_root_index,
5132
5132
  relayer: parsed.relayer ?? context.relayer,
5133
5133
  recipient: parsed.recipient ?? context.recipient,
5134
- withdraw_amount: parsed.withdraw_amount ? BigInt(parsed.withdraw_amount) : context.withdraw_amount,
5134
+ withdraw_amount: parsed.withdraw_amount != null ? BigInt(parsed.withdraw_amount) : context.withdraw_amount,
5135
5135
  extra_data: parsed.extra_data ?? context.extra_data,
5136
- relayer_fee: parsed.relayer_fee ? BigInt(parsed.relayer_fee) : context.relayer_fee,
5137
- gas_drop_value: parsed.gas_drop_value ? BigInt(parsed.gas_drop_value) : context.gas_drop_value,
5136
+ relayer_fee: parsed.relayer_fee != null ? BigInt(parsed.relayer_fee) : context.relayer_fee,
5137
+ gas_drop_value: parsed.gas_drop_value != null ? BigInt(parsed.gas_drop_value) : context.gas_drop_value,
5138
5138
  array_hash_digest: parsed.array_hash_digest ?? context.array_hash_digest,
5139
5139
  gnark_output: parsed.gnark_output,
5140
5140
  witness_json: parsed.witness_json,
@@ -6258,10 +6258,31 @@ var SyncEngine = class {
6258
6258
 
6259
6259
  // src/planner/planner.ts
6260
6260
  import { maxUint256, toHex as toHex4 } from "viem";
6261
+
6262
+ // src/utils/validators.ts
6263
+ import { getAddress as getAddress2 } from "viem";
6261
6264
  var requireHex = (value, name) => {
6262
6265
  if (isHexStrict(value, { minBytes: 1 })) return value;
6263
6266
  throw new SdkError("CONFIG", `${name} must be a hex string starting with 0x`);
6264
6267
  };
6268
+ var requireNumber = (value, name) => {
6269
+ if (typeof value === "number" && Number.isFinite(value)) return value;
6270
+ throw new SdkError("CONFIG", `${name} must be a finite number`);
6271
+ };
6272
+ var requireAddress = (value, name) => {
6273
+ if (typeof value !== "string") {
6274
+ throw new SdkError("CONFIG", `${name} must be a string address`);
6275
+ }
6276
+ return getAddress2(value);
6277
+ };
6278
+ var requireBigint = (value, name) => {
6279
+ if (typeof value === "bigint") return value;
6280
+ if (typeof value === "string" && value.length) return BigInt(value);
6281
+ if (typeof value === "number" && Number.isSafeInteger(value)) return BigInt(value);
6282
+ throw new SdkError("CONFIG", `${name} must be a bigint-compatible value`);
6283
+ };
6284
+
6285
+ // src/planner/planner.ts
6265
6286
  var parsePlanInput = (input) => {
6266
6287
  const action = input.action;
6267
6288
  if (action !== "transfer" && action !== "withdraw") {
@@ -6339,9 +6360,12 @@ var recordsFee = (input, _records, expectedOutput, action, relayerFee, expectedI
6339
6360
  }
6340
6361
  } else {
6341
6362
  cost = expectedIsWithFee ? expectedOutput : expectedOutput + fee;
6363
+ outputAmount = expectedIsWithFee ? expectedOutput - fee : expectedOutput;
6364
+ if (outputAmount < 0n) outputAmount = 0n;
6342
6365
  }
6343
6366
  if (total < cost) {
6344
6367
  cost = 0n;
6368
+ outputAmount = 0n;
6345
6369
  }
6346
6370
  break;
6347
6371
  }
@@ -6827,27 +6851,6 @@ var Planner = class {
6827
6851
  };
6828
6852
 
6829
6853
  // src/tx/txBuilder.ts
6830
- import { getAddress as getAddress2 } from "viem";
6831
- var requireNumber = (value, name) => {
6832
- if (typeof value === "number" && Number.isFinite(value)) return value;
6833
- throw new SdkError("CONFIG", `Missing ${name}`);
6834
- };
6835
- var requireHex2 = (value, name) => {
6836
- if (isHexStrict(value, { minBytes: 1 })) return value;
6837
- throw new SdkError("CONFIG", `Missing ${name}`);
6838
- };
6839
- var requireAddress = (value, name) => {
6840
- if (typeof value !== "string") {
6841
- throw new SdkError("CONFIG", `Missing ${name}`);
6842
- }
6843
- return getAddress2(value);
6844
- };
6845
- var requireBigint = (value, name) => {
6846
- if (typeof value === "bigint") return value;
6847
- if (typeof value === "string" && value.length) return BigInt(value);
6848
- if (typeof value === "number" && Number.isSafeInteger(value)) return BigInt(value);
6849
- throw new SdkError("CONFIG", `Missing ${name}`);
6850
- };
6851
6854
  var TxBuilder = class {
6852
6855
  /**
6853
6856
  * Build relayer request for transfer proofs.
@@ -6861,7 +6864,7 @@ var TxBuilder = class {
6861
6864
  if (!Array.isArray(extraData) || extraData.length !== 3) {
6862
6865
  throw new SdkError("CONFIG", "Transfer requires extra_data as bytes[3]");
6863
6866
  }
6864
- extraData.forEach((entry, idx) => requireHex2(entry, `extra_data[${idx}]`));
6867
+ extraData.forEach((entry, idx) => requireHex(entry, `extra_data[${idx}]`));
6865
6868
  const request = {
6866
6869
  kind: "relayer",
6867
6870
  method: "POST",
@@ -6894,7 +6897,7 @@ var TxBuilder = class {
6894
6897
  if (Array.isArray(extraData)) {
6895
6898
  throw new SdkError("CONFIG", "Withdraw requires extra_data as bytes");
6896
6899
  }
6897
- const extraDataHex = requireHex2(extraData, "extra_data");
6900
+ const extraDataHex = requireHex(extraData, "extra_data");
6898
6901
  const request = {
6899
6902
  kind: "relayer",
6900
6903
  method: "POST",
@@ -7403,44 +7406,64 @@ var MerkleEngine = class _MerkleEngine {
7403
7406
  await this.hydrateFromStorage(input.chainId);
7404
7407
  const canUseLocal = this.mode !== "remote";
7405
7408
  if (canUseLocal) {
7406
- const version = contractTreeElements > 0 ? await this.storage?.getChairmanMerkleVersion?.(input.chainId, contractTreeElements) : void 0;
7407
- const hasDb = typeof this.storage?.getMerkleLeaf === "function" && typeof this.storage?.getChairmanMerkleNode === "function" && (contractTreeElements === 0 || !!version);
7408
- if (hasDb) {
7409
+ const hasMerkleLeaf = typeof this.storage?.getMerkleLeaf === "function";
7410
+ const hasChairmanNode = typeof this.storage?.getChairmanMerkleNode === "function";
7411
+ if (hasMerkleLeaf && hasChairmanNode) {
7409
7412
  const state = this.ensureChainState(input.chainId);
7410
- if (contractTreeElements > 0 && state.mergedElements < contractTreeElements) {
7411
- if (this.mode === "local") {
7412
- throw new SdkError("MERKLE", "Local merkle db is behind contract", {
7413
- chainId: input.chainId,
7414
- cids,
7415
- localMergedElements: state.mergedElements,
7416
- contractTreeElements
7417
- });
7418
- }
7419
- } else {
7420
- try {
7421
- const proof = [];
7422
- for (const cid of cids) {
7423
- if (cid >= contractTreeElements) {
7424
- proof.push({ leaf_index: cid, path: new Array(this.treeDepth + 1).fill("0") });
7425
- continue;
7426
- }
7427
- const path = await this.buildLocalProofPath(input.chainId, cid, version);
7428
- proof.push({ leaf_index: cid, path });
7413
+ let version = contractTreeElements > 0 ? await this.storage?.getChairmanMerkleVersion?.(input.chainId, contractTreeElements) : void 0;
7414
+ let effectiveTreeElements = contractTreeElements;
7415
+ if (!version && contractTreeElements > 0 && state.mergedElements > 0) {
7416
+ const latest = await this.storage?.getLatestChairmanMerkleVersion?.(input.chainId);
7417
+ if (latest && latest.version > 0) {
7418
+ const allCovered = needsTreeProof.every((cid) => cid < latest.version);
7419
+ if (allCovered) {
7420
+ version = latest;
7421
+ effectiveTreeElements = latest.version;
7429
7422
  }
7430
- const effectiveRoot = contractTreeElements > 0 ? _MerkleEngine.normalizeHex32(version.rootHash, "version.rootHash") : getZeroHash(this.treeDepth);
7431
- return {
7432
- proof,
7433
- merkle_root: effectiveRoot,
7434
- latest_cid: totalElements > 0n ? Number(totalElements - 1n) : -1
7435
- };
7436
- } catch (error) {
7423
+ }
7424
+ }
7425
+ const hasDb = contractTreeElements === 0 || !!version;
7426
+ if (hasDb) {
7427
+ if (effectiveTreeElements > 0 && state.mergedElements < effectiveTreeElements) {
7437
7428
  if (this.mode === "local") {
7438
- throw new SdkError("MERKLE", "Local merkle proof build failed", { chainId: input.chainId, cids }, error);
7429
+ throw new SdkError("MERKLE", "Local merkle db is behind contract", {
7430
+ chainId: input.chainId,
7431
+ cids,
7432
+ localMergedElements: state.mergedElements,
7433
+ contractTreeElements: effectiveTreeElements
7434
+ });
7439
7435
  }
7436
+ } else {
7437
+ try {
7438
+ const proof = [];
7439
+ for (const cid of cids) {
7440
+ if (cid >= effectiveTreeElements) {
7441
+ proof.push({ leaf_index: cid, path: new Array(this.treeDepth + 1).fill("0") });
7442
+ continue;
7443
+ }
7444
+ const path = await this.buildLocalProofPath(input.chainId, cid, version);
7445
+ proof.push({ leaf_index: cid, path });
7446
+ }
7447
+ const effectiveRoot = effectiveTreeElements > 0 ? _MerkleEngine.normalizeHex32(version.rootHash, "version.rootHash") : getZeroHash(this.treeDepth);
7448
+ const effectiveLatestCid = effectiveTreeElements > 0 ? effectiveTreeElements - 1 : -1;
7449
+ return {
7450
+ proof,
7451
+ merkle_root: effectiveRoot,
7452
+ latest_cid: effectiveLatestCid
7453
+ };
7454
+ } catch (error) {
7455
+ if (this.mode === "local") {
7456
+ throw new SdkError("MERKLE", "Local merkle proof build failed", { chainId: input.chainId, cids }, error);
7457
+ }
7458
+ }
7459
+ }
7460
+ } else {
7461
+ if (this.mode === "local" && needsTreeProof.length) {
7462
+ throw new SdkError("MERKLE", "Local merkle db unavailable", { chainId: input.chainId, cids, reason: "missing_adapter_or_version" });
7440
7463
  }
7441
7464
  }
7442
7465
  } else if (this.mode === "local" && needsTreeProof.length) {
7443
- throw new SdkError("MERKLE", "Local merkle db unavailable", { chainId: input.chainId, cids, reason: "missing_adapter_or_version" });
7466
+ throw new SdkError("MERKLE", "Local merkle db unavailable", { chainId: input.chainId, cids, reason: "missing_adapter" });
7444
7467
  }
7445
7468
  }
7446
7469
  if (needsTreeProof.length === 0) {