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