@relai-fi/x402 0.6.5 → 0.6.6
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 +116 -0
- package/dist/bridge.cjs +109 -0
- package/dist/bridge.cjs.map +1 -0
- package/dist/bridge.d.cts +78 -0
- package/dist/bridge.d.ts +78 -0
- package/dist/bridge.js +80 -0
- package/dist/bridge.js.map +1 -0
- package/dist/client.cjs +131 -1
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +12 -0
- package/dist/client.d.ts +12 -0
- package/dist/client.js +131 -1
- package/dist/client.js.map +1 -1
- package/dist/index.cjs +247 -73
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +247 -73
- package/dist/index.js.map +1 -1
- package/dist/mpp/bridge-client.cjs +23922 -0
- package/dist/mpp/bridge-client.cjs.map +1 -0
- package/dist/mpp/bridge-client.d.cts +58 -0
- package/dist/mpp/bridge-client.d.ts +58 -0
- package/dist/mpp/bridge-client.js +23892 -0
- package/dist/mpp/bridge-client.js.map +1 -0
- package/dist/mpp/bridge-method.cjs +13202 -0
- package/dist/mpp/bridge-method.cjs.map +1 -0
- package/dist/mpp/bridge-method.d.cts +69 -0
- package/dist/mpp/bridge-method.d.ts +69 -0
- package/dist/mpp/bridge-method.js +13181 -0
- package/dist/mpp/bridge-method.js.map +1 -0
- package/dist/mpp/bridge-server.cjs +13887 -0
- package/dist/mpp/bridge-server.cjs.map +1 -0
- package/dist/mpp/bridge-server.d.cts +62 -0
- package/dist/mpp/bridge-server.d.ts +62 -0
- package/dist/mpp/bridge-server.js +13866 -0
- package/dist/mpp/bridge-server.js.map +1 -0
- package/dist/mpp/evm-server.cjs +49 -33
- package/dist/mpp/evm-server.cjs.map +1 -1
- package/dist/mpp/evm-server.js +49 -33
- package/dist/mpp/evm-server.js.map +1 -1
- package/dist/mpp/verify-erc20.cjs +71 -0
- package/dist/mpp/verify-erc20.cjs.map +1 -0
- package/dist/mpp/verify-erc20.d.cts +27 -0
- package/dist/mpp/verify-erc20.d.ts +27 -0
- package/dist/mpp/verify-erc20.js +46 -0
- package/dist/mpp/verify-erc20.js.map +1 -0
- package/dist/mpp/verify-spl.cjs +96 -0
- package/dist/mpp/verify-spl.cjs.map +1 -0
- package/dist/mpp/verify-spl.d.cts +30 -0
- package/dist/mpp/verify-spl.d.ts +30 -0
- package/dist/mpp/verify-spl.js +71 -0
- package/dist/mpp/verify-spl.js.map +1 -0
- package/dist/mpp/with-bridge.cjs +23956 -0
- package/dist/mpp/with-bridge.cjs.map +1 -0
- package/dist/mpp/with-bridge.d.cts +53 -0
- package/dist/mpp/with-bridge.d.ts +53 -0
- package/dist/mpp/with-bridge.js +23926 -0
- package/dist/mpp/with-bridge.js.map +1 -0
- package/dist/react/index.cjs +131 -1
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.js +131 -1
- package/dist/react/index.js.map +1 -1
- package/dist/server.cjs +6 -39
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +6 -39
- package/dist/server.js.map +1 -1
- package/package.json +31 -1
package/dist/index.js
CHANGED
|
@@ -7560,7 +7560,6 @@ var Relai = class {
|
|
|
7560
7560
|
const integritasMode = integritasFlow === "single" ? "single_signature_fee_included" : integritasFlow === "dual" ? "dual_signature_split" : void 0;
|
|
7561
7561
|
const paymentHeader = req.headers["x-payment"] || req.headers["payment-signature"] || req.headers["x-payment-signature"];
|
|
7562
7562
|
const authHeader = req.headers["authorization"] || "";
|
|
7563
|
-
console.log(`[Relai] MPP check: paymentHeader=${!!paymentHeader}, hasMpp=${!!self.mpp}, authHeader=${authHeader?.slice(0, 30)}`);
|
|
7564
7563
|
if (!paymentHeader && self.mpp && /^Payment\s+/i.test(authHeader)) {
|
|
7565
7564
|
try {
|
|
7566
7565
|
const mppAmount = resolvedPrice.toFixed(6);
|
|
@@ -7572,10 +7571,7 @@ var Relai = class {
|
|
|
7572
7571
|
const mppRequest = new Request(mppUrl, { method: req.method, headers: mppHeaders });
|
|
7573
7572
|
const chargeHandler = self.mpp.charge({ amount: mppAmount });
|
|
7574
7573
|
const mppResult = await chargeHandler(mppRequest);
|
|
7575
|
-
console.log(`[Relai] MPP charge result: status=${mppResult.status}, keys=${Object.keys(mppResult)}, hasChallenge=${!!mppResult.challenge}, hasWithReceipt=${!!mppResult.withReceipt}`);
|
|
7576
7574
|
if (mppResult.status === 402 && mppResult.challenge instanceof Response) {
|
|
7577
|
-
const retryAuth = mppResult.challenge.headers.get("www-authenticate");
|
|
7578
|
-
console.log(`[Relai] MPP re-challenged (credential not accepted). New WWW-Auth: ${retryAuth?.slice(0, 60)}`);
|
|
7579
7575
|
}
|
|
7580
7576
|
if (mppResult.status !== 200 && !mppResult.withReceipt && mppResult.status !== 402) {
|
|
7581
7577
|
if (self.plugins.length > 0) {
|
|
@@ -7618,7 +7614,10 @@ var Relai = class {
|
|
|
7618
7614
|
const dummyResponse = new Response(null);
|
|
7619
7615
|
const receiptResponse = mppResult.withReceipt(dummyResponse);
|
|
7620
7616
|
const receiptHeader = receiptResponse.headers.get("payment-receipt");
|
|
7621
|
-
if (receiptHeader)
|
|
7617
|
+
if (receiptHeader) {
|
|
7618
|
+
res.setHeader?.("Payment-Receipt", receiptHeader);
|
|
7619
|
+
res.setHeader?.("Cache-Control", "private");
|
|
7620
|
+
}
|
|
7622
7621
|
}
|
|
7623
7622
|
options.onPaymentSettled?.(req, {
|
|
7624
7623
|
success: true,
|
|
@@ -7835,12 +7834,13 @@ var Relai = class {
|
|
|
7835
7834
|
if (mppResult?.challenge instanceof Response) {
|
|
7836
7835
|
const wwwAuth = mppResult.challenge.headers.get("www-authenticate");
|
|
7837
7836
|
if (wwwAuth) {
|
|
7838
|
-
res.setHeader("WWW-Authenticate", wwwAuth);
|
|
7837
|
+
res.setHeader?.("WWW-Authenticate", wwwAuth);
|
|
7839
7838
|
}
|
|
7840
7839
|
}
|
|
7841
7840
|
} catch {
|
|
7842
7841
|
}
|
|
7843
7842
|
}
|
|
7843
|
+
res.setHeader?.("Cache-Control", "no-store");
|
|
7844
7844
|
return res.status(402).json(paymentRequiredResponse);
|
|
7845
7845
|
}
|
|
7846
7846
|
let paymentProof;
|
|
@@ -7857,39 +7857,6 @@ var Relai = class {
|
|
|
7857
7857
|
});
|
|
7858
7858
|
}
|
|
7859
7859
|
}
|
|
7860
|
-
if (paymentProof.bridged === true && paymentProof.targetTxId) {
|
|
7861
|
-
console.log(`[Relai] Bridged payment accepted: source=${paymentProof.sourceTxId}, target=${paymentProof.targetTxId}`);
|
|
7862
|
-
const paymentInfo2 = {
|
|
7863
|
-
verified: true,
|
|
7864
|
-
transactionId: paymentProof.targetTxId,
|
|
7865
|
-
payer: paymentProof.sourceTxId || "bridge",
|
|
7866
|
-
network,
|
|
7867
|
-
amount: resolvedPrice
|
|
7868
|
-
};
|
|
7869
|
-
req.payment = paymentInfo2;
|
|
7870
|
-
req.x402Payer = paymentProof.sourceTxId || "bridge";
|
|
7871
|
-
req.x402Paid = true;
|
|
7872
|
-
req.x402Transaction = paymentProof.targetTxId;
|
|
7873
|
-
req.x402Network = network;
|
|
7874
|
-
req.x402Bridged = true;
|
|
7875
|
-
req.x402SourceChain = paymentProof.sourceChain;
|
|
7876
|
-
const paymentResponse2 = {
|
|
7877
|
-
x402Version: 2,
|
|
7878
|
-
scheme: "exact",
|
|
7879
|
-
network: caip2,
|
|
7880
|
-
transaction: paymentProof.targetTxId,
|
|
7881
|
-
payer: paymentProof.sourceTxId,
|
|
7882
|
-
amount: amount2,
|
|
7883
|
-
asset,
|
|
7884
|
-
bridged: true
|
|
7885
|
-
};
|
|
7886
|
-
res.setHeader(
|
|
7887
|
-
"PAYMENT-RESPONSE",
|
|
7888
|
-
Buffer.from(JSON.stringify(paymentResponse2)).toString("base64")
|
|
7889
|
-
);
|
|
7890
|
-
options.onPaymentSettled?.(req, { success: true, transaction: paymentProof.targetTxId, payer: paymentProof.sourceTxId });
|
|
7891
|
-
return next();
|
|
7892
|
-
}
|
|
7893
7860
|
let settlePayTo;
|
|
7894
7861
|
if (stripeConfig) {
|
|
7895
7862
|
settlePayTo = paymentProof.payload?.authorization?.to || paymentProof.accepted?.payTo || "";
|
|
@@ -8047,6 +8014,73 @@ import {
|
|
|
8047
8014
|
TOKEN_PROGRAM_ID,
|
|
8048
8015
|
TOKEN_2022_PROGRAM_ID
|
|
8049
8016
|
} from "@solana/spl-token";
|
|
8017
|
+
|
|
8018
|
+
// src/bridge.ts
|
|
8019
|
+
var RELAI_API_BASE = "https://api.relai.fi";
|
|
8020
|
+
var _cacheMap = /* @__PURE__ */ new Map();
|
|
8021
|
+
var CACHE_TTL = 5 * 60 * 1e3;
|
|
8022
|
+
async function getBridgeInfo(baseUrl = RELAI_API_BASE) {
|
|
8023
|
+
const key = baseUrl.replace(/\/$/, "");
|
|
8024
|
+
const now = Date.now();
|
|
8025
|
+
const cached2 = _cacheMap.get(key);
|
|
8026
|
+
if (cached2 && now - cached2.time < CACHE_TTL) return cached2.info;
|
|
8027
|
+
const url2 = `${key}/bridge/info`;
|
|
8028
|
+
const res = await fetch(url2);
|
|
8029
|
+
if (!res.ok) {
|
|
8030
|
+
if (cached2) return cached2.info;
|
|
8031
|
+
throw new Error(`[relai:bridge] Failed to fetch ${url2}: ${res.status}`);
|
|
8032
|
+
}
|
|
8033
|
+
const data = await res.json();
|
|
8034
|
+
const info = {
|
|
8035
|
+
settleEndpoint: data.settleEndpoint,
|
|
8036
|
+
supportedSourceChains: data.supportedSourceChains || [],
|
|
8037
|
+
supportedSourceAssets: data.supportedSourceAssets || [],
|
|
8038
|
+
payTo: data.payTo || {},
|
|
8039
|
+
feePayerSvm: data.feePayerSvm ?? null,
|
|
8040
|
+
feeBps: data.feeBps ?? 100,
|
|
8041
|
+
paymentFacilitator: data.paymentFacilitator || "https://facilitator.x402.fi"
|
|
8042
|
+
};
|
|
8043
|
+
_cacheMap.set(key, { info, time: now });
|
|
8044
|
+
return info;
|
|
8045
|
+
}
|
|
8046
|
+
async function settleBridge(settleEndpoint, body) {
|
|
8047
|
+
const res = await fetch(settleEndpoint, {
|
|
8048
|
+
method: "POST",
|
|
8049
|
+
headers: { "Content-Type": "application/json" },
|
|
8050
|
+
body: JSON.stringify(body)
|
|
8051
|
+
});
|
|
8052
|
+
if (!res.ok) {
|
|
8053
|
+
const err = await res.json().catch(() => ({}));
|
|
8054
|
+
throw new Error(`[relai:bridge] settle failed: ${err.error || res.status}${err.details ? " \u2014 " + err.details : ""}`);
|
|
8055
|
+
}
|
|
8056
|
+
return res.json();
|
|
8057
|
+
}
|
|
8058
|
+
function selectSourceChain(supportedChains, hasEvmWallet, hasSolanaWallet, preferredSourceChainId) {
|
|
8059
|
+
if (preferredSourceChainId && hasEvmWallet) {
|
|
8060
|
+
const preferred = `eip155:${preferredSourceChainId}`;
|
|
8061
|
+
if (supportedChains.includes(preferred)) {
|
|
8062
|
+
return { type: "evm", chain: preferred };
|
|
8063
|
+
}
|
|
8064
|
+
}
|
|
8065
|
+
if (hasSolanaWallet) {
|
|
8066
|
+
const sol = supportedChains.find((c) => c.startsWith("solana:"));
|
|
8067
|
+
if (sol) return { type: "solana", chain: sol };
|
|
8068
|
+
}
|
|
8069
|
+
if (hasEvmWallet) {
|
|
8070
|
+
for (const chain of supportedChains) {
|
|
8071
|
+
if (chain.startsWith("eip155:")) {
|
|
8072
|
+
return { type: "evm", chain };
|
|
8073
|
+
}
|
|
8074
|
+
}
|
|
8075
|
+
}
|
|
8076
|
+
return null;
|
|
8077
|
+
}
|
|
8078
|
+
function computeSourceAmount(targetAmount, feeBps) {
|
|
8079
|
+
const fee = targetAmount * BigInt(feeBps) / 10000n;
|
|
8080
|
+
return targetAmount + fee;
|
|
8081
|
+
}
|
|
8082
|
+
|
|
8083
|
+
// src/client.ts
|
|
8050
8084
|
var PERMIT_NETWORKS = /* @__PURE__ */ new Set([]);
|
|
8051
8085
|
var DEFAULT_EVM_RPC_URLS = {
|
|
8052
8086
|
"skale-base": "https://skale-base.skalenodes.com/v1/base",
|
|
@@ -8072,7 +8106,8 @@ function createX402Client(config2) {
|
|
|
8072
8106
|
integritas,
|
|
8073
8107
|
verbose = false,
|
|
8074
8108
|
defaultHeaders = {},
|
|
8075
|
-
mpp
|
|
8109
|
+
mpp,
|
|
8110
|
+
bridge: bridgeConfig
|
|
8076
8111
|
} = config2;
|
|
8077
8112
|
const relayWsEnabled = relayWs?.enabled === true;
|
|
8078
8113
|
const relayWsPreflightTimeoutMs = relayWs?.preflightTimeoutMs ?? 5e3;
|
|
@@ -9187,6 +9222,70 @@ function createX402Client(config2) {
|
|
|
9187
9222
|
headers: { ...requestHeaders, "X-PAYMENT": paymentHeader }
|
|
9188
9223
|
});
|
|
9189
9224
|
}
|
|
9225
|
+
if (bridgeConfig?.enabled) {
|
|
9226
|
+
log("No direct wallet match \u2014 attempting auto-bridge via RelAI API");
|
|
9227
|
+
try {
|
|
9228
|
+
const info = await getBridgeInfo(bridgeConfig.baseUrl);
|
|
9229
|
+
const targetAccept = accepts[0];
|
|
9230
|
+
const hasEvm = !!effectiveWallets.evm;
|
|
9231
|
+
const hasSol = !!hasSolanaWallet;
|
|
9232
|
+
const source = selectSourceChain(info.supportedSourceChains, hasEvm, hasSol);
|
|
9233
|
+
if (source) {
|
|
9234
|
+
const bridgePayTo = info.payTo[source.chain];
|
|
9235
|
+
if (bridgePayTo) {
|
|
9236
|
+
const targetAmount = targetAccept.amount || targetAccept.maxAmountRequired;
|
|
9237
|
+
const sourceAmount = computeSourceAmount(BigInt(targetAmount), info.feeBps).toString();
|
|
9238
|
+
const sourceChainIdx = info.supportedSourceChains.indexOf(source.chain);
|
|
9239
|
+
const sourceAsset = sourceChainIdx >= 0 && info.supportedSourceAssets[sourceChainIdx] || (source.type === "evm" ? info.supportedSourceAssets.find((a) => a.startsWith("0x")) || targetAccept.asset : info.supportedSourceAssets.find((a) => !a.startsWith("0x")) || "");
|
|
9240
|
+
let sourcePaymentHeader;
|
|
9241
|
+
const sourceAccept = {
|
|
9242
|
+
scheme: "exact",
|
|
9243
|
+
network: source.chain,
|
|
9244
|
+
asset: sourceAsset,
|
|
9245
|
+
payTo: bridgePayTo,
|
|
9246
|
+
amount: sourceAmount,
|
|
9247
|
+
extra: {
|
|
9248
|
+
...targetAccept.extra || {},
|
|
9249
|
+
...source.type === "solana" && info.feePayerSvm ? { feePayer: info.feePayerSvm } : {}
|
|
9250
|
+
}
|
|
9251
|
+
};
|
|
9252
|
+
if (source.type === "solana" && hasSolanaWallet) {
|
|
9253
|
+
sourcePaymentHeader = await buildSolanaPayment(sourceAccept, requirements, url2);
|
|
9254
|
+
} else if (source.type === "evm") {
|
|
9255
|
+
const evmNetwork = normalizeNetwork(source.chain);
|
|
9256
|
+
const usePermit = evmNetwork && PERMIT_NETWORKS.has(evmNetwork);
|
|
9257
|
+
sourcePaymentHeader = usePermit ? await buildEvmPermitPayment(sourceAccept, requirements, url2) : await buildEvmPayment(sourceAccept, requirements, url2);
|
|
9258
|
+
} else {
|
|
9259
|
+
throw new Error(`[relai-x402] No wallet for source chain type: ${source.type}`);
|
|
9260
|
+
}
|
|
9261
|
+
const settleData = await settleBridge(info.settleEndpoint, {
|
|
9262
|
+
sourcePayment: sourcePaymentHeader,
|
|
9263
|
+
sourceChain: source.chain,
|
|
9264
|
+
targetAccept: {
|
|
9265
|
+
scheme: "exact",
|
|
9266
|
+
network: targetAccept.network,
|
|
9267
|
+
asset: targetAccept.asset,
|
|
9268
|
+
payTo: targetAccept.payTo,
|
|
9269
|
+
amount: targetAmount
|
|
9270
|
+
},
|
|
9271
|
+
requirements,
|
|
9272
|
+
resource: url2,
|
|
9273
|
+
paymentFacilitator: info.paymentFacilitator
|
|
9274
|
+
});
|
|
9275
|
+
if (settleData.xPayment) {
|
|
9276
|
+
log(`Auto-bridge settled: target=${settleData.targetTxId}`);
|
|
9277
|
+
return fetch(input, {
|
|
9278
|
+
...requestInitWithHeaders,
|
|
9279
|
+
headers: { ...requestHeaders, "X-PAYMENT": settleData.xPayment }
|
|
9280
|
+
});
|
|
9281
|
+
}
|
|
9282
|
+
throw new Error("[relai-x402] Bridge settle did not return xPayment");
|
|
9283
|
+
}
|
|
9284
|
+
}
|
|
9285
|
+
} catch (bridgeErr) {
|
|
9286
|
+
log(`Auto-bridge failed: ${bridgeErr instanceof Error ? bridgeErr.message : bridgeErr}`);
|
|
9287
|
+
}
|
|
9288
|
+
}
|
|
9190
9289
|
throw new Error(buildNoWalletError(accepts, false));
|
|
9191
9290
|
}
|
|
9192
9291
|
const { accept, chain } = selected;
|
|
@@ -22882,8 +22981,50 @@ var charge = Method_exports.from({
|
|
|
22882
22981
|
}
|
|
22883
22982
|
});
|
|
22884
22983
|
|
|
22885
|
-
// src/mpp/
|
|
22984
|
+
// src/mpp/verify-erc20.ts
|
|
22886
22985
|
var TRANSFER_EVENT_TOPIC = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";
|
|
22986
|
+
async function verifyErc20Transfer(opts) {
|
|
22987
|
+
const { txHash, rpcUrl, tokenAddress, recipient, expectedAmount } = opts;
|
|
22988
|
+
let receipt = null;
|
|
22989
|
+
for (let attempt = 0; attempt < 5; attempt++) {
|
|
22990
|
+
const receiptRes = await fetch(rpcUrl, {
|
|
22991
|
+
method: "POST",
|
|
22992
|
+
headers: { "Content-Type": "application/json" },
|
|
22993
|
+
body: JSON.stringify({
|
|
22994
|
+
jsonrpc: "2.0",
|
|
22995
|
+
id: 1,
|
|
22996
|
+
method: "eth_getTransactionReceipt",
|
|
22997
|
+
params: [txHash]
|
|
22998
|
+
})
|
|
22999
|
+
});
|
|
23000
|
+
const receiptData = await receiptRes.json();
|
|
23001
|
+
if (receiptData.error) {
|
|
23002
|
+
throw new Error(`RPC error: ${receiptData.error.message}`);
|
|
23003
|
+
}
|
|
23004
|
+
receipt = receiptData.result;
|
|
23005
|
+
if (receipt) break;
|
|
23006
|
+
await new Promise((r) => setTimeout(r, (attempt + 1) * 1e3));
|
|
23007
|
+
}
|
|
23008
|
+
if (!receipt) {
|
|
23009
|
+
throw new Error("Transaction not found or not yet confirmed");
|
|
23010
|
+
}
|
|
23011
|
+
if (receipt.status !== "0x1") {
|
|
23012
|
+
throw new Error("Transaction failed on-chain");
|
|
23013
|
+
}
|
|
23014
|
+
const recipientPadded = "0x" + recipient.slice(2).toLowerCase().padStart(64, "0");
|
|
23015
|
+
const tokenLower = tokenAddress.toLowerCase();
|
|
23016
|
+
const matchingLog = receipt.logs.find((log) => {
|
|
23017
|
+
if (log.address.toLowerCase() !== tokenLower) return false;
|
|
23018
|
+
if (log.topics[0] !== TRANSFER_EVENT_TOPIC) return false;
|
|
23019
|
+
if (log.topics[2]?.toLowerCase() !== recipientPadded) return false;
|
|
23020
|
+
return BigInt(log.data) >= expectedAmount;
|
|
23021
|
+
});
|
|
23022
|
+
if (!matchingLog) {
|
|
23023
|
+
throw new Error("No matching ERC-20 Transfer found for recipient and amount");
|
|
23024
|
+
}
|
|
23025
|
+
}
|
|
23026
|
+
|
|
23027
|
+
// src/mpp/evm-server.ts
|
|
22887
23028
|
function evmCharge(config2) {
|
|
22888
23029
|
const {
|
|
22889
23030
|
recipient,
|
|
@@ -22925,39 +23066,13 @@ function evmCharge(config2) {
|
|
|
22925
23066
|
if (!txHash || !txHash.startsWith("0x")) {
|
|
22926
23067
|
throw new Error("Missing or invalid transaction hash in credential payload");
|
|
22927
23068
|
}
|
|
22928
|
-
|
|
22929
|
-
|
|
22930
|
-
|
|
22931
|
-
|
|
22932
|
-
|
|
22933
|
-
|
|
22934
|
-
id: 1,
|
|
22935
|
-
method: "eth_getTransactionReceipt",
|
|
22936
|
-
params: [txHash]
|
|
22937
|
-
})
|
|
22938
|
-
});
|
|
22939
|
-
const receiptData = await receiptRes.json();
|
|
22940
|
-
if (receiptData.error) {
|
|
22941
|
-
throw new Error(`RPC error: ${receiptData.error.message}`);
|
|
22942
|
-
}
|
|
22943
|
-
const receipt = receiptData.result;
|
|
22944
|
-
if (!receipt) {
|
|
22945
|
-
throw new Error("Transaction not found or not yet confirmed");
|
|
22946
|
-
}
|
|
22947
|
-
if (receipt.status !== "0x1") {
|
|
22948
|
-
throw new Error("Transaction failed on-chain");
|
|
22949
|
-
}
|
|
22950
|
-
const recipientPadded = "0x" + recipient.slice(2).toLowerCase().padStart(64, "0");
|
|
22951
|
-
const tokenLower = tokenAddress.toLowerCase();
|
|
22952
|
-
const matchingLog = receipt.logs.find((log) => {
|
|
22953
|
-
if (log.address.toLowerCase() !== tokenLower) return false;
|
|
22954
|
-
if (log.topics[0] !== TRANSFER_EVENT_TOPIC) return false;
|
|
22955
|
-
if (log.topics[2]?.toLowerCase() !== recipientPadded) return false;
|
|
22956
|
-
return BigInt(log.data) >= expectedAmount;
|
|
23069
|
+
await verifyErc20Transfer({
|
|
23070
|
+
txHash,
|
|
23071
|
+
rpcUrl,
|
|
23072
|
+
tokenAddress,
|
|
23073
|
+
recipient,
|
|
23074
|
+
expectedAmount: BigInt(cred.challenge.request.amount)
|
|
22957
23075
|
});
|
|
22958
|
-
if (!matchingLog) {
|
|
22959
|
-
throw new Error("No matching ERC-20 Transfer found for recipient and amount");
|
|
22960
|
-
}
|
|
22961
23076
|
return Receipt_exports.from({
|
|
22962
23077
|
method: "evm",
|
|
22963
23078
|
reference: txHash,
|
|
@@ -26283,6 +26398,65 @@ async function waitForReceipt(rpcUrl, txHash, timeoutMs = 3e4) {
|
|
|
26283
26398
|
}
|
|
26284
26399
|
return false;
|
|
26285
26400
|
}
|
|
26401
|
+
|
|
26402
|
+
// src/mpp/bridge-method.ts
|
|
26403
|
+
var charge2 = Method_exports.from({
|
|
26404
|
+
intent: "charge",
|
|
26405
|
+
name: "bridge",
|
|
26406
|
+
schema: {
|
|
26407
|
+
credential: {
|
|
26408
|
+
payload: zod_exports.object({
|
|
26409
|
+
/** "settled" = client called bridge settle, targetTxHash is proof */
|
|
26410
|
+
type: zod_exports.string(),
|
|
26411
|
+
/** Target chain tx hash (0x-prefixed) — server verifies on-chain */
|
|
26412
|
+
targetTxHash: zod_exports.optional(zod_exports.string()),
|
|
26413
|
+
/** Source chain tx hash/signature (for auditing) */
|
|
26414
|
+
sourceTxHash: zod_exports.optional(zod_exports.string()),
|
|
26415
|
+
/** CAIP-2 source chain used */
|
|
26416
|
+
sourceChain: zod_exports.optional(zod_exports.string())
|
|
26417
|
+
})
|
|
26418
|
+
},
|
|
26419
|
+
request: zod_exports.object({
|
|
26420
|
+
/** Amount in target token base units */
|
|
26421
|
+
amount: zod_exports.string(),
|
|
26422
|
+
/** Target ERC-20 token contract address */
|
|
26423
|
+
currency: zod_exports.string(),
|
|
26424
|
+
/** Target chain recipient address (merchant) */
|
|
26425
|
+
recipient: zod_exports.string(),
|
|
26426
|
+
/** Human-readable description */
|
|
26427
|
+
description: zod_exports.optional(zod_exports.string()),
|
|
26428
|
+
methodDetails: zod_exports.object({
|
|
26429
|
+
/** Target chain ID (where the merchant gets paid) */
|
|
26430
|
+
targetChainId: zod_exports.number(),
|
|
26431
|
+
/** Human-readable target network name (e.g. "skale-base") */
|
|
26432
|
+
targetNetwork: zod_exports.optional(zod_exports.string()),
|
|
26433
|
+
/** Target chain RPC URL (for server-side verification) */
|
|
26434
|
+
targetRpcUrl: zod_exports.optional(zod_exports.string()),
|
|
26435
|
+
/** Target token decimals */
|
|
26436
|
+
targetDecimals: zod_exports.optional(zod_exports.number()),
|
|
26437
|
+
/** Bridge settle endpoint URL */
|
|
26438
|
+
settleEndpoint: zod_exports.string(),
|
|
26439
|
+
/** Supported source chains (CAIP-2 format, e.g. ["eip155:8453", "solana:5eykt4..."]) */
|
|
26440
|
+
supportedSourceChains: zod_exports.array(zod_exports.string()),
|
|
26441
|
+
/** Supported source token addresses */
|
|
26442
|
+
supportedSourceAssets: zod_exports.optional(zod_exports.array(zod_exports.string())),
|
|
26443
|
+
/** Bridge receiver addresses per source chain: { [caip2]: address } */
|
|
26444
|
+
payToMap: zod_exports.record(zod_exports.string(), zod_exports.string()),
|
|
26445
|
+
/** Solana fee payer address (bridge facilitator sponsors gas) */
|
|
26446
|
+
feePayerSvm: zod_exports.optional(zod_exports.string()),
|
|
26447
|
+
/** Bridge fee in basis points */
|
|
26448
|
+
feeBps: zod_exports.optional(zod_exports.number()),
|
|
26449
|
+
/** Payment facilitator URL */
|
|
26450
|
+
paymentFacilitator: zod_exports.optional(zod_exports.string()),
|
|
26451
|
+
/** Unique reference ID (for replay protection) */
|
|
26452
|
+
reference: zod_exports.string()
|
|
26453
|
+
})
|
|
26454
|
+
})
|
|
26455
|
+
}
|
|
26456
|
+
});
|
|
26457
|
+
|
|
26458
|
+
// src/mpp/bridge-server.ts
|
|
26459
|
+
var BRIDGE_INFO_TTL_MS = 5 * 60 * 1e3;
|
|
26286
26460
|
export {
|
|
26287
26461
|
BASE_MAINNET_NETWORK,
|
|
26288
26462
|
CAIP2_TO_NETWORK,
|