@anywalletkit/protocol-swap2-relay 0.0.0-stage → 0.1.1
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 +202 -0
- package/README.md +116 -2
- package/dist/activity.cjs +82 -0
- package/dist/activity.cjs.map +1 -0
- package/dist/activity.d.cts +15 -0
- package/dist/activity.d.ts +15 -0
- package/dist/activity.js +10 -0
- package/dist/activity.js.map +1 -0
- package/dist/chunk-7LPLU3MB.js +27 -0
- package/dist/chunk-7LPLU3MB.js.map +1 -0
- package/dist/chunk-CCMNAZZB.js +307 -0
- package/dist/chunk-CCMNAZZB.js.map +1 -0
- package/dist/chunk-JQAN7HB5.js +80 -0
- package/dist/chunk-JQAN7HB5.js.map +1 -0
- package/dist/chunk-K5F3BEUO.js +22 -0
- package/dist/chunk-K5F3BEUO.js.map +1 -0
- package/dist/chunk-UVHDMGM5.js +190 -0
- package/dist/chunk-UVHDMGM5.js.map +1 -0
- package/dist/chunk-WRIKAUWI.js +384 -0
- package/dist/chunk-WRIKAUWI.js.map +1 -0
- package/dist/config.cjs +100 -0
- package/dist/config.cjs.map +1 -0
- package/dist/config.d.cts +58 -0
- package/dist/config.d.ts +58 -0
- package/dist/config.js +35 -0
- package/dist/config.js.map +1 -0
- package/dist/index.cjs +965 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +11 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +98 -0
- package/dist/index.js.map +1 -0
- package/dist/order.cjs +210 -0
- package/dist/order.cjs.map +1 -0
- package/dist/order.d.cts +178 -0
- package/dist/order.d.ts +178 -0
- package/dist/order.js +15 -0
- package/dist/order.js.map +1 -0
- package/dist/protocol.cjs +922 -0
- package/dist/protocol.cjs.map +1 -0
- package/dist/protocol.d.cts +16 -0
- package/dist/protocol.d.ts +16 -0
- package/dist/protocol.js +12 -0
- package/dist/protocol.js.map +1 -0
- package/dist/provider.cjs +907 -0
- package/dist/provider.cjs.map +1 -0
- package/dist/provider.d.cts +31 -0
- package/dist/provider.d.ts +31 -0
- package/dist/provider.js +13 -0
- package/dist/provider.js.map +1 -0
- package/dist/verify.cjs +617 -0
- package/dist/verify.cjs.map +1 -0
- package/dist/verify.d.cts +151 -0
- package/dist/verify.d.ts +151 -0
- package/dist/verify.js +39 -0
- package/dist/verify.js.map +1 -0
- package/module.json +42 -0
- package/package.json +99 -3
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import {
|
|
2
|
+
RELAY_DEFAULT_SLIPPAGE_BPS,
|
|
3
|
+
RELAY_GAS_CAP,
|
|
4
|
+
RELAY_GAS_FLOOR_ERC20,
|
|
5
|
+
RELAY_GAS_FLOOR_NATIVE,
|
|
6
|
+
checkRelayQuote,
|
|
7
|
+
relayClearOrder,
|
|
8
|
+
relayRequestOf,
|
|
9
|
+
verifyRelayOrder
|
|
10
|
+
} from "./chunk-WRIKAUWI.js";
|
|
11
|
+
import {
|
|
12
|
+
RelayRefusal
|
|
13
|
+
} from "./chunk-UVHDMGM5.js";
|
|
14
|
+
import {
|
|
15
|
+
describeRelayActivity
|
|
16
|
+
} from "./chunk-K5F3BEUO.js";
|
|
17
|
+
import {
|
|
18
|
+
RELAY_API,
|
|
19
|
+
relay,
|
|
20
|
+
relayChain
|
|
21
|
+
} from "./chunk-JQAN7HB5.js";
|
|
22
|
+
|
|
23
|
+
// src/provider.ts
|
|
24
|
+
import { anySignal, redactUrls, timeoutSignal } from "@anywalletkit/protocol-swap2-core/util";
|
|
25
|
+
var EVM_PLACEHOLDER = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045";
|
|
26
|
+
var DEFAULT_QUOTE_TTL_MS = 6e4;
|
|
27
|
+
var QUOTE_TIMEOUT_MS = 2e4;
|
|
28
|
+
var STATUS_TIMEOUT_MS = 12e3;
|
|
29
|
+
var INTENT_PREFIX = "relay:";
|
|
30
|
+
var REQUEST_ID = /^0x[0-9a-f]{64}$/;
|
|
31
|
+
var MAX_BODY = 512 * 1024;
|
|
32
|
+
var MAX_REMEMBERED = 256;
|
|
33
|
+
var RELAY_STATUS_MAP = Object.freeze({
|
|
34
|
+
waiting: "pending",
|
|
35
|
+
depositing: "pending",
|
|
36
|
+
pending: "pending",
|
|
37
|
+
submitted: "pending",
|
|
38
|
+
delayed: "pending",
|
|
39
|
+
unknown: "pending",
|
|
40
|
+
success: "completed",
|
|
41
|
+
refund: "refunded",
|
|
42
|
+
refunded: "refunded",
|
|
43
|
+
failure: "refund-pending"
|
|
44
|
+
});
|
|
45
|
+
function clip(text, max = 240) {
|
|
46
|
+
const t = redactUrls(text).replace(/\s+/g, " ").trim();
|
|
47
|
+
return t.length > max ? `${t.slice(0, max)}\u2026` : t;
|
|
48
|
+
}
|
|
49
|
+
function depositStep(body) {
|
|
50
|
+
const steps = body.steps;
|
|
51
|
+
if (!Array.isArray(steps) || steps.length === 0 || steps.length > 8) throw new RelayRefusal("quote-steps", "the quote has no steps");
|
|
52
|
+
let found = null;
|
|
53
|
+
for (const s of steps) {
|
|
54
|
+
if (s === null || typeof s !== "object") throw new RelayRefusal("quote-steps", "the quote has a malformed step");
|
|
55
|
+
if (s.id === "approve") continue;
|
|
56
|
+
if (s.id !== "deposit") throw new RelayRefusal("quote-steps", `the quote needs a "${clip(String(s.id), 40)}" step, only a single deposit is signed`);
|
|
57
|
+
if (found) throw new RelayRefusal("quote-steps", "the quote has more than one deposit step");
|
|
58
|
+
found = s;
|
|
59
|
+
}
|
|
60
|
+
if (!found) throw new RelayRefusal("quote-steps", "the quote has no deposit step");
|
|
61
|
+
const items = found.items;
|
|
62
|
+
if (!Array.isArray(items) || items.length !== 1) throw new RelayRefusal("quote-steps", "the deposit step is not a single transaction");
|
|
63
|
+
const data = items[0]?.data;
|
|
64
|
+
if (data === null || typeof data !== "object") throw new RelayRefusal("quote-steps", "the deposit step has no transaction");
|
|
65
|
+
const requestId = typeof found.requestId === "string" ? found.requestId.toLowerCase() : "";
|
|
66
|
+
if (!REQUEST_ID.test(requestId)) throw new RelayRefusal("quote-steps", "the quote has no request id to track the deposit by");
|
|
67
|
+
return { requestId, tx: data };
|
|
68
|
+
}
|
|
69
|
+
function relayProvider(config = {}) {
|
|
70
|
+
config = Object.freeze({ ...config });
|
|
71
|
+
const base = (config.baseUrl ?? RELAY_API).replace(/\/+$/, "");
|
|
72
|
+
if (!/^https?:\/\//.test(base)) throw new Error("relay: baseUrl must use http or https");
|
|
73
|
+
const quoteTtlMs = config.quoteTtlMs ?? DEFAULT_QUOTE_TTL_MS;
|
|
74
|
+
if (!Number.isInteger(quoteTtlMs) || quoteTtlMs <= 0 || quoteTtlMs > 3e5) throw new Error("relay: quoteTtlMs must be an integer between 1 and 300000");
|
|
75
|
+
if (config.apiKey !== void 0 && (typeof config.apiKey !== "string" || !/^[\x21-\x7e]{1,256}$/.test(config.apiKey))) throw new Error("relay: apiKey must be a printable string");
|
|
76
|
+
const doFetch = (input, init) => (config.fetchImpl ?? fetch)(input, init);
|
|
77
|
+
const headers = (json) => ({
|
|
78
|
+
accept: "application/json",
|
|
79
|
+
...json ? { "content-type": "application/json" } : {},
|
|
80
|
+
...config.apiKey ? { "x-api-key": config.apiKey } : {}
|
|
81
|
+
});
|
|
82
|
+
const issued = /* @__PURE__ */ new Map();
|
|
83
|
+
const remember = (m, k, v) => {
|
|
84
|
+
m.delete(k);
|
|
85
|
+
m.set(k, v);
|
|
86
|
+
if (m.size > MAX_REMEMBERED) m.delete(m.keys().next().value);
|
|
87
|
+
};
|
|
88
|
+
function requestOf(quote) {
|
|
89
|
+
const pd = quote.providerData ?? {};
|
|
90
|
+
const sealed = {
|
|
91
|
+
sourceChain: pd.sourceChain ?? "",
|
|
92
|
+
destChain: pd.destChain ?? "",
|
|
93
|
+
sourceToken: pd.sourceToken ?? "",
|
|
94
|
+
destToken: pd.destToken ?? "",
|
|
95
|
+
amount: /^[1-9]\d{0,77}$/.test(pd.amount ?? "") ? BigInt(pd.amount) : 0n,
|
|
96
|
+
depositor: pd.depositor ?? "",
|
|
97
|
+
recipient: pd.recipient ?? "",
|
|
98
|
+
.../^\d{1,78}$/.test(pd.minAmountOut ?? "") ? { minAmountOut: BigInt(pd.minAmountOut) } : {},
|
|
99
|
+
.../^\d{1,5}$/.test(pd.slippageBps ?? "") ? { slippageBps: Number(pd.slippageBps) } : {}
|
|
100
|
+
};
|
|
101
|
+
if (sealed.depositor.toLowerCase() === EVM_PLACEHOLDER.toLowerCase() || sealed.recipient.toLowerCase() === EVM_PLACEHOLDER.toLowerCase()) {
|
|
102
|
+
throw new RelayRefusal("request-invalid", "a quote priced without the real addresses is never built or signed \u2014 quote again with them");
|
|
103
|
+
}
|
|
104
|
+
const mine = issued.get(quote.intentId);
|
|
105
|
+
if (!mine) return sealed;
|
|
106
|
+
const same = mine.sourceChain === sealed.sourceChain && mine.destChain === sealed.destChain && mine.amount === sealed.amount && mine.sourceToken.toLowerCase() === sealed.sourceToken.toLowerCase() && mine.destToken.toLowerCase() === sealed.destToken.toLowerCase() && mine.depositor.toLowerCase() === sealed.depositor.toLowerCase() && mine.recipient.toLowerCase() === sealed.recipient.toLowerCase();
|
|
107
|
+
if (!same) throw new RelayRefusal("request-invalid", "the quote no longer says what was asked when it was issued \u2014 quote again");
|
|
108
|
+
return mine;
|
|
109
|
+
}
|
|
110
|
+
async function readJson(res) {
|
|
111
|
+
const text = await res.text();
|
|
112
|
+
if (text.length > MAX_BODY) throw new Error("relay: response too large");
|
|
113
|
+
return JSON.parse(text);
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
name: "relay",
|
|
117
|
+
describeActivity: describeRelayActivity,
|
|
118
|
+
enabled: () => config.enabled ?? true,
|
|
119
|
+
supportsChain: (chain) => relay.supportsChain(chain),
|
|
120
|
+
supportsChainPair: (from, to) => relay.supports(from, to),
|
|
121
|
+
supportsRoute: (from, to) => relay.supports(from.chain, to.chain),
|
|
122
|
+
async getQuote(params, signal) {
|
|
123
|
+
const refuse = (reason) => {
|
|
124
|
+
params.onRefusal?.(reason);
|
|
125
|
+
return null;
|
|
126
|
+
};
|
|
127
|
+
const dry = params.dry !== false;
|
|
128
|
+
const placeholder = dry && (!params.destAddress || !params.refundAddress);
|
|
129
|
+
let request;
|
|
130
|
+
try {
|
|
131
|
+
request = relayRequestOf(params, dry ? { placeholder: EVM_PLACEHOLDER } : {});
|
|
132
|
+
} catch (err) {
|
|
133
|
+
if (err instanceof RelayRefusal) return refuse(err.message);
|
|
134
|
+
throw err;
|
|
135
|
+
}
|
|
136
|
+
const src = relayChain(request.sourceChain);
|
|
137
|
+
const dst = relayChain(request.destChain);
|
|
138
|
+
let body;
|
|
139
|
+
try {
|
|
140
|
+
const res = await doFetch(`${base}/quote/v2`, {
|
|
141
|
+
method: "POST",
|
|
142
|
+
headers: headers(true),
|
|
143
|
+
body: JSON.stringify({
|
|
144
|
+
user: request.depositor,
|
|
145
|
+
recipient: request.recipient,
|
|
146
|
+
refundTo: request.depositor,
|
|
147
|
+
originChainId: src.chainId,
|
|
148
|
+
destinationChainId: dst.chainId,
|
|
149
|
+
originCurrency: request.sourceToken.toLowerCase(),
|
|
150
|
+
destinationCurrency: request.destToken.toLowerCase(),
|
|
151
|
+
amount: request.amount.toString(10),
|
|
152
|
+
tradeType: "EXACT_INPUT",
|
|
153
|
+
includeProtocolData: true,
|
|
154
|
+
// Always named: Relay's "auto" would leave the distance between expected and minimum to the answering side.
|
|
155
|
+
slippageTolerance: String(request.slippageBps ?? RELAY_DEFAULT_SLIPPAGE_BPS)
|
|
156
|
+
}),
|
|
157
|
+
signal: signal ? anySignal([signal, timeoutSignal(QUOTE_TIMEOUT_MS)]) : timeoutSignal(QUOTE_TIMEOUT_MS)
|
|
158
|
+
});
|
|
159
|
+
let parsed;
|
|
160
|
+
try {
|
|
161
|
+
parsed = await readJson(res);
|
|
162
|
+
} catch {
|
|
163
|
+
parsed = null;
|
|
164
|
+
}
|
|
165
|
+
if (!res.ok) {
|
|
166
|
+
const e = parsed ?? {};
|
|
167
|
+
const why = typeof e.message === "string" ? clip(e.message) : `HTTP ${res.status}`;
|
|
168
|
+
return refuse(`relay: no quote \u2014 ${typeof e.errorCode === "string" ? `${clip(e.errorCode, 60)}: ` : ""}${why}`);
|
|
169
|
+
}
|
|
170
|
+
if (parsed === null || typeof parsed !== "object") return refuse("relay: the quote response is not JSON");
|
|
171
|
+
body = parsed;
|
|
172
|
+
} catch (err) {
|
|
173
|
+
return refuse(`relay: quote request failed \u2014 ${clip(err instanceof Error ? err.message : String(err))}`);
|
|
174
|
+
}
|
|
175
|
+
try {
|
|
176
|
+
const step = depositStep(body);
|
|
177
|
+
const proto = body.protocol?.v2 ?? null;
|
|
178
|
+
const v = verifyRelayOrder(request, proto, step.tx);
|
|
179
|
+
const extra = (x) => x !== void 0 && x !== null && x !== "0" && x !== 0;
|
|
180
|
+
if (extra(body.fees?.app?.amount)) throw new RelayRefusal("app-fee", "the quote charges an app fee this module did not ask for");
|
|
181
|
+
if (extra(body.details?.currencyGasTopup?.amount)) throw new RelayRefusal("gas-topup", "the quote converts part of the output into a gas top-up this module did not ask for");
|
|
182
|
+
const native = v.deposit.approvalAddress === void 0;
|
|
183
|
+
const floor = native ? RELAY_GAS_FLOOR_NATIVE : RELAY_GAS_FLOOR_ERC20;
|
|
184
|
+
const apiGas = typeof step.tx.gas === "string" && /^[1-9]\d{0,9}$/.test(step.tx.gas) ? BigInt(step.tx.gas) * 2n : 0n;
|
|
185
|
+
const gasLimit = apiGas > RELAY_GAS_CAP ? RELAY_GAS_CAP : apiGas > floor ? apiGas : floor;
|
|
186
|
+
const relayer = body.fees?.relayer;
|
|
187
|
+
const usd = typeof relayer?.amountUsd === "string" && /^\d{1,12}(?:\.\d{1,18})?$/.test(relayer.amountUsd) ? parseFloat(relayer.amountUsd) : 0;
|
|
188
|
+
const feeToken = relayer?.currency?.address;
|
|
189
|
+
const fees = typeof relayer?.amount === "string" && /^[1-9]\d{0,77}$/.test(relayer.amount) && typeof feeToken === "string" && /^0x[0-9a-fA-F]{40}$/.test(feeToken) ? [{ type: "protocol", amount: relayer.amount, token: feeToken.toLowerCase(), included: true, description: "Relay fee" }] : [];
|
|
190
|
+
const eta = body.details?.timeEstimate;
|
|
191
|
+
const etaSeconds = typeof eta === "number" && Number.isFinite(eta) && eta > 0 ? Math.min(Math.ceil(eta), 86400) : 60;
|
|
192
|
+
const intentId = `${INTENT_PREFIX}${step.requestId}`;
|
|
193
|
+
if (!placeholder) remember(issued, intentId, request);
|
|
194
|
+
return {
|
|
195
|
+
provider: "relay",
|
|
196
|
+
intentId,
|
|
197
|
+
depositAddress: "",
|
|
198
|
+
depositMemo: null,
|
|
199
|
+
txRequest: {
|
|
200
|
+
to: v.deposit.to,
|
|
201
|
+
data: v.deposit.data,
|
|
202
|
+
value: v.deposit.value,
|
|
203
|
+
chainId: v.deposit.chainId,
|
|
204
|
+
gasLimit: gasLimit.toString(10),
|
|
205
|
+
...v.deposit.approvalAddress ? { approvalAddress: v.deposit.approvalAddress } : {}
|
|
206
|
+
},
|
|
207
|
+
sourceAmount: request.amount.toString(10),
|
|
208
|
+
destAmount: v.expectedAmount.toString(10),
|
|
209
|
+
minDestAmount: v.minimumAmount.toString(10),
|
|
210
|
+
feeUsd: usd,
|
|
211
|
+
fees,
|
|
212
|
+
etaSeconds,
|
|
213
|
+
reliability: 0.97,
|
|
214
|
+
validUntilMs: Date.now() + quoteTtlMs,
|
|
215
|
+
providerData: {
|
|
216
|
+
requestId: step.requestId,
|
|
217
|
+
orderId: v.id,
|
|
218
|
+
hubType: "onchain",
|
|
219
|
+
// The order as received, re-read by the same parser before a build and before a signature.
|
|
220
|
+
orderData: JSON.stringify(proto.orderData),
|
|
221
|
+
orderSignature: String(proto.orderSignature).toLowerCase(),
|
|
222
|
+
paymentDetails: JSON.stringify(proto.paymentDetails),
|
|
223
|
+
sourceChain: request.sourceChain,
|
|
224
|
+
destChain: request.destChain,
|
|
225
|
+
sourceToken: request.sourceToken.toLowerCase(),
|
|
226
|
+
destToken: request.destToken.toLowerCase(),
|
|
227
|
+
amount: request.amount.toString(10),
|
|
228
|
+
depositor: request.depositor.toLowerCase(),
|
|
229
|
+
recipient: request.recipient.toLowerCase(),
|
|
230
|
+
...request.minAmountOut !== void 0 ? { minAmountOut: request.minAmountOut.toString(10) } : {},
|
|
231
|
+
...request.slippageBps !== void 0 ? { slippageBps: String(request.slippageBps) } : {},
|
|
232
|
+
...placeholder ? { placeholder: "1" } : {}
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
} catch (err) {
|
|
236
|
+
if (err instanceof RelayRefusal) return refuse(err.message);
|
|
237
|
+
return refuse(`relay: unreadable quote \u2014 ${clip(err instanceof Error ? err.message : String(err))}`);
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
/** The quote's own transaction — after the order it carries has been verified once more. */
|
|
241
|
+
async buildDeposit(quote) {
|
|
242
|
+
const tx = quote.txRequest;
|
|
243
|
+
if (!tx || !quote.intentId.startsWith(INTENT_PREFIX)) throw new Error("swap2: Relay quote has no transaction request");
|
|
244
|
+
if (quote.providerData?.placeholder === "1") throw new RelayRefusal("request-invalid", "a quote priced without the real addresses is never built \u2014 quote again with them");
|
|
245
|
+
const request = requestOf(quote);
|
|
246
|
+
const v = checkRelayQuote(request, quote);
|
|
247
|
+
return {
|
|
248
|
+
chain: request.sourceChain,
|
|
249
|
+
to: v.deposit.to,
|
|
250
|
+
value: v.deposit.value,
|
|
251
|
+
data: v.deposit.data,
|
|
252
|
+
chainId: v.deposit.chainId,
|
|
253
|
+
...tx.gasLimit ? { gasLimit: tx.gasLimit } : {},
|
|
254
|
+
...v.deposit.approvalAddress ? { approvalAddress: v.deposit.approvalAddress } : {}
|
|
255
|
+
};
|
|
256
|
+
},
|
|
257
|
+
/**
|
|
258
|
+
* Right before signing: the whole verification again, against the request this instance issued the quote for
|
|
259
|
+
* and the exact transaction about to be signed — and each order is cleared for one deposit only.
|
|
260
|
+
*/
|
|
261
|
+
async preflightDeposit(quote, tx) {
|
|
262
|
+
if (quote.providerData?.placeholder === "1") throw new RelayRefusal("request-invalid", "a quote priced without the real addresses is never signed");
|
|
263
|
+
const request = requestOf(quote);
|
|
264
|
+
if (tx.chain !== request.sourceChain) throw new RelayRefusal("tx-chain", `the deposit is for ${tx.chain}, not ${request.sourceChain}`);
|
|
265
|
+
if (tx.serializedTx !== void 0 || tx.memo !== void 0 || tx.typedData !== void 0 || tx.bodyBoc !== void 0) {
|
|
266
|
+
throw new RelayRefusal("quote-shape", "a Relay deposit is one EVM call");
|
|
267
|
+
}
|
|
268
|
+
const v = checkRelayQuote(request, quote, tx);
|
|
269
|
+
const store = config.clearedStore;
|
|
270
|
+
if (store && await store.has(v.id)) throw new RelayRefusal("order-reused", `order ${v.id} was already cleared for a deposit \u2014 quote again`);
|
|
271
|
+
relayClearOrder(v.id, "sign");
|
|
272
|
+
if (store) await store.add(v.id, v.order.output.deadline * 1e3);
|
|
273
|
+
},
|
|
274
|
+
async trackIntent(ref) {
|
|
275
|
+
if (typeof ref.intentId !== "string" || !ref.intentId.startsWith(INTENT_PREFIX)) return { state: "failed" };
|
|
276
|
+
const requestId = ref.intentId.slice(INTENT_PREFIX.length);
|
|
277
|
+
if (!REQUEST_ID.test(requestId)) return { state: "failed" };
|
|
278
|
+
if (!ref.sourceTxHash) return { state: "pending" };
|
|
279
|
+
try {
|
|
280
|
+
const res = await doFetch(`${base}/intents/status/v3?requestId=${requestId}`, { headers: headers(false), signal: timeoutSignal(STATUS_TIMEOUT_MS) });
|
|
281
|
+
if (!res.ok) return { state: "pending" };
|
|
282
|
+
const s = await readJson(res);
|
|
283
|
+
const status = typeof s?.status === "string" ? s.status.toLowerCase() : "";
|
|
284
|
+
const state = Object.prototype.hasOwnProperty.call(RELAY_STATUS_MAP, status) ? RELAY_STATUS_MAP[status] : "pending";
|
|
285
|
+
const seen = status !== "waiting" && status !== "unknown" && status !== "";
|
|
286
|
+
if (state === "completed") {
|
|
287
|
+
const hashes = Array.isArray(s?.txHashes) ? s.txHashes.filter((h) => typeof h === "string" && /^0x[0-9a-fA-F]{64}$/.test(h)) : [];
|
|
288
|
+
const dest = hashes[hashes.length - 1] ?? ref.destTxHash ?? void 0;
|
|
289
|
+
return { state, depositReceived: true, ...dest ? { destTxHash: dest } : {} };
|
|
290
|
+
}
|
|
291
|
+
if (status === "failure") {
|
|
292
|
+
const why = typeof s?.refundFailReason === "string" ? s.refundFailReason.trim() : "";
|
|
293
|
+
return { state: why !== "" && why.toUpperCase() !== "N/A" ? "failed" : "refund-pending", depositReceived: true };
|
|
294
|
+
}
|
|
295
|
+
return { state, ...seen ? { depositReceived: true } : {} };
|
|
296
|
+
} catch {
|
|
297
|
+
return { state: "pending" };
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export {
|
|
304
|
+
RELAY_STATUS_MAP,
|
|
305
|
+
relayProvider
|
|
306
|
+
};
|
|
307
|
+
//# sourceMappingURL=chunk-CCMNAZZB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/provider.ts"],"sourcesContent":["import {anySignal, redactUrls, timeoutSignal} from \"@anywalletkit/protocol-swap2-core/util\";\nimport type {Asset, CrossChainProvider, IntentRef, IntentState, IntentStatus, Quote, QuoteParams, UnsignedTx} from \"@anywalletkit/protocol-swap2-core/types\";\nimport {describeRelayActivity} from \"./activity.js\";\nimport {RELAY_API, relay as relayCfg, relayChain} from \"./config.js\";\nimport {RelayRefusal} from \"./order.js\";\nimport {RELAY_DEFAULT_SLIPPAGE_BPS, RELAY_GAS_CAP as GAS_CAP, RELAY_GAS_FLOOR_ERC20 as GAS_FLOOR_ERC20, RELAY_GAS_FLOOR_NATIVE as GAS_FLOOR_NATIVE, checkRelayQuote, relayClearOrder, relayRequestOf, verifyRelayOrder, type RelayRequest} from \"./verify.js\";\n\n/**\n * Relay (relay.link) — a solver network. ONE source transaction: a deposit into the chain's RelayDepository that names\n * an order by its hash; Relay's solver then pays the recipient on the destination chain, or the deposit is refunded.\n *\n * - Quote = `POST /quote/v2` with `includeProtocolData: true`, which returns the order itself next to the deposit.\n * The answer is only an input to `verify.ts`: the order is parsed, hashed and attributed on the device, compared\n * with the request, and the deposit this module builds from its own pins must be byte-for-byte the one offered.\n * What a quote carries afterwards is that own-built call; the amounts it shows are the order's (`expectedAmount`\n * as the estimate, `minimumAmount` as the enforced minimum).\n * - The API's `approve` step is never used: an ERC-20 input sets `approvalAddress` to the pinned depository and the\n * engine approves exactly the input amount.\n * - `baseUrl` may be the app's own proxy that adds the API key. It cannot get a deposit signed for another\n * recipient, chain, token, minimum or refund address than the request's. It CAN make the quote worse: the solver\n * signs whatever request reaches Relay, so a proxy that adds an app fee or a gas top-up gets a genuine order with\n * a lower expected amount. The response's own account of such extras is refused (`app-fee`, `gas-topup`), but a\n * proxy can strip that too — the amounts shown are always the order's, and what bounds the price is the caller's\n * `minAmountOut` or the other quotes of the router, not this module.\n * - Routes Relay serves by first swapping on the source chain call a router, not the depository, and are refused\n * by name (`tx-target`); so are non-EVM chains and any chain without a pin.\n * - Status: `GET /intents/status/v3?requestId=` — display only, nothing is signed on its word.\n */\n\nconst EVM_PLACEHOLDER = \"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045\";\nconst DEFAULT_QUOTE_TTL_MS = 60_000;\nconst QUOTE_TIMEOUT_MS = 20_000;\nconst STATUS_TIMEOUT_MS = 12_000;\nconst INTENT_PREFIX = \"relay:\";\nconst REQUEST_ID = /^0x[0-9a-f]{64}$/;\nconst MAX_BODY = 512 * 1024;\nconst MAX_REMEMBERED = 256;\n\nexport interface RelayProviderConfig {\n enabled?: boolean;\n /**\n * Relay's API (default https://api.relay.link) or the app's own proxy in front of it. Untrusted either way:\n * every answer is verified on the device.\n */\n baseUrl?: string;\n /** Sent as `x-api-key` when set. Prefer a proxy that adds it — a key shipped in an app is public. */\n apiKey?: string;\n /** Local lifetime of a quote (default 60 s, at most 5 min). The order itself is refused once older than 10 min. */\n quoteTtlMs?: number;\n /** Injectable for tests and for runtimes that bring their own. */\n fetchImpl?: typeof fetch;\n /**\n * Where cleared order ids are also kept, so that \"one deposit per order\" survives an app restart (the built-in\n * record lives in memory). `has` is asked and `add` awaited right before a signature; either throwing refuses.\n */\n clearedStore?: RelayClearedStore;\n}\n\n/** A durable record of order ids a deposit was cleared for. `expiresAtMs` is when an entry may be dropped. */\nexport interface RelayClearedStore {\n has(orderId: string): boolean | Promise<boolean>;\n add(orderId: string, expiresAtMs: number): void | Promise<void>;\n}\n\ninterface RelayStep {id?: unknown; requestId?: unknown; items?: unknown}\ninterface RelayQuoteBody {\n steps?: unknown;\n fees?: {relayer?: {currency?: {address?: unknown}; amount?: unknown; amountUsd?: unknown}; app?: {amount?: unknown}};\n details?: {timeEstimate?: unknown; currencyGasTopup?: {amount?: unknown}};\n protocol?: {v2?: unknown};\n message?: unknown;\n errorCode?: unknown;\n}\n\n/** Relay's request states → swap2 states. `failure` is read together with `refundFailReason` (see `trackIntent`). */\nexport const RELAY_STATUS_MAP: Readonly<Record<string, IntentState>> = Object.freeze({\n waiting: \"pending\", depositing: \"pending\", pending: \"pending\", submitted: \"pending\", delayed: \"pending\", unknown: \"pending\",\n success: \"completed\", refund: \"refunded\", refunded: \"refunded\", failure: \"refund-pending\",\n});\n\nfunction clip(text: string, max = 240): string {\n const t = redactUrls(text).replace(/\\s+/g, \" \").trim();\n return t.length > max ? `${t.slice(0, max)}…` : t;\n}\n\n/** The single deposit step of a quote response; an `approve` step is ignored, anything else refuses the quote. */\nfunction depositStep(body: RelayQuoteBody): {requestId: string; tx: {to?: unknown; data?: unknown; value?: unknown; chainId?: unknown; gas?: unknown}} {\n const steps = body.steps;\n if (!Array.isArray(steps) || steps.length === 0 || steps.length > 8) throw new RelayRefusal(\"quote-steps\", \"the quote has no steps\");\n let found: RelayStep | null = null;\n for (const s of steps as RelayStep[]) {\n if (s === null || typeof s !== \"object\") throw new RelayRefusal(\"quote-steps\", \"the quote has a malformed step\");\n if (s.id === \"approve\") continue; // never used: the approval is built here, for the exact amount, to the pinned depository\n if (s.id !== \"deposit\") throw new RelayRefusal(\"quote-steps\", `the quote needs a \"${clip(String(s.id), 40)}\" step, only a single deposit is signed`);\n if (found) throw new RelayRefusal(\"quote-steps\", \"the quote has more than one deposit step\");\n found = s;\n }\n if (!found) throw new RelayRefusal(\"quote-steps\", \"the quote has no deposit step\");\n const items = found.items;\n if (!Array.isArray(items) || items.length !== 1) throw new RelayRefusal(\"quote-steps\", \"the deposit step is not a single transaction\");\n const data = (items[0] as {data?: unknown} | null)?.data;\n if (data === null || typeof data !== \"object\") throw new RelayRefusal(\"quote-steps\", \"the deposit step has no transaction\");\n const requestId = typeof found.requestId === \"string\" ? found.requestId.toLowerCase() : \"\";\n if (!REQUEST_ID.test(requestId)) throw new RelayRefusal(\"quote-steps\", \"the quote has no request id to track the deposit by\");\n return {requestId, tx: data as never};\n}\n\nexport function relayProvider(config: RelayProviderConfig = {}): CrossChainProvider {\n config = Object.freeze({...config});\n const base = (config.baseUrl ?? RELAY_API).replace(/\\/+$/, \"\");\n if (!/^https?:\\/\\//.test(base)) throw new Error(\"relay: baseUrl must use http or https\");\n const quoteTtlMs = config.quoteTtlMs ?? DEFAULT_QUOTE_TTL_MS;\n if (!Number.isInteger(quoteTtlMs) || quoteTtlMs <= 0 || quoteTtlMs > 300_000) throw new Error(\"relay: quoteTtlMs must be an integer between 1 and 300000\");\n if (config.apiKey !== undefined && (typeof config.apiKey !== \"string\" || !/^[\\x21-\\x7e]{1,256}$/.test(config.apiKey))) throw new Error(\"relay: apiKey must be a printable string\");\n const doFetch: typeof fetch = (input, init) => (config.fetchImpl ?? fetch)(input, init);\n const headers = (json: boolean): Record<string, string> => ({\n accept: \"application/json\",\n ...(json ? {\"content-type\": \"application/json\"} : {}),\n ...(config.apiKey ? {\"x-api-key\": config.apiKey} : {}),\n });\n\n // The request each live quote answered, kept on this side: a deposit is checked against what was asked here, not\n // against what the quote object says was asked.\n const issued = new Map<string, RelayRequest>();\n const remember = <K, V>(m: Map<K, V>, k: K, v: V): void => {\n m.delete(k);\n m.set(k, v);\n if (m.size > MAX_REMEMBERED) m.delete(m.keys().next().value as K);\n };\n\n /** The request a quote is checked against before a build or a signature. */\n function requestOf(quote: Quote): RelayRequest {\n const pd = quote.providerData ?? {};\n const sealed: RelayRequest = {\n sourceChain: pd.sourceChain ?? \"\", destChain: pd.destChain ?? \"\", sourceToken: pd.sourceToken ?? \"\", destToken: pd.destToken ?? \"\",\n amount: /^[1-9]\\d{0,77}$/.test(pd.amount ?? \"\") ? BigInt(pd.amount!) : 0n,\n depositor: pd.depositor ?? \"\", recipient: pd.recipient ?? \"\",\n ...(/^\\d{1,78}$/.test(pd.minAmountOut ?? \"\") ? {minAmountOut: BigInt(pd.minAmountOut!)} : {}),\n ...(/^\\d{1,5}$/.test(pd.slippageBps ?? \"\") ? {slippageBps: Number(pd.slippageBps)} : {}),\n };\n // The pricing placeholder is never a party to a deposit, whatever flags the quote object carries.\n if (sealed.depositor.toLowerCase() === EVM_PLACEHOLDER.toLowerCase() || sealed.recipient.toLowerCase() === EVM_PLACEHOLDER.toLowerCase()) {\n throw new RelayRefusal(\"request-invalid\", \"a quote priced without the real addresses is never built or signed — quote again with them\");\n }\n const mine = issued.get(quote.intentId);\n if (!mine) return sealed;\n const same = mine.sourceChain === sealed.sourceChain && mine.destChain === sealed.destChain && mine.amount === sealed.amount\n && mine.sourceToken.toLowerCase() === sealed.sourceToken.toLowerCase() && mine.destToken.toLowerCase() === sealed.destToken.toLowerCase()\n && mine.depositor.toLowerCase() === sealed.depositor.toLowerCase() && mine.recipient.toLowerCase() === sealed.recipient.toLowerCase();\n if (!same) throw new RelayRefusal(\"request-invalid\", \"the quote no longer says what was asked when it was issued — quote again\");\n return mine;\n }\n\n async function readJson(res: Response): Promise<unknown> {\n const text = await res.text();\n if (text.length > MAX_BODY) throw new Error(\"relay: response too large\");\n return JSON.parse(text) as unknown;\n }\n\n return {\n name: \"relay\",\n describeActivity: describeRelayActivity,\n enabled: () => config.enabled ?? true,\n supportsChain: (chain: string) => relayCfg.supportsChain(chain),\n supportsChainPair: (from: string, to: string) => relayCfg.supports(from, to),\n supportsRoute: (from: Asset, to: Asset) => relayCfg.supports(from.chain, to.chain),\n\n async getQuote(params: QuoteParams, signal?: AbortSignal): Promise<Quote | null> {\n const refuse = (reason: string) => { params.onRefusal?.(reason); return null; };\n const dry = params.dry !== false;\n // Only a quote priced with the placeholder is unbuildable; one asked with real addresses is a real order.\n const placeholder = dry && (!params.destAddress || !params.refundAddress);\n let request: RelayRequest;\n try {\n // The placeholder prices a dry quote; a live one without addresses is refused.\n request = relayRequestOf(params, dry ? {placeholder: EVM_PLACEHOLDER} : {});\n } catch (err) {\n if (err instanceof RelayRefusal) return refuse(err.message);\n throw err;\n }\n const src = relayChain(request.sourceChain)!;\n const dst = relayChain(request.destChain)!;\n let body: RelayQuoteBody;\n try {\n const res = await doFetch(`${base}/quote/v2`, {\n method: \"POST\",\n headers: headers(true),\n body: JSON.stringify({\n user: request.depositor,\n recipient: request.recipient,\n refundTo: request.depositor,\n originChainId: src.chainId,\n destinationChainId: dst.chainId,\n originCurrency: request.sourceToken.toLowerCase(),\n destinationCurrency: request.destToken.toLowerCase(),\n amount: request.amount.toString(10),\n tradeType: \"EXACT_INPUT\",\n includeProtocolData: true,\n // Always named: Relay's \"auto\" would leave the distance between expected and minimum to the answering side.\n slippageTolerance: String(request.slippageBps ?? RELAY_DEFAULT_SLIPPAGE_BPS),\n }),\n signal: signal ? anySignal([signal, timeoutSignal(QUOTE_TIMEOUT_MS)]) : timeoutSignal(QUOTE_TIMEOUT_MS),\n });\n let parsed: unknown;\n try { parsed = await readJson(res); } catch { parsed = null; }\n if (!res.ok) {\n const e = (parsed ?? {}) as RelayQuoteBody;\n const why = typeof e.message === \"string\" ? clip(e.message) : `HTTP ${res.status}`;\n return refuse(`relay: no quote — ${typeof e.errorCode === \"string\" ? `${clip(e.errorCode, 60)}: ` : \"\"}${why}`);\n }\n if (parsed === null || typeof parsed !== \"object\") return refuse(\"relay: the quote response is not JSON\");\n body = parsed as RelayQuoteBody;\n } catch (err) {\n return refuse(`relay: quote request failed — ${clip(err instanceof Error ? err.message : String(err))}`);\n }\n\n try {\n const step = depositStep(body);\n const proto = (body.protocol?.v2 ?? null) as Record<string, unknown> | null;\n const v = verifyRelayOrder(request, proto, step.tx);\n // Extras this module never asks for. Each lowers the output inside a genuine order; the response's own account\n // of them is only a hint (an answering side that adds one can also hide it), so this refuses the honest case.\n const extra = (x: unknown): boolean => x !== undefined && x !== null && x !== \"0\" && x !== 0;\n if (extra(body.fees?.app?.amount)) throw new RelayRefusal(\"app-fee\", \"the quote charges an app fee this module did not ask for\");\n if (extra(body.details?.currencyGasTopup?.amount)) throw new RelayRefusal(\"gas-topup\", \"the quote converts part of the output into a gas top-up this module did not ask for\");\n const native = v.deposit.approvalAddress === undefined;\n const floor = native ? GAS_FLOOR_NATIVE : GAS_FLOOR_ERC20;\n const apiGas = typeof step.tx.gas === \"string\" && /^[1-9]\\d{0,9}$/.test(step.tx.gas) ? BigInt(step.tx.gas) * 2n : 0n;\n const gasLimit = apiGas > GAS_CAP ? GAS_CAP : apiGas > floor ? apiGas : floor;\n\n // Fees are Relay's own account of the quote: shown, never used in a check. They are already inside the output.\n const relayer = body.fees?.relayer;\n const usd = typeof relayer?.amountUsd === \"string\" && /^\\d{1,12}(?:\\.\\d{1,18})?$/.test(relayer.amountUsd) ? parseFloat(relayer.amountUsd) : 0;\n const feeToken = relayer?.currency?.address;\n const fees = typeof relayer?.amount === \"string\" && /^[1-9]\\d{0,77}$/.test(relayer.amount) && typeof feeToken === \"string\" && /^0x[0-9a-fA-F]{40}$/.test(feeToken)\n ? [{type: \"protocol\" as const, amount: relayer.amount, token: feeToken.toLowerCase(), included: true, description: \"Relay fee\"}]\n : [];\n const eta = body.details?.timeEstimate;\n const etaSeconds = typeof eta === \"number\" && Number.isFinite(eta) && eta > 0 ? Math.min(Math.ceil(eta), 86_400) : 60;\n\n const intentId = `${INTENT_PREFIX}${step.requestId}`;\n if (!placeholder) remember(issued, intentId, request);\n return {\n provider: \"relay\",\n intentId,\n depositAddress: \"\",\n depositMemo: null,\n txRequest: {\n to: v.deposit.to,\n data: v.deposit.data,\n value: v.deposit.value,\n chainId: v.deposit.chainId,\n gasLimit: gasLimit.toString(10),\n ...(v.deposit.approvalAddress ? {approvalAddress: v.deposit.approvalAddress} : {}),\n },\n sourceAmount: request.amount.toString(10),\n destAmount: v.expectedAmount.toString(10),\n minDestAmount: v.minimumAmount.toString(10),\n feeUsd: usd,\n fees,\n etaSeconds,\n reliability: 0.97,\n validUntilMs: Date.now() + quoteTtlMs,\n providerData: {\n requestId: step.requestId,\n orderId: v.id,\n hubType: \"onchain\",\n // The order as received, re-read by the same parser before a build and before a signature.\n orderData: JSON.stringify(proto!.orderData),\n orderSignature: String(proto!.orderSignature).toLowerCase(),\n paymentDetails: JSON.stringify(proto!.paymentDetails),\n sourceChain: request.sourceChain,\n destChain: request.destChain,\n sourceToken: request.sourceToken.toLowerCase(),\n destToken: request.destToken.toLowerCase(),\n amount: request.amount.toString(10),\n depositor: request.depositor.toLowerCase(),\n recipient: request.recipient.toLowerCase(),\n ...(request.minAmountOut !== undefined ? {minAmountOut: request.minAmountOut.toString(10)} : {}),\n ...(request.slippageBps !== undefined ? {slippageBps: String(request.slippageBps)} : {}),\n ...(placeholder ? {placeholder: \"1\"} : {}),\n },\n };\n } catch (err) {\n if (err instanceof RelayRefusal) return refuse(err.message);\n return refuse(`relay: unreadable quote — ${clip(err instanceof Error ? err.message : String(err))}`);\n }\n },\n\n /** The quote's own transaction — after the order it carries has been verified once more. */\n async buildDeposit(quote: Quote): Promise<UnsignedTx> {\n const tx = quote.txRequest;\n if (!tx || !quote.intentId.startsWith(INTENT_PREFIX)) throw new Error(\"swap2: Relay quote has no transaction request\");\n if (quote.providerData?.placeholder === \"1\") throw new RelayRefusal(\"request-invalid\", \"a quote priced without the real addresses is never built — quote again with them\");\n const request = requestOf(quote);\n const v = checkRelayQuote(request, quote);\n return {\n chain: request.sourceChain,\n to: v.deposit.to,\n value: v.deposit.value,\n data: v.deposit.data,\n chainId: v.deposit.chainId,\n ...(tx.gasLimit ? {gasLimit: tx.gasLimit} : {}),\n ...(v.deposit.approvalAddress ? {approvalAddress: v.deposit.approvalAddress} : {}),\n };\n },\n\n /**\n * Right before signing: the whole verification again, against the request this instance issued the quote for\n * and the exact transaction about to be signed — and each order is cleared for one deposit only.\n */\n async preflightDeposit(quote: Quote, tx: UnsignedTx): Promise<void> {\n if (quote.providerData?.placeholder === \"1\") throw new RelayRefusal(\"request-invalid\", \"a quote priced without the real addresses is never signed\");\n const request = requestOf(quote);\n if (tx.chain !== request.sourceChain) throw new RelayRefusal(\"tx-chain\", `the deposit is for ${tx.chain}, not ${request.sourceChain}`);\n if (tx.serializedTx !== undefined || tx.memo !== undefined || tx.typedData !== undefined || tx.bodyBoc !== undefined) {\n throw new RelayRefusal(\"quote-shape\", \"a Relay deposit is one EVM call\");\n }\n const v = checkRelayQuote(request, quote, tx);\n const store = config.clearedStore;\n if (store && await store.has(v.id)) throw new RelayRefusal(\"order-reused\", `order ${v.id} was already cleared for a deposit — quote again`);\n relayClearOrder(v.id, \"sign\");\n // Kept until the order's own deadline: a deposit for it is never signed twice, restart or not.\n if (store) await store.add(v.id, v.order.output.deadline * 1000);\n },\n\n async trackIntent(ref: IntentRef): Promise<IntentStatus> {\n if (typeof ref.intentId !== \"string\" || !ref.intentId.startsWith(INTENT_PREFIX)) return {state: \"failed\"};\n const requestId = ref.intentId.slice(INTENT_PREFIX.length);\n if (!REQUEST_ID.test(requestId)) return {state: \"failed\"};\n // Nothing was sent yet: Relay answers \"waiting\" for a request it has seen no deposit for.\n if (!ref.sourceTxHash) return {state: \"pending\"};\n try {\n const res = await doFetch(`${base}/intents/status/v3?requestId=${requestId}`, {headers: headers(false), signal: timeoutSignal(STATUS_TIMEOUT_MS)});\n if (!res.ok) return {state: \"pending\"};\n const s = (await readJson(res)) as {status?: unknown; txHashes?: unknown; refundFailReason?: unknown} | null;\n const status = typeof s?.status === \"string\" ? s.status.toLowerCase() : \"\";\n const state = Object.prototype.hasOwnProperty.call(RELAY_STATUS_MAP, status) ? RELAY_STATUS_MAP[status]! : \"pending\";\n const seen = status !== \"waiting\" && status !== \"unknown\" && status !== \"\";\n if (state === \"completed\") {\n const hashes = Array.isArray(s?.txHashes) ? s.txHashes.filter((h): h is string => typeof h === \"string\" && /^0x[0-9a-fA-F]{64}$/.test(h)) : [];\n const dest = hashes[hashes.length - 1] ?? ref.destTxHash ?? undefined;\n return {state, depositReceived: true, ...(dest ? {destTxHash: dest} : {})};\n }\n if (status === \"failure\") {\n // A failed fill is refunded by Relay on its own. Only when the refund itself failed is there nothing\n // more coming without Relay's support.\n const why = typeof s?.refundFailReason === \"string\" ? s.refundFailReason.trim() : \"\";\n return {state: why !== \"\" && why.toUpperCase() !== \"N/A\" ? \"failed\" : \"refund-pending\", depositReceived: true};\n }\n return {state, ...(seen ? {depositReceived: true} : {})};\n } catch {\n return {state: \"pending\"};\n }\n },\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// src/config.ts
|
|
2
|
+
var DEPOSITORY = "0x4cd00e387622c35bddb9b4c962c136462338bc31";
|
|
3
|
+
var DEPOSITORY_B = "0x59916da825d2d2ec1bf878d71c88826f6633ecca";
|
|
4
|
+
var c = (chainId, slug, name, depository = DEPOSITORY) => Object.freeze({ caip2: `eip155:${chainId}`, chainId, slug, name, depository });
|
|
5
|
+
var RELAY_CHAINS = Object.freeze(Object.assign(/* @__PURE__ */ Object.create(null), Object.fromEntries([
|
|
6
|
+
c(1, "ethereum", "Ethereum"),
|
|
7
|
+
c(10, "optimism", "OP Mainnet"),
|
|
8
|
+
c(56, "bnb", "BNB Chain"),
|
|
9
|
+
c(100, "gnosis", "Gnosis"),
|
|
10
|
+
c(130, "unichain", "Unichain"),
|
|
11
|
+
c(137, "polygon", "Polygon"),
|
|
12
|
+
c(143, "monad", "Monad"),
|
|
13
|
+
c(146, "sonic", "Sonic"),
|
|
14
|
+
c(196, "xlayer", "X Layer"),
|
|
15
|
+
c(324, "zksync", "zkSync Era"),
|
|
16
|
+
c(480, "worldchain", "World Chain"),
|
|
17
|
+
c(999, "hyperevm", "HyperEVM"),
|
|
18
|
+
c(2818, "morph", "Morph"),
|
|
19
|
+
c(4326, "megaeth", "MegaETH"),
|
|
20
|
+
c(4663, "robinhood", "Robinhood Chain"),
|
|
21
|
+
c(5e3, "mantle", "Mantle", DEPOSITORY_B),
|
|
22
|
+
c(5042, "arc", "Arc"),
|
|
23
|
+
c(8453, "base", "Base"),
|
|
24
|
+
c(9745, "plasma", "Plasma"),
|
|
25
|
+
c(42161, "arbitrum", "Arbitrum"),
|
|
26
|
+
c(42220, "celo", "Celo"),
|
|
27
|
+
c(43114, "avalanche", "Avalanche"),
|
|
28
|
+
c(57073, "ink", "Ink"),
|
|
29
|
+
c(59144, "linea", "Linea", DEPOSITORY_B),
|
|
30
|
+
c(80094, "berachain", "Berachain"),
|
|
31
|
+
c(98866, "plume", "Plume"),
|
|
32
|
+
c(99901, "elysium", "Elysium"),
|
|
33
|
+
c(534352, "scroll", "Scroll"),
|
|
34
|
+
c(747474, "katana", "Katana")
|
|
35
|
+
].map((x) => [x.caip2, x]))));
|
|
36
|
+
function relayChain(caip2) {
|
|
37
|
+
return typeof caip2 === "string" && Object.prototype.hasOwnProperty.call(RELAY_CHAINS, caip2) ? RELAY_CHAINS[caip2] : void 0;
|
|
38
|
+
}
|
|
39
|
+
var RELAY_SOLVERS = Object.freeze([
|
|
40
|
+
Object.freeze({ chainId: "base", address: "0xf70da97812cb96acdf810712aa562db8dfa3dbef" })
|
|
41
|
+
]);
|
|
42
|
+
var RELAY_ALLOCATOR = "0x63c1d3e9c646184529c5694630a01c00df171b56";
|
|
43
|
+
var RELAY_OWNER = "0xf61a305199fa1135d76ffab3752d42f55cbd775a";
|
|
44
|
+
var RELAY_API = "https://api.relay.link";
|
|
45
|
+
var RELAY_NATIVE = "0x0000000000000000000000000000000000000000";
|
|
46
|
+
var RELAY_DEPOSIT_NATIVE = "0x49290c1c";
|
|
47
|
+
var RELAY_DEPOSIT_ERC20 = "0xe8017952";
|
|
48
|
+
var RELAY_DEPOSIT_ERC20_ALLOWANCE = "0x5a1ee3ac";
|
|
49
|
+
var RELAY_ORDER_VERSION = "v1";
|
|
50
|
+
var RELAY_ORDER_LIFETIME_S = 604800;
|
|
51
|
+
var RELAY_MAX_ORDER_AGE_S = 600;
|
|
52
|
+
var RELAY_CLOCK_SKEW_S = 300;
|
|
53
|
+
var relay = {
|
|
54
|
+
supportsChain(chain) {
|
|
55
|
+
return relayChain(chain) !== void 0;
|
|
56
|
+
},
|
|
57
|
+
/** Two different pinned EVM chains. */
|
|
58
|
+
supports(from, to) {
|
|
59
|
+
return from !== to && relayChain(from) !== void 0 && relayChain(to) !== void 0;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export {
|
|
64
|
+
RELAY_CHAINS,
|
|
65
|
+
relayChain,
|
|
66
|
+
RELAY_SOLVERS,
|
|
67
|
+
RELAY_ALLOCATOR,
|
|
68
|
+
RELAY_OWNER,
|
|
69
|
+
RELAY_API,
|
|
70
|
+
RELAY_NATIVE,
|
|
71
|
+
RELAY_DEPOSIT_NATIVE,
|
|
72
|
+
RELAY_DEPOSIT_ERC20,
|
|
73
|
+
RELAY_DEPOSIT_ERC20_ALLOWANCE,
|
|
74
|
+
RELAY_ORDER_VERSION,
|
|
75
|
+
RELAY_ORDER_LIFETIME_S,
|
|
76
|
+
RELAY_MAX_ORDER_AGE_S,
|
|
77
|
+
RELAY_CLOCK_SKEW_S,
|
|
78
|
+
relay
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=chunk-JQAN7HB5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/config.ts"],"sourcesContent":["// Relay (relay.link) — the pins this module signs against. Nothing here is read from the API at run time: the API (or\n// an app's own proxy in front of it) is untrusted, and a deposit is signed only for a depository, a chain mapping and\n// a solver signer written in this file.\n//\n// Sources, all read on 2026-11-10:\n// - `GET https://api.relay.link/chains` — per chain: `id`, `protocol.v2.chainId` (the chain's name inside an order,\n// which is NOT always `name`: BNB Chain is \"bnb\" in orders and \"bsc\" as `name`, World Chain \"worldchain\" /\n// \"world-chain\"), `protocol.v2.depository`, `solverAddresses`.\n// - On chain, over the SDK's public RPCs, for every row below: the depository has code, `allocator()` =\n// {@link RELAY_ALLOCATOR}, `owner()` = {@link RELAY_OWNER}, its EIP-712 domain reports the row's chain id, and the\n// bytecode carries the three deposit selectors. The runtime code is the same 8 628 bytes everywhere apart from the\n// immutables (the Mantle / Linea deployment is a second build, 8 777 bytes, at its own address).\n// - The contract: github.com/relayprotocol/relay-depository, packages/ethereum-vm/src/RelayDepository.sol.\n// - The order: github.com/relayprotocol/relay-protocol-sdk, src/order/index.ts (types and hashing), and Relay's own\n// \"input validation\" page (docs.relay.link), which names the solver below and tells integrators to take the\n// depository from `/chains` rather than from a quote.\n//\n// Only chains the SDK ships are listed, plus Elysium (99901), whose catalog entry is added separately. Relay also\n// serves chains the SDK does not carry; the SDK's Flare (14) and Sei (1329) are not on Relay.\n\nexport interface RelayChain {\n caip2: string;\n chainId: number;\n /** The chain's name inside a Relay order (`/chains[].protocol.v2.chainId`). */\n slug: string;\n name: string;\n /** RelayDepository on that chain: the only contract a deposit calls and the only spender an approval names. */\n depository: string;\n}\n\nconst DEPOSITORY = \"0x4cd00e387622c35bddb9b4c962c136462338bc31\";\n/** Mantle and Linea run a second deployment. */\nconst DEPOSITORY_B = \"0x59916da825d2d2ec1bf878d71c88826f6633ecca\";\n\nconst c = (chainId: number, slug: string, name: string, depository: string = DEPOSITORY): RelayChain =>\n Object.freeze({caip2: `eip155:${chainId}`, chainId, slug, name, depository});\n\n/** CAIP-2 → the chain as Relay knows it. A null-prototype map: `RELAY_CHAINS[\"constructor\"]` is undefined. */\nexport const RELAY_CHAINS: Readonly<Record<string, RelayChain>> = Object.freeze(Object.assign(Object.create(null) as Record<string, RelayChain>, Object.fromEntries([\n c(1, \"ethereum\", \"Ethereum\"),\n c(10, \"optimism\", \"OP Mainnet\"),\n c(56, \"bnb\", \"BNB Chain\"),\n c(100, \"gnosis\", \"Gnosis\"),\n c(130, \"unichain\", \"Unichain\"),\n c(137, \"polygon\", \"Polygon\"),\n c(143, \"monad\", \"Monad\"),\n c(146, \"sonic\", \"Sonic\"),\n c(196, \"xlayer\", \"X Layer\"),\n c(324, \"zksync\", \"zkSync Era\"),\n c(480, \"worldchain\", \"World Chain\"),\n c(999, \"hyperevm\", \"HyperEVM\"),\n c(2818, \"morph\", \"Morph\"),\n c(4326, \"megaeth\", \"MegaETH\"),\n c(4663, \"robinhood\", \"Robinhood Chain\"),\n c(5000, \"mantle\", \"Mantle\", DEPOSITORY_B),\n c(5042, \"arc\", \"Arc\"),\n c(8453, \"base\", \"Base\"),\n c(9745, \"plasma\", \"Plasma\"),\n c(42161, \"arbitrum\", \"Arbitrum\"),\n c(42220, \"celo\", \"Celo\"),\n c(43114, \"avalanche\", \"Avalanche\"),\n c(57073, \"ink\", \"Ink\"),\n c(59144, \"linea\", \"Linea\", DEPOSITORY_B),\n c(80094, \"berachain\", \"Berachain\"),\n c(98866, \"plume\", \"Plume\"),\n c(99901, \"elysium\", \"Elysium\"),\n c(534352, \"scroll\", \"Scroll\"),\n c(747474, \"katana\", \"Katana\"),\n].map((x) => [x.caip2, x]))));\n\n/** The chain for a CAIP-2 id, or undefined — own keys only. */\nexport function relayChain(caip2: string): RelayChain | undefined {\n return typeof caip2 === \"string\" && Object.prototype.hasOwnProperty.call(RELAY_CHAINS, caip2) ? RELAY_CHAINS[caip2] : undefined;\n}\n\n/**\n * The solver whose signature makes an order worth depositing for: `order.solver` on `order.solverChainId`, the signer of\n * `orderSignature`. One pair today (every order seen, Relay's validation page, first in `/chains[].solverAddresses`).\n * An order naming any other solver, or this address on another solver chain, is refused.\n */\nexport const RELAY_SOLVERS: readonly {readonly chainId: string; readonly address: string}[] = Object.freeze([\n Object.freeze({chainId: \"base\", address: \"0xf70da97812cb96acdf810712aa562db8dfa3dbef\"}),\n]);\n\n/** `allocator()` of every pinned depository (the key that authorises withdrawals from it) — a watched fact, not used in checks. */\nexport const RELAY_ALLOCATOR = \"0x63c1d3e9c646184529c5694630a01c00df171b56\";\n/** `owner()` of every pinned depository — a watched fact, not used in checks. */\nexport const RELAY_OWNER = \"0xf61a305199fa1135d76ffab3752d42f55cbd775a\";\n\n/** Relay's API. An app may point the provider at its own proxy instead (`baseUrl`); either is untrusted. */\nexport const RELAY_API = \"https://api.relay.link\";\n\n/** The native coin in a Relay order and in the API: twenty zero bytes. */\nexport const RELAY_NATIVE = \"0x0000000000000000000000000000000000000000\";\n\n/** `depositNative(address depositor, bytes32 id)` payable. */\nexport const RELAY_DEPOSIT_NATIVE = \"0x49290c1c\";\n/** `depositErc20(address depositor, address token, uint256 amount, bytes32 id)`. */\nexport const RELAY_DEPOSIT_ERC20 = \"0xe8017952\";\n/**\n * `depositErc20(address depositor, address token, bytes32 id)` — deposits the caller's WHOLE allowance. Never built and\n * always refused: the amount is not in the calldata.\n */\nexport const RELAY_DEPOSIT_ERC20_ALLOWANCE = \"0x5a1ee3ac\";\n\n/** The only order version this module reads. */\nexport const RELAY_ORDER_VERSION = \"v1\";\n\n/**\n * How long Relay gives an order: the output deadline and every refund deadline are the quote time + 7 days (every\n * order seen, 2026-11-02 … 2026-11-10). The verifier holds a deadline to this lifetime, which is also what makes an\n * old order stale: one issued more than {@link RELAY_MAX_ORDER_AGE_S} ago is refused even when everything else fits.\n */\nexport const RELAY_ORDER_LIFETIME_S = 604_800;\n/** An order older than this is refused (the quote itself lives for `quoteTtlMs`, 60 s by default, 5 min at most). */\nexport const RELAY_MAX_ORDER_AGE_S = 600;\n/** Tolerated clock difference between the device and Relay, forwards. */\nexport const RELAY_CLOCK_SKEW_S = 300;\n\nexport const relay = {\n supportsChain(chain: string): boolean {\n return relayChain(chain) !== undefined;\n },\n /** Two different pinned EVM chains. */\n supports(from: string, to: string): boolean {\n return from !== to && relayChain(from) !== undefined && relayChain(to) !== undefined;\n },\n};\n"],"mappings":";AA8BA,IAAM,aAAa;AAEnB,IAAM,eAAe;AAErB,IAAM,IAAI,CAAC,SAAiB,MAAc,MAAc,aAAqB,eAC3E,OAAO,OAAO,EAAC,OAAO,UAAU,OAAO,IAAI,SAAS,MAAM,MAAM,WAAU,CAAC;AAGtE,IAAM,eAAqD,OAAO,OAAO,OAAO,OAAO,uBAAO,OAAO,IAAI,GAAiC,OAAO,YAAY;AAAA,EAClK,EAAE,GAAG,YAAY,UAAU;AAAA,EAC3B,EAAE,IAAI,YAAY,YAAY;AAAA,EAC9B,EAAE,IAAI,OAAO,WAAW;AAAA,EACxB,EAAE,KAAK,UAAU,QAAQ;AAAA,EACzB,EAAE,KAAK,YAAY,UAAU;AAAA,EAC7B,EAAE,KAAK,WAAW,SAAS;AAAA,EAC3B,EAAE,KAAK,SAAS,OAAO;AAAA,EACvB,EAAE,KAAK,SAAS,OAAO;AAAA,EACvB,EAAE,KAAK,UAAU,SAAS;AAAA,EAC1B,EAAE,KAAK,UAAU,YAAY;AAAA,EAC7B,EAAE,KAAK,cAAc,aAAa;AAAA,EAClC,EAAE,KAAK,YAAY,UAAU;AAAA,EAC7B,EAAE,MAAM,SAAS,OAAO;AAAA,EACxB,EAAE,MAAM,WAAW,SAAS;AAAA,EAC5B,EAAE,MAAM,aAAa,iBAAiB;AAAA,EACtC,EAAE,KAAM,UAAU,UAAU,YAAY;AAAA,EACxC,EAAE,MAAM,OAAO,KAAK;AAAA,EACpB,EAAE,MAAM,QAAQ,MAAM;AAAA,EACtB,EAAE,MAAM,UAAU,QAAQ;AAAA,EAC1B,EAAE,OAAO,YAAY,UAAU;AAAA,EAC/B,EAAE,OAAO,QAAQ,MAAM;AAAA,EACvB,EAAE,OAAO,aAAa,WAAW;AAAA,EACjC,EAAE,OAAO,OAAO,KAAK;AAAA,EACrB,EAAE,OAAO,SAAS,SAAS,YAAY;AAAA,EACvC,EAAE,OAAO,aAAa,WAAW;AAAA,EACjC,EAAE,OAAO,SAAS,OAAO;AAAA,EACzB,EAAE,OAAO,WAAW,SAAS;AAAA,EAC7B,EAAE,QAAQ,UAAU,QAAQ;AAAA,EAC5B,EAAE,QAAQ,UAAU,QAAQ;AAC9B,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;AAGrB,SAAS,WAAW,OAAuC;AAChE,SAAO,OAAO,UAAU,YAAY,OAAO,UAAU,eAAe,KAAK,cAAc,KAAK,IAAI,aAAa,KAAK,IAAI;AACxH;AAOO,IAAM,gBAAiF,OAAO,OAAO;AAAA,EAC1G,OAAO,OAAO,EAAC,SAAS,QAAQ,SAAS,6CAA4C,CAAC;AACxF,CAAC;AAGM,IAAM,kBAAkB;AAExB,IAAM,cAAc;AAGpB,IAAM,YAAY;AAGlB,IAAM,eAAe;AAGrB,IAAM,uBAAuB;AAE7B,IAAM,sBAAsB;AAK5B,IAAM,gCAAgC;AAGtC,IAAM,sBAAsB;AAO5B,IAAM,yBAAyB;AAE/B,IAAM,wBAAwB;AAE9B,IAAM,qBAAqB;AAE3B,IAAM,QAAQ;AAAA,EACnB,cAAc,OAAwB;AACpC,WAAO,WAAW,KAAK,MAAM;AAAA,EAC/B;AAAA;AAAA,EAEA,SAAS,MAAc,IAAqB;AAC1C,WAAO,SAAS,MAAM,WAAW,IAAI,MAAM,UAAa,WAAW,EAAE,MAAM;AAAA,EAC7E;AACF;","names":[]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {
|
|
2
|
+
RELAY_DEPOSIT_ERC20,
|
|
3
|
+
RELAY_DEPOSIT_ERC20_ALLOWANCE,
|
|
4
|
+
RELAY_DEPOSIT_NATIVE,
|
|
5
|
+
relayChain
|
|
6
|
+
} from "./chunk-JQAN7HB5.js";
|
|
7
|
+
|
|
8
|
+
// src/activity.ts
|
|
9
|
+
import { chainLabel, describeSwapLike, matchesCall } from "@anywalletkit/protocol-swap2-core/activity";
|
|
10
|
+
var RELAY_MODULE = "@anywalletkit/protocol-swap2-relay";
|
|
11
|
+
function describeRelayActivity(tx, ctx) {
|
|
12
|
+
const chain = relayChain(tx.chain);
|
|
13
|
+
if (!chain) return null;
|
|
14
|
+
if (!matchesCall(tx, [chain.depository], [RELAY_DEPOSIT_NATIVE, RELAY_DEPOSIT_ERC20, RELAY_DEPOSIT_ERC20_ALLOWANCE])) return null;
|
|
15
|
+
return describeSwapLike(tx, ctx, { protocol: RELAY_MODULE, subtitle: `Relay \xB7 ${chainLabel(tx.chain)}`, kind: "bridge", outVerb: "Bridged" });
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export {
|
|
19
|
+
RELAY_MODULE,
|
|
20
|
+
describeRelayActivity
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=chunk-K5F3BEUO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/activity.ts"],"sourcesContent":["/**\n * Activity recognition for Relay on every pinned chain: `depositNative` / `depositErc20` on the chain's\n * RelayDepository is our source leg (\"Bridged ETH\").\n *\n * The destination leg is not claimed. A fill is sent by one of Relay's many relayer keys as an ordinary transfer (or\n * through a router for a destination swap) and names neither the order nor Relay on chain, so there is nothing to\n * recognise it by that a stranger could not imitate; it reads as a plain incoming transfer.\n */\nimport type {ActivityItem, ChainTx, DescribeActivityContext} from \"@anywalletkit/core\";\nimport {chainLabel, describeSwapLike, matchesCall} from \"@anywalletkit/protocol-swap2-core/activity\";\nimport {RELAY_DEPOSIT_ERC20, RELAY_DEPOSIT_ERC20_ALLOWANCE, RELAY_DEPOSIT_NATIVE, relayChain} from \"./config.js\";\n\nexport const RELAY_MODULE = \"@anywalletkit/protocol-swap2-relay\";\n\nexport function describeRelayActivity(tx: ChainTx, ctx: DescribeActivityContext): ActivityItem | null {\n const chain = relayChain(tx.chain);\n if (!chain) return null;\n // All three deposit functions are read here (history is not ours alone); only two are ever built or signed.\n if (!matchesCall(tx, [chain.depository], [RELAY_DEPOSIT_NATIVE, RELAY_DEPOSIT_ERC20, RELAY_DEPOSIT_ERC20_ALLOWANCE])) return null;\n return describeSwapLike(tx, ctx, {protocol: RELAY_MODULE, subtitle: `Relay · ${chainLabel(tx.chain)}`, kind: \"bridge\", outVerb: \"Bridged\"});\n}\n"],"mappings":";;;;;;;;AASA,SAAQ,YAAY,kBAAkB,mBAAkB;AAGjD,IAAM,eAAe;AAErB,SAAS,sBAAsB,IAAa,KAAmD;AACpG,QAAM,QAAQ,WAAW,GAAG,KAAK;AACjC,MAAI,CAAC,MAAO,QAAO;AAEnB,MAAI,CAAC,YAAY,IAAI,CAAC,MAAM,UAAU,GAAG,CAAC,sBAAsB,qBAAqB,6BAA6B,CAAC,EAAG,QAAO;AAC7H,SAAO,iBAAiB,IAAI,KAAK,EAAC,UAAU,cAAc,UAAU,cAAW,WAAW,GAAG,KAAK,CAAC,IAAI,MAAM,UAAU,SAAS,UAAS,CAAC;AAC5I;","names":[]}
|