@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/browser.cjs +88 -65
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.js +82 -59
- package/dist/browser.js.map +1 -1
- package/dist/index.cjs +88 -65
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +82 -59
- package/dist/index.js.map +1 -1
- package/dist/node.cjs +121 -87
- package/dist/node.cjs.map +1 -1
- package/dist/node.js +115 -81
- package/dist/node.js.map +1 -1
- package/package.json +1 -1
package/dist/browser.cjs
CHANGED
|
@@ -3420,7 +3420,7 @@ var MemoryStore = class {
|
|
|
3420
3420
|
async getMerkleLeaf(chainId, cid) {
|
|
3421
3421
|
const rows = this.merkleLeavesByChain.get(chainId);
|
|
3422
3422
|
const row = rows?.[cid];
|
|
3423
|
-
if (!row) return void 0;
|
|
3423
|
+
if (!row || row.cid !== cid) return void 0;
|
|
3424
3424
|
return { chainId, cid: row.cid, commitment: row.commitment };
|
|
3425
3425
|
}
|
|
3426
3426
|
/**
|
|
@@ -4437,7 +4437,7 @@ var KeyValueStore = class {
|
|
|
4437
4437
|
if (!this.merkleLeafCids[String(chainId)]?.has(cid)) return void 0;
|
|
4438
4438
|
const raw = await this.options.client.get(this.sharedRecordKey("merkleLeaves", chainId, cid));
|
|
4439
4439
|
const row = this.parseJson(raw, null);
|
|
4440
|
-
if (!row) return void 0;
|
|
4440
|
+
if (!row || row.cid !== cid) return void 0;
|
|
4441
4441
|
return { chainId, cid: row.cid, commitment: row.commitment };
|
|
4442
4442
|
}
|
|
4443
4443
|
async appendMerkleLeaves(chainId, leaves) {
|
|
@@ -5199,10 +5199,10 @@ var ProofEngine = class {
|
|
|
5199
5199
|
merkle_root_index: parsed.merkle_root_index ?? context.merkle_root_index,
|
|
5200
5200
|
relayer: parsed.relayer ?? context.relayer,
|
|
5201
5201
|
recipient: parsed.recipient ?? context.recipient,
|
|
5202
|
-
withdraw_amount: parsed.withdraw_amount ? BigInt(parsed.withdraw_amount) : context.withdraw_amount,
|
|
5202
|
+
withdraw_amount: parsed.withdraw_amount != null ? BigInt(parsed.withdraw_amount) : context.withdraw_amount,
|
|
5203
5203
|
extra_data: parsed.extra_data ?? context.extra_data,
|
|
5204
|
-
relayer_fee: parsed.relayer_fee ? BigInt(parsed.relayer_fee) : context.relayer_fee,
|
|
5205
|
-
gas_drop_value: parsed.gas_drop_value ? BigInt(parsed.gas_drop_value) : context.gas_drop_value,
|
|
5204
|
+
relayer_fee: parsed.relayer_fee != null ? BigInt(parsed.relayer_fee) : context.relayer_fee,
|
|
5205
|
+
gas_drop_value: parsed.gas_drop_value != null ? BigInt(parsed.gas_drop_value) : context.gas_drop_value,
|
|
5206
5206
|
array_hash_digest: parsed.array_hash_digest ?? context.array_hash_digest,
|
|
5207
5207
|
gnark_output: parsed.gnark_output,
|
|
5208
5208
|
witness_json: parsed.witness_json,
|
|
@@ -6325,11 +6325,32 @@ var SyncEngine = class {
|
|
|
6325
6325
|
};
|
|
6326
6326
|
|
|
6327
6327
|
// src/planner/planner.ts
|
|
6328
|
+
var import_viem8 = require("viem");
|
|
6329
|
+
|
|
6330
|
+
// src/utils/validators.ts
|
|
6328
6331
|
var import_viem7 = require("viem");
|
|
6329
6332
|
var requireHex = (value, name) => {
|
|
6330
6333
|
if (isHexStrict(value, { minBytes: 1 })) return value;
|
|
6331
6334
|
throw new SdkError("CONFIG", `${name} must be a hex string starting with 0x`);
|
|
6332
6335
|
};
|
|
6336
|
+
var requireNumber = (value, name) => {
|
|
6337
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
6338
|
+
throw new SdkError("CONFIG", `${name} must be a finite number`);
|
|
6339
|
+
};
|
|
6340
|
+
var requireAddress = (value, name) => {
|
|
6341
|
+
if (typeof value !== "string") {
|
|
6342
|
+
throw new SdkError("CONFIG", `${name} must be a string address`);
|
|
6343
|
+
}
|
|
6344
|
+
return (0, import_viem7.getAddress)(value);
|
|
6345
|
+
};
|
|
6346
|
+
var requireBigint = (value, name) => {
|
|
6347
|
+
if (typeof value === "bigint") return value;
|
|
6348
|
+
if (typeof value === "string" && value.length) return BigInt(value);
|
|
6349
|
+
if (typeof value === "number" && Number.isSafeInteger(value)) return BigInt(value);
|
|
6350
|
+
throw new SdkError("CONFIG", `${name} must be a bigint-compatible value`);
|
|
6351
|
+
};
|
|
6352
|
+
|
|
6353
|
+
// src/planner/planner.ts
|
|
6333
6354
|
var parsePlanInput = (input) => {
|
|
6334
6355
|
const action = input.action;
|
|
6335
6356
|
if (action !== "transfer" && action !== "withdraw") {
|
|
@@ -6358,7 +6379,7 @@ var parsePlanInput = (input) => {
|
|
|
6358
6379
|
if (gasDropValue != null && typeof gasDropValue !== "bigint") throw new SdkError("CONFIG", "gasDropValue must be bigint");
|
|
6359
6380
|
return { action, chainId, assetId, amount, recipient, gasDropValue, payIncludesFee, relayerUrl: relayerUrl ?? void 0 };
|
|
6360
6381
|
};
|
|
6361
|
-
var tokenFeeKey = (token) => (0,
|
|
6382
|
+
var tokenFeeKey = (token) => (0, import_viem8.toHex)(BigInt(token.id), { size: 32 }).toLowerCase();
|
|
6362
6383
|
var selectTransferInputs = (utxos, required, maxInputs = 3) => {
|
|
6363
6384
|
const sorted = [...utxos].sort((a, b) => b.amount > a.amount ? 1 : b.amount < a.amount ? -1 : 0);
|
|
6364
6385
|
const selected = [];
|
|
@@ -6398,7 +6419,7 @@ var recordsFee = (input, _records, expectedOutput, action, relayerFee, expectedI
|
|
|
6398
6419
|
total = records.reduce((acc, cur) => acc + cur, 0n);
|
|
6399
6420
|
fee = BigInt(feeCount) * relayerFee.transfer;
|
|
6400
6421
|
relayFee = fee;
|
|
6401
|
-
if (
|
|
6422
|
+
if (import_viem8.maxUint256 === expectedOutput) {
|
|
6402
6423
|
cost = total;
|
|
6403
6424
|
outputAmount = total - fee;
|
|
6404
6425
|
if (outputAmount < 0n) {
|
|
@@ -6407,9 +6428,12 @@ var recordsFee = (input, _records, expectedOutput, action, relayerFee, expectedI
|
|
|
6407
6428
|
}
|
|
6408
6429
|
} else {
|
|
6409
6430
|
cost = expectedIsWithFee ? expectedOutput : expectedOutput + fee;
|
|
6431
|
+
outputAmount = expectedIsWithFee ? expectedOutput - fee : expectedOutput;
|
|
6432
|
+
if (outputAmount < 0n) outputAmount = 0n;
|
|
6410
6433
|
}
|
|
6411
6434
|
if (total < cost) {
|
|
6412
6435
|
cost = 0n;
|
|
6436
|
+
outputAmount = 0n;
|
|
6413
6437
|
}
|
|
6414
6438
|
break;
|
|
6415
6439
|
}
|
|
@@ -6420,7 +6444,7 @@ var recordsFee = (input, _records, expectedOutput, action, relayerFee, expectedI
|
|
|
6420
6444
|
const withdrawFeeDenominator = bpsBase + withdrawFeeBps;
|
|
6421
6445
|
total = records.reduce((acc, cur) => acc + cur, 0n);
|
|
6422
6446
|
fee = BigInt(feeCount - 1) * relayerFee.transfer;
|
|
6423
|
-
if (
|
|
6447
|
+
if (import_viem8.maxUint256 === expectedOutput) {
|
|
6424
6448
|
const withdrawBase = (total - fee) * bpsBase / withdrawFeeDenominator;
|
|
6425
6449
|
outputAmount = withdrawBase - relayFeePay;
|
|
6426
6450
|
relayFee = fee + relayFeePay;
|
|
@@ -6491,7 +6515,7 @@ var estimateRecords = (input) => {
|
|
|
6491
6515
|
const payRecords = [];
|
|
6492
6516
|
let payInfo = recordsFee({ withdrawFeeBps: input.withdrawFeeBps }, [...payRecords], input.expectedOutput, input.action, input.relayerFee, input.expectedIsWithFee);
|
|
6493
6517
|
const maxRecords = [];
|
|
6494
|
-
let maxInfo = recordsFee({ withdrawFeeBps: input.withdrawFeeBps }, [...maxRecords],
|
|
6518
|
+
let maxInfo = recordsFee({ withdrawFeeBps: input.withdrawFeeBps }, [...maxRecords], import_viem8.maxUint256, input.action, input.relayerFee, input.expectedIsWithFee);
|
|
6495
6519
|
for (const record of sorted) {
|
|
6496
6520
|
const isExceedPay = input.expectedIsWithFee ? payInfo.cost >= input.expectedOutput : payInfo.outputAmount >= input.expectedOutput;
|
|
6497
6521
|
if (payInfo.cost === 0n || !isExceedPay) {
|
|
@@ -6499,7 +6523,7 @@ var estimateRecords = (input) => {
|
|
|
6499
6523
|
payInfo = recordsFee({ withdrawFeeBps: input.withdrawFeeBps }, [...payRecords], input.expectedOutput, input.action, input.relayerFee, input.expectedIsWithFee);
|
|
6500
6524
|
}
|
|
6501
6525
|
maxRecords.push(record);
|
|
6502
|
-
const tempMax = recordsFee({ withdrawFeeBps: input.withdrawFeeBps }, [...maxRecords],
|
|
6526
|
+
const tempMax = recordsFee({ withdrawFeeBps: input.withdrawFeeBps }, [...maxRecords], import_viem8.maxUint256, input.action, input.relayerFee, input.expectedIsWithFee);
|
|
6503
6527
|
if (maxInfo.cost === 0n || tempMax.outputAmount > maxInfo.outputAmount) {
|
|
6504
6528
|
maxInfo = tempMax;
|
|
6505
6529
|
}
|
|
@@ -6664,7 +6688,7 @@ var Planner = class {
|
|
|
6664
6688
|
const records = utxos.map((u) => u.amount).filter((v) => v > 0n);
|
|
6665
6689
|
const estimates = estimateRecords({
|
|
6666
6690
|
records,
|
|
6667
|
-
expectedOutput:
|
|
6691
|
+
expectedOutput: import_viem8.maxUint256,
|
|
6668
6692
|
action: input.action,
|
|
6669
6693
|
relayerFee: { transfer: transferFee, withdraw: relayerFee },
|
|
6670
6694
|
withdrawFeeBps: token.withdrawFeeBps,
|
|
@@ -6895,27 +6919,6 @@ var Planner = class {
|
|
|
6895
6919
|
};
|
|
6896
6920
|
|
|
6897
6921
|
// src/tx/txBuilder.ts
|
|
6898
|
-
var import_viem8 = require("viem");
|
|
6899
|
-
var requireNumber = (value, name) => {
|
|
6900
|
-
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
6901
|
-
throw new SdkError("CONFIG", `Missing ${name}`);
|
|
6902
|
-
};
|
|
6903
|
-
var requireHex2 = (value, name) => {
|
|
6904
|
-
if (isHexStrict(value, { minBytes: 1 })) return value;
|
|
6905
|
-
throw new SdkError("CONFIG", `Missing ${name}`);
|
|
6906
|
-
};
|
|
6907
|
-
var requireAddress = (value, name) => {
|
|
6908
|
-
if (typeof value !== "string") {
|
|
6909
|
-
throw new SdkError("CONFIG", `Missing ${name}`);
|
|
6910
|
-
}
|
|
6911
|
-
return (0, import_viem8.getAddress)(value);
|
|
6912
|
-
};
|
|
6913
|
-
var requireBigint = (value, name) => {
|
|
6914
|
-
if (typeof value === "bigint") return value;
|
|
6915
|
-
if (typeof value === "string" && value.length) return BigInt(value);
|
|
6916
|
-
if (typeof value === "number" && Number.isSafeInteger(value)) return BigInt(value);
|
|
6917
|
-
throw new SdkError("CONFIG", `Missing ${name}`);
|
|
6918
|
-
};
|
|
6919
6922
|
var TxBuilder = class {
|
|
6920
6923
|
/**
|
|
6921
6924
|
* Build relayer request for transfer proofs.
|
|
@@ -6929,7 +6932,7 @@ var TxBuilder = class {
|
|
|
6929
6932
|
if (!Array.isArray(extraData) || extraData.length !== 3) {
|
|
6930
6933
|
throw new SdkError("CONFIG", "Transfer requires extra_data as bytes[3]");
|
|
6931
6934
|
}
|
|
6932
|
-
extraData.forEach((entry, idx) =>
|
|
6935
|
+
extraData.forEach((entry, idx) => requireHex(entry, `extra_data[${idx}]`));
|
|
6933
6936
|
const request = {
|
|
6934
6937
|
kind: "relayer",
|
|
6935
6938
|
method: "POST",
|
|
@@ -6962,7 +6965,7 @@ var TxBuilder = class {
|
|
|
6962
6965
|
if (Array.isArray(extraData)) {
|
|
6963
6966
|
throw new SdkError("CONFIG", "Withdraw requires extra_data as bytes");
|
|
6964
6967
|
}
|
|
6965
|
-
const extraDataHex =
|
|
6968
|
+
const extraDataHex = requireHex(extraData, "extra_data");
|
|
6966
6969
|
const request = {
|
|
6967
6970
|
kind: "relayer",
|
|
6968
6971
|
method: "POST",
|
|
@@ -7471,44 +7474,64 @@ var MerkleEngine = class _MerkleEngine {
|
|
|
7471
7474
|
await this.hydrateFromStorage(input.chainId);
|
|
7472
7475
|
const canUseLocal = this.mode !== "remote";
|
|
7473
7476
|
if (canUseLocal) {
|
|
7474
|
-
const
|
|
7475
|
-
const
|
|
7476
|
-
if (
|
|
7477
|
+
const hasMerkleLeaf = typeof this.storage?.getMerkleLeaf === "function";
|
|
7478
|
+
const hasChairmanNode = typeof this.storage?.getChairmanMerkleNode === "function";
|
|
7479
|
+
if (hasMerkleLeaf && hasChairmanNode) {
|
|
7477
7480
|
const state = this.ensureChainState(input.chainId);
|
|
7478
|
-
|
|
7479
|
-
|
|
7480
|
-
|
|
7481
|
-
|
|
7482
|
-
|
|
7483
|
-
|
|
7484
|
-
|
|
7485
|
-
|
|
7486
|
-
|
|
7487
|
-
} else {
|
|
7488
|
-
try {
|
|
7489
|
-
const proof = [];
|
|
7490
|
-
for (const cid of cids) {
|
|
7491
|
-
if (cid >= contractTreeElements) {
|
|
7492
|
-
proof.push({ leaf_index: cid, path: new Array(this.treeDepth + 1).fill("0") });
|
|
7493
|
-
continue;
|
|
7494
|
-
}
|
|
7495
|
-
const path = await this.buildLocalProofPath(input.chainId, cid, version);
|
|
7496
|
-
proof.push({ leaf_index: cid, path });
|
|
7481
|
+
let version = contractTreeElements > 0 ? await this.storage?.getChairmanMerkleVersion?.(input.chainId, contractTreeElements) : void 0;
|
|
7482
|
+
let effectiveTreeElements = contractTreeElements;
|
|
7483
|
+
if (!version && contractTreeElements > 0 && state.mergedElements > 0) {
|
|
7484
|
+
const latest = await this.storage?.getLatestChairmanMerkleVersion?.(input.chainId);
|
|
7485
|
+
if (latest && latest.version > 0) {
|
|
7486
|
+
const allCovered = needsTreeProof.every((cid) => cid < latest.version);
|
|
7487
|
+
if (allCovered) {
|
|
7488
|
+
version = latest;
|
|
7489
|
+
effectiveTreeElements = latest.version;
|
|
7497
7490
|
}
|
|
7498
|
-
|
|
7499
|
-
|
|
7500
|
-
|
|
7501
|
-
|
|
7502
|
-
|
|
7503
|
-
};
|
|
7504
|
-
} catch (error) {
|
|
7491
|
+
}
|
|
7492
|
+
}
|
|
7493
|
+
const hasDb = contractTreeElements === 0 || !!version;
|
|
7494
|
+
if (hasDb) {
|
|
7495
|
+
if (effectiveTreeElements > 0 && state.mergedElements < effectiveTreeElements) {
|
|
7505
7496
|
if (this.mode === "local") {
|
|
7506
|
-
throw new SdkError("MERKLE", "Local merkle
|
|
7497
|
+
throw new SdkError("MERKLE", "Local merkle db is behind contract", {
|
|
7498
|
+
chainId: input.chainId,
|
|
7499
|
+
cids,
|
|
7500
|
+
localMergedElements: state.mergedElements,
|
|
7501
|
+
contractTreeElements: effectiveTreeElements
|
|
7502
|
+
});
|
|
7507
7503
|
}
|
|
7504
|
+
} else {
|
|
7505
|
+
try {
|
|
7506
|
+
const proof = [];
|
|
7507
|
+
for (const cid of cids) {
|
|
7508
|
+
if (cid >= effectiveTreeElements) {
|
|
7509
|
+
proof.push({ leaf_index: cid, path: new Array(this.treeDepth + 1).fill("0") });
|
|
7510
|
+
continue;
|
|
7511
|
+
}
|
|
7512
|
+
const path = await this.buildLocalProofPath(input.chainId, cid, version);
|
|
7513
|
+
proof.push({ leaf_index: cid, path });
|
|
7514
|
+
}
|
|
7515
|
+
const effectiveRoot = effectiveTreeElements > 0 ? _MerkleEngine.normalizeHex32(version.rootHash, "version.rootHash") : getZeroHash(this.treeDepth);
|
|
7516
|
+
const effectiveLatestCid = effectiveTreeElements > 0 ? effectiveTreeElements - 1 : -1;
|
|
7517
|
+
return {
|
|
7518
|
+
proof,
|
|
7519
|
+
merkle_root: effectiveRoot,
|
|
7520
|
+
latest_cid: effectiveLatestCid
|
|
7521
|
+
};
|
|
7522
|
+
} catch (error) {
|
|
7523
|
+
if (this.mode === "local") {
|
|
7524
|
+
throw new SdkError("MERKLE", "Local merkle proof build failed", { chainId: input.chainId, cids }, error);
|
|
7525
|
+
}
|
|
7526
|
+
}
|
|
7527
|
+
}
|
|
7528
|
+
} else {
|
|
7529
|
+
if (this.mode === "local" && needsTreeProof.length) {
|
|
7530
|
+
throw new SdkError("MERKLE", "Local merkle db unavailable", { chainId: input.chainId, cids, reason: "missing_adapter_or_version" });
|
|
7508
7531
|
}
|
|
7509
7532
|
}
|
|
7510
7533
|
} else if (this.mode === "local" && needsTreeProof.length) {
|
|
7511
|
-
throw new SdkError("MERKLE", "Local merkle db unavailable", { chainId: input.chainId, cids, reason: "
|
|
7534
|
+
throw new SdkError("MERKLE", "Local merkle db unavailable", { chainId: input.chainId, cids, reason: "missing_adapter" });
|
|
7512
7535
|
}
|
|
7513
7536
|
}
|
|
7514
7537
|
if (needsTreeProof.length === 0) {
|