@persistenceone/bridgekitty 0.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/LICENSE +21 -0
- package/README.md +232 -0
- package/dist/backends/across.d.ts +10 -0
- package/dist/backends/across.js +285 -0
- package/dist/backends/debridge.d.ts +11 -0
- package/dist/backends/debridge.js +380 -0
- package/dist/backends/lifi.d.ts +19 -0
- package/dist/backends/lifi.js +295 -0
- package/dist/backends/persistence.d.ts +86 -0
- package/dist/backends/persistence.js +642 -0
- package/dist/backends/relay.d.ts +11 -0
- package/dist/backends/relay.js +292 -0
- package/dist/backends/squid.d.ts +31 -0
- package/dist/backends/squid.js +476 -0
- package/dist/backends/types.d.ts +125 -0
- package/dist/backends/types.js +11 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +154 -0
- package/dist/routing/engine.d.ts +49 -0
- package/dist/routing/engine.js +336 -0
- package/dist/tools/check-status.d.ts +3 -0
- package/dist/tools/check-status.js +93 -0
- package/dist/tools/execute-bridge.d.ts +3 -0
- package/dist/tools/execute-bridge.js +428 -0
- package/dist/tools/get-chains.d.ts +3 -0
- package/dist/tools/get-chains.js +162 -0
- package/dist/tools/get-quote.d.ts +3 -0
- package/dist/tools/get-quote.js +534 -0
- package/dist/tools/get-tokens.d.ts +3 -0
- package/dist/tools/get-tokens.js +128 -0
- package/dist/tools/help.d.ts +2 -0
- package/dist/tools/help.js +204 -0
- package/dist/tools/multi-quote.d.ts +3 -0
- package/dist/tools/multi-quote.js +310 -0
- package/dist/tools/onboard.d.ts +3 -0
- package/dist/tools/onboard.js +218 -0
- package/dist/tools/wallet.d.ts +14 -0
- package/dist/tools/wallet.js +744 -0
- package/dist/tools/xprt-farm.d.ts +3 -0
- package/dist/tools/xprt-farm.js +1308 -0
- package/dist/tools/xprt-rewards.d.ts +2 -0
- package/dist/tools/xprt-rewards.js +177 -0
- package/dist/tools/xprt-staking.d.ts +2 -0
- package/dist/tools/xprt-staking.js +565 -0
- package/dist/utils/chains.d.ts +22 -0
- package/dist/utils/chains.js +154 -0
- package/dist/utils/circuit-breaker.d.ts +64 -0
- package/dist/utils/circuit-breaker.js +160 -0
- package/dist/utils/evm.d.ts +18 -0
- package/dist/utils/evm.js +46 -0
- package/dist/utils/fill-detector.d.ts +70 -0
- package/dist/utils/fill-detector.js +298 -0
- package/dist/utils/gas-estimator.d.ts +67 -0
- package/dist/utils/gas-estimator.js +340 -0
- package/dist/utils/sanitize-error.d.ts +23 -0
- package/dist/utils/sanitize-error.js +101 -0
- package/dist/utils/token-registry.d.ts +70 -0
- package/dist/utils/token-registry.js +669 -0
- package/dist/utils/tokens.d.ts +17 -0
- package/dist/utils/tokens.js +37 -0
- package/dist/utils/tx-simulator.d.ts +27 -0
- package/dist/utils/tx-simulator.js +105 -0
- package/package.json +75 -0
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import { formatTokenAmount } from "../utils/tokens.js";
|
|
2
|
+
import { buildApproveData } from "../utils/evm.js";
|
|
3
|
+
import { sanitizeError } from "../utils/sanitize-error.js";
|
|
4
|
+
const BASE_URL = "https://li.quest/v1";
|
|
5
|
+
const TIMEOUT_MS = 30_000;
|
|
6
|
+
async function fetchJson(url, init) {
|
|
7
|
+
const controller = new AbortController();
|
|
8
|
+
const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
9
|
+
try {
|
|
10
|
+
const res = await fetch(url, { ...init, signal: controller.signal });
|
|
11
|
+
if (!res.ok) {
|
|
12
|
+
const text = await res.text().catch(() => "");
|
|
13
|
+
throw new Error(`LI.FI ${res.status}: ${text.slice(0, 200)}`);
|
|
14
|
+
}
|
|
15
|
+
return res.json();
|
|
16
|
+
}
|
|
17
|
+
finally {
|
|
18
|
+
clearTimeout(timer);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export class LiFiBackend {
|
|
22
|
+
name = "lifi";
|
|
23
|
+
apiKey;
|
|
24
|
+
integrator;
|
|
25
|
+
integratorFee;
|
|
26
|
+
constructor(apiKey, integrator, integratorFee) {
|
|
27
|
+
this.apiKey = apiKey;
|
|
28
|
+
this.integrator = integrator;
|
|
29
|
+
this.integratorFee = integratorFee;
|
|
30
|
+
}
|
|
31
|
+
headers() {
|
|
32
|
+
const h = { Accept: "application/json" };
|
|
33
|
+
if (this.apiKey)
|
|
34
|
+
h["x-lifi-api-key"] = this.apiKey;
|
|
35
|
+
return h;
|
|
36
|
+
}
|
|
37
|
+
async getQuote(params) {
|
|
38
|
+
const quotes = await this.getQuotes(params);
|
|
39
|
+
return quotes.length > 0 ? quotes[0] : null;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Fetch multiple routes via LI.FI /advanced/routes endpoint.
|
|
43
|
+
* Returns up to 5 route options with full fee breakdowns.
|
|
44
|
+
*/
|
|
45
|
+
async getQuotes(params) {
|
|
46
|
+
try {
|
|
47
|
+
const body = {
|
|
48
|
+
fromChainId: params.fromChainId,
|
|
49
|
+
toChainId: params.toChainId,
|
|
50
|
+
fromTokenAddress: params.fromTokenAddress,
|
|
51
|
+
toTokenAddress: params.toTokenAddress,
|
|
52
|
+
fromAmount: params.amountRaw,
|
|
53
|
+
fromAddress: params.fromAddress,
|
|
54
|
+
toAddress: params.toAddress || params.fromAddress,
|
|
55
|
+
options: {
|
|
56
|
+
order: params.preference === "fastest" ? "FASTEST" : "CHEAPEST",
|
|
57
|
+
slippage: 0.03,
|
|
58
|
+
maxPriceImpact: 0.4,
|
|
59
|
+
allowSwitchChain: false,
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
if (this.integrator) {
|
|
63
|
+
body.options.integrator = this.integrator;
|
|
64
|
+
if (this.integratorFee)
|
|
65
|
+
body.options.fee = parseFloat(this.integratorFee);
|
|
66
|
+
}
|
|
67
|
+
let data;
|
|
68
|
+
try {
|
|
69
|
+
data = await fetchJson(`${BASE_URL}/advanced/routes`, {
|
|
70
|
+
method: "POST",
|
|
71
|
+
headers: { ...this.headers(), "Content-Type": "application/json" },
|
|
72
|
+
body: JSON.stringify(body),
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
// If fee param caused the error, retry without it
|
|
77
|
+
if (this.integratorFee && body.options?.fee !== undefined) {
|
|
78
|
+
console.warn("[lifi] quote failed with integrator fee, retrying without fee:", err.message);
|
|
79
|
+
delete body.options.fee;
|
|
80
|
+
data = await fetchJson(`${BASE_URL}/advanced/routes`, {
|
|
81
|
+
method: "POST",
|
|
82
|
+
headers: { ...this.headers(), "Content-Type": "application/json" },
|
|
83
|
+
body: JSON.stringify(body),
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
throw err;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const routes = data.routes ?? [];
|
|
91
|
+
if (routes.length === 0)
|
|
92
|
+
return [];
|
|
93
|
+
// Filter to single-step routes only — our buildTransaction() only handles step[0],
|
|
94
|
+
// so multi-step routes would silently drop subsequent steps. Let LI.FI handle
|
|
95
|
+
// complex multi-hop routes internally; we only expose atomic single-step bridges.
|
|
96
|
+
const singleStepRoutes = routes.filter((r) => (r.steps?.length ?? 0) === 1);
|
|
97
|
+
if (singleStepRoutes.length === 0)
|
|
98
|
+
return [];
|
|
99
|
+
const integratorFeePercent = this.integratorFee
|
|
100
|
+
? `${(parseFloat(this.integratorFee) * 100).toFixed(1)}%`
|
|
101
|
+
: null;
|
|
102
|
+
return singleStepRoutes.slice(0, 5).map((route) => {
|
|
103
|
+
const steps = route.steps ?? [];
|
|
104
|
+
const firstStep = steps[0];
|
|
105
|
+
const lastStep = steps[steps.length - 1];
|
|
106
|
+
// Fee breakdown from route data
|
|
107
|
+
const gasCostUsd = route.gasCostUSD ? parseFloat(route.gasCostUSD) : 0;
|
|
108
|
+
// Extract protocol fees from step fee costs
|
|
109
|
+
let protocolFeeUsd = 0;
|
|
110
|
+
let integratorFeeUsd = 0;
|
|
111
|
+
for (const step of steps) {
|
|
112
|
+
const estimate = step.estimate ?? {};
|
|
113
|
+
const feeCosts = estimate.feeCosts ?? [];
|
|
114
|
+
for (const fee of feeCosts) {
|
|
115
|
+
const usd = parseFloat(fee.amountUSD || "0");
|
|
116
|
+
if (fee.name?.toLowerCase().includes("integrator") ||
|
|
117
|
+
fee.name?.toLowerCase().includes("affiliate")) {
|
|
118
|
+
integratorFeeUsd += usd;
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
protocolFeeUsd += usd;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
const totalFeeUsd = gasCostUsd + protocolFeeUsd + integratorFeeUsd;
|
|
126
|
+
const feeBreakdown = {
|
|
127
|
+
gasCostUsd: Math.round(gasCostUsd * 100) / 100,
|
|
128
|
+
protocolFeeUsd: Math.round(protocolFeeUsd * 100) / 100,
|
|
129
|
+
integratorFeeUsd: Math.round(integratorFeeUsd * 100) / 100,
|
|
130
|
+
integratorFeePercent,
|
|
131
|
+
totalFeeUsd: Math.round(totalFeeUsd * 100) / 100,
|
|
132
|
+
};
|
|
133
|
+
// Build human-readable route description
|
|
134
|
+
const toolNames = steps
|
|
135
|
+
.map((s) => s.toolDetails?.name ?? s.tool ?? "?")
|
|
136
|
+
.join(" → ");
|
|
137
|
+
const fromSymbol = firstStep?.action?.fromToken?.symbol ?? "?";
|
|
138
|
+
const toSymbol = lastStep?.action?.toToken?.symbol ?? "?";
|
|
139
|
+
const toDecimals = lastStep?.action?.toToken?.decimals ?? 18;
|
|
140
|
+
// Extract minimum output amount (after slippage)
|
|
141
|
+
// LI.FI provides toAmountMin at the route level
|
|
142
|
+
const minOutputRaw = route.toAmountMin ?? route.toAmount ?? "0";
|
|
143
|
+
return {
|
|
144
|
+
backendName: "lifi",
|
|
145
|
+
provider: `${toolNames} via LI.FI`,
|
|
146
|
+
outputAmount: route.toAmount
|
|
147
|
+
? formatTokenAmount(route.toAmount, toDecimals)
|
|
148
|
+
: "0",
|
|
149
|
+
outputAmountRaw: route.toAmount ?? "0",
|
|
150
|
+
minOutputAmount: formatTokenAmount(minOutputRaw, toDecimals),
|
|
151
|
+
minOutputAmountRaw: minOutputRaw,
|
|
152
|
+
outputDecimals: toDecimals,
|
|
153
|
+
estimatedGasCostUsd: Math.round(gasCostUsd * 100) / 100,
|
|
154
|
+
estimatedFeeUsd: totalFeeUsd,
|
|
155
|
+
feeBreakdown,
|
|
156
|
+
estimatedTimeSeconds: steps.reduce((sum, s) => sum + (s.estimate?.executionDuration ?? 0), 0) || 300,
|
|
157
|
+
route: `${fromSymbol} → ${toolNames} → ${toSymbol}`,
|
|
158
|
+
quoteData: route,
|
|
159
|
+
// LI.FI quotes are volatile (DEX prices shift rapidly) — use 30s expiry
|
|
160
|
+
expiresAt: Date.now() + 60_000,
|
|
161
|
+
};
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
catch (err) {
|
|
165
|
+
console.error("[lifi] advanced/routes error:", err.message);
|
|
166
|
+
return [];
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
async buildTransaction(quote) {
|
|
170
|
+
const route = quote.quoteData;
|
|
171
|
+
// For /advanced/routes, get step transaction from the first step
|
|
172
|
+
const step = route.steps?.[0];
|
|
173
|
+
if (!step)
|
|
174
|
+
throw new Error("No steps in LI.FI route");
|
|
175
|
+
// Call /advanced/stepTransaction to get the actual tx data
|
|
176
|
+
const stepData = await fetchJson(`${BASE_URL}/advanced/stepTransaction`, {
|
|
177
|
+
method: "POST",
|
|
178
|
+
headers: { ...this.headers(), "Content-Type": "application/json" },
|
|
179
|
+
body: JSON.stringify(step),
|
|
180
|
+
});
|
|
181
|
+
const txReq = stepData.transactionRequest;
|
|
182
|
+
if (!txReq)
|
|
183
|
+
throw new Error("No transactionRequest in LI.FI step response");
|
|
184
|
+
const toolName = step.tool ?? step.toolDetails?.name ?? "unknown";
|
|
185
|
+
const result = {
|
|
186
|
+
to: txReq.to,
|
|
187
|
+
data: txReq.data,
|
|
188
|
+
value: txReq.value ?? "0x0",
|
|
189
|
+
chainId: txReq.chainId,
|
|
190
|
+
gasLimit: txReq.gasLimit,
|
|
191
|
+
provider: "lifi",
|
|
192
|
+
trackingId: `lifi:${toolName}:${Date.now()}`,
|
|
193
|
+
};
|
|
194
|
+
// Check if approval is needed
|
|
195
|
+
const estimate = stepData.estimate ?? step.estimate;
|
|
196
|
+
const action = stepData.action ?? step.action;
|
|
197
|
+
if (estimate?.approvalAddress && action?.fromToken?.address) {
|
|
198
|
+
const tokenAddr = action.fromToken.address;
|
|
199
|
+
// Non-native tokens may need approval
|
|
200
|
+
if (tokenAddr !== "0x0000000000000000000000000000000000000000") {
|
|
201
|
+
// MEDIUM-001: Sanity-check approval amount against quoted input
|
|
202
|
+
let approvalAmount = action.fromAmount;
|
|
203
|
+
const quotedInput = route.steps?.[0]?.action?.fromAmount ?? route.fromAmount;
|
|
204
|
+
if (quotedInput && approvalAmount) {
|
|
205
|
+
const approvalBn = BigInt(approvalAmount);
|
|
206
|
+
const quotedBn = BigInt(quotedInput);
|
|
207
|
+
const maxAllowed = (quotedBn * 110n) / 100n; // 110% of quoted
|
|
208
|
+
if (approvalBn > maxAllowed) {
|
|
209
|
+
console.warn(`[lifi] Approval amount ${approvalAmount} exceeds 110% of quoted input ${quotedInput}. Capping to ${maxAllowed.toString()}.`);
|
|
210
|
+
approvalAmount = maxAllowed.toString();
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
result.approvalTx = {
|
|
214
|
+
to: tokenAddr,
|
|
215
|
+
data: buildApproveData(estimate.approvalAddress, approvalAmount),
|
|
216
|
+
value: "0x0",
|
|
217
|
+
chainId: txReq.chainId,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return result;
|
|
222
|
+
}
|
|
223
|
+
async getStatus(trackingId, meta) {
|
|
224
|
+
try {
|
|
225
|
+
const txHash = meta?.txHash;
|
|
226
|
+
const fromChain = meta?.fromChain;
|
|
227
|
+
const toChain = meta?.toChain;
|
|
228
|
+
if (!txHash) {
|
|
229
|
+
return {
|
|
230
|
+
state: "unknown",
|
|
231
|
+
humanReadable: "No transaction hash provided for status check",
|
|
232
|
+
provider: "lifi",
|
|
233
|
+
elapsed: 0,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
const url = new URL(`${BASE_URL}/status`);
|
|
237
|
+
url.searchParams.set("txHash", txHash);
|
|
238
|
+
if (fromChain)
|
|
239
|
+
url.searchParams.set("fromChain", fromChain);
|
|
240
|
+
if (toChain)
|
|
241
|
+
url.searchParams.set("toChain", toChain);
|
|
242
|
+
const data = await fetchJson(url.toString(), { headers: this.headers() });
|
|
243
|
+
const stateMap = {
|
|
244
|
+
NOT_FOUND: "pending",
|
|
245
|
+
PENDING: "pending",
|
|
246
|
+
DONE: "completed",
|
|
247
|
+
FAILED: "failed",
|
|
248
|
+
};
|
|
249
|
+
const elapsed = data.sending?.timestamp
|
|
250
|
+
? Math.floor((Date.now() - data.sending.timestamp * 1000) / 1000)
|
|
251
|
+
: 0;
|
|
252
|
+
return {
|
|
253
|
+
state: stateMap[data.status] ?? "in_progress",
|
|
254
|
+
humanReadable: `Bridge via ${data.tool ?? "LI.FI"}: ${data.status ?? "unknown"}${data.substatus ? ` (${data.substatus})` : ""}`,
|
|
255
|
+
sourceTxHash: data.sending?.txHash,
|
|
256
|
+
destTxHash: data.receiving?.txHash,
|
|
257
|
+
provider: "lifi",
|
|
258
|
+
elapsed,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
catch (err) {
|
|
262
|
+
return {
|
|
263
|
+
state: "unknown",
|
|
264
|
+
humanReadable: `Status check failed: ${sanitizeError(err)}`,
|
|
265
|
+
provider: "lifi",
|
|
266
|
+
elapsed: 0,
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
async getSupportedChains() {
|
|
271
|
+
const data = await fetchJson(`${BASE_URL}/chains`, {
|
|
272
|
+
headers: this.headers(),
|
|
273
|
+
});
|
|
274
|
+
return (data.chains ?? []).map((c) => ({
|
|
275
|
+
id: c.id,
|
|
276
|
+
name: c.name,
|
|
277
|
+
key: c.key,
|
|
278
|
+
logoURI: c.logoURI,
|
|
279
|
+
providers: ["lifi"],
|
|
280
|
+
}));
|
|
281
|
+
}
|
|
282
|
+
async getSupportedTokens(chainId) {
|
|
283
|
+
const data = await fetchJson(`${BASE_URL}/tokens?chains=${chainId}`, { headers: this.headers() });
|
|
284
|
+
const tokens = data.tokens?.[String(chainId)] ?? [];
|
|
285
|
+
return tokens.slice(0, 50).map((t) => ({
|
|
286
|
+
symbol: t.symbol,
|
|
287
|
+
name: t.name,
|
|
288
|
+
address: t.address,
|
|
289
|
+
decimals: t.decimals,
|
|
290
|
+
chainId: t.chainId,
|
|
291
|
+
logoURI: t.logoURI,
|
|
292
|
+
}));
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
// buildApproveData imported from ../utils/evm.js
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { ethers } from "ethers";
|
|
2
|
+
import type { BridgeBackend, BridgeQuote, BridgeStatus, ChainInfo, QuoteParams, TransactionRequest } from "./types.js";
|
|
3
|
+
import { BackendValidationError } from "./types.js";
|
|
4
|
+
/**
|
|
5
|
+
* @deprecated Use BackendValidationError from types.ts instead.
|
|
6
|
+
* Kept as re-export for backward compatibility.
|
|
7
|
+
*/
|
|
8
|
+
export declare const PersistenceValidationError: typeof BackendValidationError;
|
|
9
|
+
declare const PERMIT2_WITNESS_TYPES: {
|
|
10
|
+
CrossChainOrder: {
|
|
11
|
+
name: string;
|
|
12
|
+
type: string;
|
|
13
|
+
}[];
|
|
14
|
+
PermitWitnessTransferFrom: {
|
|
15
|
+
name: string;
|
|
16
|
+
type: string;
|
|
17
|
+
}[];
|
|
18
|
+
TokenPermissions: {
|
|
19
|
+
name: string;
|
|
20
|
+
type: string;
|
|
21
|
+
}[];
|
|
22
|
+
};
|
|
23
|
+
/** Prepared order data ready for signing */
|
|
24
|
+
export interface PreparedOrder {
|
|
25
|
+
order: {
|
|
26
|
+
settlementContract: string;
|
|
27
|
+
swapper: string;
|
|
28
|
+
nonce: bigint;
|
|
29
|
+
originChainId: number;
|
|
30
|
+
initiateDeadline: number;
|
|
31
|
+
fillDeadline: number;
|
|
32
|
+
orderData: string;
|
|
33
|
+
};
|
|
34
|
+
eip712Domain: {
|
|
35
|
+
name: string;
|
|
36
|
+
chainId: number;
|
|
37
|
+
verifyingContract: string;
|
|
38
|
+
};
|
|
39
|
+
eip712Types: typeof PERMIT2_WITNESS_TYPES;
|
|
40
|
+
eip712Value: Record<string, unknown>;
|
|
41
|
+
inputToken: string;
|
|
42
|
+
inputAmount: string;
|
|
43
|
+
approvalTx: {
|
|
44
|
+
to: string;
|
|
45
|
+
data: string;
|
|
46
|
+
value: string;
|
|
47
|
+
chainId: number;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
export declare class PersistenceBackend implements BridgeBackend {
|
|
51
|
+
name: string;
|
|
52
|
+
/**
|
|
53
|
+
* Validate amount against Persistence Interop caps.
|
|
54
|
+
* Caps are defined in 8-decimal BTC units (MIN_AMOUNT_RAW=5000, MAX_AMOUNT_RAW=100000).
|
|
55
|
+
* BTCB uses 18 decimals, cbBTC uses 8 decimals — normalize before comparing.
|
|
56
|
+
*/
|
|
57
|
+
private validateAmount;
|
|
58
|
+
getQuote(params: QuoteParams): Promise<BridgeQuote | null>;
|
|
59
|
+
/**
|
|
60
|
+
* Prepare a CrossChainOrder for signing. This calls the settlement contract
|
|
61
|
+
* on-chain to get a properly formed order with nonce and orderData.
|
|
62
|
+
*/
|
|
63
|
+
prepareOrder(quote: BridgeQuote, swapperAddress: string): Promise<PreparedOrder>;
|
|
64
|
+
/**
|
|
65
|
+
* Build transaction data for the MCP flow (no server-side signing).
|
|
66
|
+
* Calls prepareOrder() via on-chain view to get the EIP-712 typed data
|
|
67
|
+
* and Permit2 approval tx that the agent/wallet must sign externally.
|
|
68
|
+
*
|
|
69
|
+
* Use signAndExecute() for flows where a signer (private key) is available.
|
|
70
|
+
*/
|
|
71
|
+
buildTransaction(quote: BridgeQuote): Promise<TransactionRequest>;
|
|
72
|
+
/**
|
|
73
|
+
* Full sign-and-execute flow for when a signer (private key) is available.
|
|
74
|
+
* This is used by test scripts and the ACP listener.
|
|
75
|
+
*
|
|
76
|
+
* Returns the source chain tx hash and order ID for tracking.
|
|
77
|
+
*/
|
|
78
|
+
signAndExecute(quote: BridgeQuote, signer: ethers.Wallet): Promise<{
|
|
79
|
+
txHash: string;
|
|
80
|
+
orderId: string;
|
|
81
|
+
trackingId: string;
|
|
82
|
+
}>;
|
|
83
|
+
getStatus(trackingId: string, meta?: Record<string, string>): Promise<BridgeStatus>;
|
|
84
|
+
getSupportedChains(): Promise<ChainInfo[]>;
|
|
85
|
+
}
|
|
86
|
+
export {};
|