@blazephoenix/sdk 1.2.0 → 1.3.0
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/README.md +17 -6
- package/dist/index.cjs +44 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -2
- package/dist/index.d.ts +16 -2
- package/dist/index.js +44 -9
- package/dist/index.js.map +1 -1
- package/llms.txt +3 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -183,8 +183,10 @@ interface ExactQuote {
|
|
|
183
183
|
tokenIn: Address;
|
|
184
184
|
tokenOut: Address;
|
|
185
185
|
amountIn: bigint;
|
|
186
|
-
/** Execution-grade NET output (every concentrated leg dry-run on the
|
|
186
|
+
/** Execution-grade NET output (every concentrated leg dry-run on its venue), net of the protocol fee. */
|
|
187
187
|
exactOut: bigint;
|
|
188
|
+
/** The scalar exactly as the Quoter returned it (gross of the fee on 1.x Quoters). */
|
|
189
|
+
quoterOut: bigint;
|
|
188
190
|
route: Route;
|
|
189
191
|
quotedAt: number;
|
|
190
192
|
}
|
|
@@ -199,6 +201,13 @@ interface SwapRequest extends QuoteRequest {
|
|
|
199
201
|
recipient: Address;
|
|
200
202
|
/** The account that will send the swap — enables the allowance check and simulation. */
|
|
201
203
|
from?: Address;
|
|
204
|
+
/** With `from`: eth_call the built swap from that account before returning it, and fail closed
|
|
205
|
+
* (`not_executable`, no plan) on a revert. The Quoter's `canExecute` is swap math; whether these
|
|
206
|
+
* bytes settle for the payer is answered only by that call.
|
|
207
|
+
* Exception: while the Router still needs its approval, no eth_call is made. The plan comes back
|
|
208
|
+
* with `simulation: { ok: false, error.name: 'allowance' }`; send the approval, then `simulate()`
|
|
209
|
+
* again from the payer before sending the swap (`execute()` does this). */
|
|
210
|
+
simulate?: boolean;
|
|
202
211
|
/** Default 50 (0.5%). minOut = netOut − slippage, never below the on-chain floor. */
|
|
203
212
|
slippageBps?: number;
|
|
204
213
|
/** Seconds from now (default 120, 10–3600) — or pass an absolute `deadline`. */
|
|
@@ -232,6 +241,11 @@ interface ApprovalStep {
|
|
|
232
241
|
}
|
|
233
242
|
interface SwapPlan {
|
|
234
243
|
quote: Quote;
|
|
244
|
+
/** Present when built with `simulate: true`. Either the Router's eth_call from `from` settled
|
|
245
|
+
* (`ok: true`, `amountOut`), or no eth_call was made because the approval is still missing
|
|
246
|
+
* (`ok: false`, `error.name: 'allowance'`): approve, then `simulate()` again. A revert never
|
|
247
|
+
* reaches here; it is thrown as `not_executable`. */
|
|
248
|
+
simulation?: SimulationResult;
|
|
235
249
|
entry: 'swapExactIn' | 'swapExactInNative' | 'swapBestExactIn';
|
|
236
250
|
/** 'quoter': the bytes are the Quoter's own previewAndEncode output (2.x),
|
|
237
251
|
* verified field-by-field against what you asked; 'sdk': encoded locally. */
|
|
@@ -247,7 +261,7 @@ interface SwapPlan {
|
|
|
247
261
|
unwrapAfter: boolean;
|
|
248
262
|
/** Ordered transactions to send: [approval?, swap]. */
|
|
249
263
|
steps: TxRequest[];
|
|
250
|
-
/** With `exact: true`: the previewPlanExact output
|
|
264
|
+
/** With `exact: true`: the NET previewPlanExact output used to derive `minOut`. */
|
|
251
265
|
exactOut?: bigint;
|
|
252
266
|
}
|
|
253
267
|
interface SimulationResult {
|
package/dist/index.d.ts
CHANGED
|
@@ -183,8 +183,10 @@ interface ExactQuote {
|
|
|
183
183
|
tokenIn: Address;
|
|
184
184
|
tokenOut: Address;
|
|
185
185
|
amountIn: bigint;
|
|
186
|
-
/** Execution-grade NET output (every concentrated leg dry-run on the
|
|
186
|
+
/** Execution-grade NET output (every concentrated leg dry-run on its venue), net of the protocol fee. */
|
|
187
187
|
exactOut: bigint;
|
|
188
|
+
/** The scalar exactly as the Quoter returned it (gross of the fee on 1.x Quoters). */
|
|
189
|
+
quoterOut: bigint;
|
|
188
190
|
route: Route;
|
|
189
191
|
quotedAt: number;
|
|
190
192
|
}
|
|
@@ -199,6 +201,13 @@ interface SwapRequest extends QuoteRequest {
|
|
|
199
201
|
recipient: Address;
|
|
200
202
|
/** The account that will send the swap — enables the allowance check and simulation. */
|
|
201
203
|
from?: Address;
|
|
204
|
+
/** With `from`: eth_call the built swap from that account before returning it, and fail closed
|
|
205
|
+
* (`not_executable`, no plan) on a revert. The Quoter's `canExecute` is swap math; whether these
|
|
206
|
+
* bytes settle for the payer is answered only by that call.
|
|
207
|
+
* Exception: while the Router still needs its approval, no eth_call is made. The plan comes back
|
|
208
|
+
* with `simulation: { ok: false, error.name: 'allowance' }`; send the approval, then `simulate()`
|
|
209
|
+
* again from the payer before sending the swap (`execute()` does this). */
|
|
210
|
+
simulate?: boolean;
|
|
202
211
|
/** Default 50 (0.5%). minOut = netOut − slippage, never below the on-chain floor. */
|
|
203
212
|
slippageBps?: number;
|
|
204
213
|
/** Seconds from now (default 120, 10–3600) — or pass an absolute `deadline`. */
|
|
@@ -232,6 +241,11 @@ interface ApprovalStep {
|
|
|
232
241
|
}
|
|
233
242
|
interface SwapPlan {
|
|
234
243
|
quote: Quote;
|
|
244
|
+
/** Present when built with `simulate: true`. Either the Router's eth_call from `from` settled
|
|
245
|
+
* (`ok: true`, `amountOut`), or no eth_call was made because the approval is still missing
|
|
246
|
+
* (`ok: false`, `error.name: 'allowance'`): approve, then `simulate()` again. A revert never
|
|
247
|
+
* reaches here; it is thrown as `not_executable`. */
|
|
248
|
+
simulation?: SimulationResult;
|
|
235
249
|
entry: 'swapExactIn' | 'swapExactInNative' | 'swapBestExactIn';
|
|
236
250
|
/** 'quoter': the bytes are the Quoter's own previewAndEncode output (2.x),
|
|
237
251
|
* verified field-by-field against what you asked; 'sdk': encoded locally. */
|
|
@@ -247,7 +261,7 @@ interface SwapPlan {
|
|
|
247
261
|
unwrapAfter: boolean;
|
|
248
262
|
/** Ordered transactions to send: [approval?, swap]. */
|
|
249
263
|
steps: TxRequest[];
|
|
250
|
-
/** With `exact: true`: the previewPlanExact output
|
|
264
|
+
/** With `exact: true`: the NET previewPlanExact output used to derive `minOut`. */
|
|
251
265
|
exactOut?: bigint;
|
|
252
266
|
}
|
|
253
267
|
interface SimulationResult {
|
package/dist/index.js
CHANGED
|
@@ -4766,7 +4766,8 @@ var CHAINS = {
|
|
|
4766
4766
|
explorer: "https://robinhoodchain.blockscout.com",
|
|
4767
4767
|
weth: "0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73",
|
|
4768
4768
|
usdc: "0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168",
|
|
4769
|
-
blockTime:
|
|
4769
|
+
blockTime: 0.104
|
|
4770
|
+
// measured ~0.104 s/block
|
|
4770
4771
|
}
|
|
4771
4772
|
};
|
|
4772
4773
|
var ALIASES = {
|
|
@@ -4831,7 +4832,7 @@ function urlTransport(url, o) {
|
|
|
4831
4832
|
throw new BlazeError("bad_request", `refusing RPC URL "${redact(url)}": use https:// or wss:// (http/ws only for localhost)`);
|
|
4832
4833
|
}
|
|
4833
4834
|
const u = url.trim();
|
|
4834
|
-
return u.startsWith("ws") ? webSocket(u, { timeout: o.timeoutMs, retryCount: o.retries }) : http(u, { timeout: o.timeoutMs, retryCount: o.retries, batch: o.batch });
|
|
4835
|
+
return u.startsWith("ws") ? webSocket(u, { timeout: o.timeoutMs, retryCount: o.retries }) : http(u, { timeout: o.timeoutMs, retryCount: o.retries, batch: o.batch, fetchOptions: { redirect: "error" } });
|
|
4835
4836
|
}
|
|
4836
4837
|
function redact(url) {
|
|
4837
4838
|
try {
|
|
@@ -4979,6 +4980,9 @@ function scrubCause(c, depth = 0) {
|
|
|
4979
4980
|
out.name = c.name;
|
|
4980
4981
|
return out;
|
|
4981
4982
|
}
|
|
4983
|
+
function untrustedText(t, max = 120) {
|
|
4984
|
+
return (t ?? "").replace(/[^\x20-\x7e]+/g, " ").replace(/\s+/g, " ").trim().slice(0, max);
|
|
4985
|
+
}
|
|
4982
4986
|
var BlazeError = class extends Error {
|
|
4983
4987
|
code;
|
|
4984
4988
|
details;
|
|
@@ -5157,9 +5161,9 @@ var EMBEDDED_DEPLOYMENTS = {
|
|
|
5157
5161
|
{
|
|
5158
5162
|
version: "2.0.0",
|
|
5159
5163
|
status: "pending",
|
|
5160
|
-
source: "blazephoenixxyz-crypto/Blaze-Phoenix-Dex@
|
|
5164
|
+
source: "blazephoenixxyz-crypto/Blaze-Phoenix-Dex@f746a48",
|
|
5161
5165
|
notes: "Final generation (Core/Hub/Solver/Quoter/Router). Addresses arrive through the registry the day they are deployed.",
|
|
5162
|
-
chains: { 8453: pending(),
|
|
5166
|
+
chains: { 8453: pending(), 10: pending(), 42161: pending(), 4663: pending() }
|
|
5163
5167
|
},
|
|
5164
5168
|
{
|
|
5165
5169
|
version: "1.0.0",
|
|
@@ -5652,6 +5656,9 @@ function fromBaseUnits(v, decimals, maxDp) {
|
|
|
5652
5656
|
var HEX_ADDR2 = /^0x[0-9a-fA-F]{40}$/;
|
|
5653
5657
|
var INT = /^\d{1,78}$/;
|
|
5654
5658
|
var UINT128_MAX = (1n << 128n) - 1n;
|
|
5659
|
+
function netExactOutput(version, exactOut) {
|
|
5660
|
+
return featuresOf(version).previewAndEncode ? exactOut : exactOut - (exactOut * BigInt(FEE_BPS) + 9999n) / 10000n;
|
|
5661
|
+
}
|
|
5655
5662
|
var BlazePhoenix = class {
|
|
5656
5663
|
registry;
|
|
5657
5664
|
rpc;
|
|
@@ -5810,6 +5817,20 @@ var BlazePhoenix = class {
|
|
|
5810
5817
|
if (typeof req.amountIn === "bigint") v = req.amountIn;
|
|
5811
5818
|
else if (INT.test(String(req.amountIn).trim())) v = BigInt(String(req.amountIn).trim());
|
|
5812
5819
|
else throw new BlazeError("bad_request", 'amountIn must be an integer in base units \u2014 use `amount` for human units ("1.5")');
|
|
5820
|
+
if (req.amount !== void 0 && req.amount !== null && req.amount !== "") {
|
|
5821
|
+
const d = await this.decimalsOf(client, chainId, tIn).catch((e) => {
|
|
5822
|
+
throw new BlazeError("bad_request", "amount and amountIn are both set and the decimals could not be read to compare them \u2014 pass only one", { cause: e });
|
|
5823
|
+
});
|
|
5824
|
+
let human;
|
|
5825
|
+
try {
|
|
5826
|
+
human = toBaseUnits(req.amount, d);
|
|
5827
|
+
} catch (e) {
|
|
5828
|
+
throw new BlazeError("bad_request", e.message);
|
|
5829
|
+
}
|
|
5830
|
+
if (human !== v) {
|
|
5831
|
+
throw new BlazeError("bad_request", `amount and amountIn disagree (${human} vs ${v} base units): pass only one`);
|
|
5832
|
+
}
|
|
5833
|
+
}
|
|
5813
5834
|
} else if (req.amount !== void 0) {
|
|
5814
5835
|
const d = await this.decimalsOf(client, chainId, tIn).catch((e) => {
|
|
5815
5836
|
throw new BlazeError("bad_request", `could not read decimals of ${tIn.address} on your RPC \u2014 pass amountIn in base units`, { cause: e });
|
|
@@ -5917,13 +5938,15 @@ var BlazePhoenix = class {
|
|
|
5917
5938
|
args: [tIn.address, tOut.address, amountIn],
|
|
5918
5939
|
...req.blockNumber !== void 0 ? { blockNumber: req.blockNumber } : {}
|
|
5919
5940
|
});
|
|
5941
|
+
const net = netExactOutput(ctx.dep.version, exactOut);
|
|
5920
5942
|
return {
|
|
5921
5943
|
chainId: ctx.chainId,
|
|
5922
5944
|
version: ctx.dep.version,
|
|
5923
5945
|
tokenIn: tIn.address,
|
|
5924
5946
|
tokenOut: tOut.address,
|
|
5925
5947
|
amountIn,
|
|
5926
|
-
exactOut,
|
|
5948
|
+
exactOut: net,
|
|
5949
|
+
quoterOut: exactOut,
|
|
5927
5950
|
route,
|
|
5928
5951
|
quotedAt: Date.now()
|
|
5929
5952
|
};
|
|
@@ -6058,8 +6081,8 @@ var BlazePhoenix = class {
|
|
|
6058
6081
|
if (!samePath(ex[0], route)) {
|
|
6059
6082
|
throw new BlazeError("calldata_mismatch", "previewPlanExact priced a different route than the one to execute");
|
|
6060
6083
|
}
|
|
6061
|
-
exactOut = ex[1];
|
|
6062
|
-
return
|
|
6084
|
+
exactOut = netExactOutput(ctx.dep.version, ex[1]);
|
|
6085
|
+
return exactOut;
|
|
6063
6086
|
};
|
|
6064
6087
|
const settleMin = async (p) => {
|
|
6065
6088
|
let floor = minOutFor(p.netOut, slippageBps, p.ironFloor);
|
|
@@ -6159,7 +6182,7 @@ var BlazePhoenix = class {
|
|
|
6159
6182
|
}
|
|
6160
6183
|
}
|
|
6161
6184
|
const quote = this.buildQuote(ctx, tIn, tOut, amountIn, pv, fb);
|
|
6162
|
-
|
|
6185
|
+
const plan = {
|
|
6163
6186
|
quote,
|
|
6164
6187
|
entry,
|
|
6165
6188
|
encodedBy,
|
|
@@ -6173,6 +6196,18 @@ var BlazePhoenix = class {
|
|
|
6173
6196
|
steps: approval ? [approval.tx, tx] : [tx],
|
|
6174
6197
|
...exactOut !== void 0 ? { exactOut } : {}
|
|
6175
6198
|
};
|
|
6199
|
+
if (!req.simulate) return plan;
|
|
6200
|
+
if (!from) throw new BlazeError("bad_request", "simulate: true needs `from` (the account that will send the swap)");
|
|
6201
|
+
const simulation = await this.simulate(plan, from);
|
|
6202
|
+
if (!simulation.ok && simulation.error?.name !== "allowance") {
|
|
6203
|
+
const err = simulation.error;
|
|
6204
|
+
throw new BlazeError(
|
|
6205
|
+
"not_executable",
|
|
6206
|
+
`the Router refuses these bytes from ${from}: ${err?.name ?? "revert"}${err?.code !== void 0 ? `(${err.code})` : ""} \u2014 ${err?.reason ?? "execution reverted"}`,
|
|
6207
|
+
{ details: { from, error: err } }
|
|
6208
|
+
);
|
|
6209
|
+
}
|
|
6210
|
+
return { ...plan, simulation };
|
|
6176
6211
|
}
|
|
6177
6212
|
/** eth_call the swap from `from` on your RPC: the realised amountOut if it
|
|
6178
6213
|
* would settle now, or the decoded reason it would revert. */
|
|
@@ -6188,7 +6223,7 @@ var BlazePhoenix = class {
|
|
|
6188
6223
|
} catch (e) {
|
|
6189
6224
|
if (isTransportError(e)) throw new BlazeError("rpc_error", `simulation: your RPC failed (${e?.message?.split("\n")[0]})`, { cause: e });
|
|
6190
6225
|
const d = decodeBlazeError(e);
|
|
6191
|
-
return { ok: false, error: d ?? { contract: "unknown", name: "revert", reason: e?.message?.split("\n")[0]
|
|
6226
|
+
return { ok: false, error: d ?? { contract: "unknown", name: "revert", reason: untrustedText(e?.message?.split("\n")[0]) || "execution reverted" } };
|
|
6192
6227
|
}
|
|
6193
6228
|
}
|
|
6194
6229
|
/**
|