@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.cjs
CHANGED
|
@@ -7624,7 +7624,6 @@ var Relai = class {
|
|
|
7624
7624
|
const integritasMode = integritasFlow === "single" ? "single_signature_fee_included" : integritasFlow === "dual" ? "dual_signature_split" : void 0;
|
|
7625
7625
|
const paymentHeader = req.headers["x-payment"] || req.headers["payment-signature"] || req.headers["x-payment-signature"];
|
|
7626
7626
|
const authHeader = req.headers["authorization"] || "";
|
|
7627
|
-
console.log(`[Relai] MPP check: paymentHeader=${!!paymentHeader}, hasMpp=${!!self.mpp}, authHeader=${authHeader?.slice(0, 30)}`);
|
|
7628
7627
|
if (!paymentHeader && self.mpp && /^Payment\s+/i.test(authHeader)) {
|
|
7629
7628
|
try {
|
|
7630
7629
|
const mppAmount = resolvedPrice.toFixed(6);
|
|
@@ -7636,10 +7635,7 @@ var Relai = class {
|
|
|
7636
7635
|
const mppRequest = new Request(mppUrl, { method: req.method, headers: mppHeaders });
|
|
7637
7636
|
const chargeHandler = self.mpp.charge({ amount: mppAmount });
|
|
7638
7637
|
const mppResult = await chargeHandler(mppRequest);
|
|
7639
|
-
console.log(`[Relai] MPP charge result: status=${mppResult.status}, keys=${Object.keys(mppResult)}, hasChallenge=${!!mppResult.challenge}, hasWithReceipt=${!!mppResult.withReceipt}`);
|
|
7640
7638
|
if (mppResult.status === 402 && mppResult.challenge instanceof Response) {
|
|
7641
|
-
const retryAuth = mppResult.challenge.headers.get("www-authenticate");
|
|
7642
|
-
console.log(`[Relai] MPP re-challenged (credential not accepted). New WWW-Auth: ${retryAuth?.slice(0, 60)}`);
|
|
7643
7639
|
}
|
|
7644
7640
|
if (mppResult.status !== 200 && !mppResult.withReceipt && mppResult.status !== 402) {
|
|
7645
7641
|
if (self.plugins.length > 0) {
|
|
@@ -7682,7 +7678,10 @@ var Relai = class {
|
|
|
7682
7678
|
const dummyResponse = new Response(null);
|
|
7683
7679
|
const receiptResponse = mppResult.withReceipt(dummyResponse);
|
|
7684
7680
|
const receiptHeader = receiptResponse.headers.get("payment-receipt");
|
|
7685
|
-
if (receiptHeader)
|
|
7681
|
+
if (receiptHeader) {
|
|
7682
|
+
res.setHeader?.("Payment-Receipt", receiptHeader);
|
|
7683
|
+
res.setHeader?.("Cache-Control", "private");
|
|
7684
|
+
}
|
|
7686
7685
|
}
|
|
7687
7686
|
options.onPaymentSettled?.(req, {
|
|
7688
7687
|
success: true,
|
|
@@ -7899,12 +7898,13 @@ var Relai = class {
|
|
|
7899
7898
|
if (mppResult?.challenge instanceof Response) {
|
|
7900
7899
|
const wwwAuth = mppResult.challenge.headers.get("www-authenticate");
|
|
7901
7900
|
if (wwwAuth) {
|
|
7902
|
-
res.setHeader("WWW-Authenticate", wwwAuth);
|
|
7901
|
+
res.setHeader?.("WWW-Authenticate", wwwAuth);
|
|
7903
7902
|
}
|
|
7904
7903
|
}
|
|
7905
7904
|
} catch {
|
|
7906
7905
|
}
|
|
7907
7906
|
}
|
|
7907
|
+
res.setHeader?.("Cache-Control", "no-store");
|
|
7908
7908
|
return res.status(402).json(paymentRequiredResponse);
|
|
7909
7909
|
}
|
|
7910
7910
|
let paymentProof;
|
|
@@ -7921,39 +7921,6 @@ var Relai = class {
|
|
|
7921
7921
|
});
|
|
7922
7922
|
}
|
|
7923
7923
|
}
|
|
7924
|
-
if (paymentProof.bridged === true && paymentProof.targetTxId) {
|
|
7925
|
-
console.log(`[Relai] Bridged payment accepted: source=${paymentProof.sourceTxId}, target=${paymentProof.targetTxId}`);
|
|
7926
|
-
const paymentInfo2 = {
|
|
7927
|
-
verified: true,
|
|
7928
|
-
transactionId: paymentProof.targetTxId,
|
|
7929
|
-
payer: paymentProof.sourceTxId || "bridge",
|
|
7930
|
-
network,
|
|
7931
|
-
amount: resolvedPrice
|
|
7932
|
-
};
|
|
7933
|
-
req.payment = paymentInfo2;
|
|
7934
|
-
req.x402Payer = paymentProof.sourceTxId || "bridge";
|
|
7935
|
-
req.x402Paid = true;
|
|
7936
|
-
req.x402Transaction = paymentProof.targetTxId;
|
|
7937
|
-
req.x402Network = network;
|
|
7938
|
-
req.x402Bridged = true;
|
|
7939
|
-
req.x402SourceChain = paymentProof.sourceChain;
|
|
7940
|
-
const paymentResponse2 = {
|
|
7941
|
-
x402Version: 2,
|
|
7942
|
-
scheme: "exact",
|
|
7943
|
-
network: caip2,
|
|
7944
|
-
transaction: paymentProof.targetTxId,
|
|
7945
|
-
payer: paymentProof.sourceTxId,
|
|
7946
|
-
amount: amount2,
|
|
7947
|
-
asset,
|
|
7948
|
-
bridged: true
|
|
7949
|
-
};
|
|
7950
|
-
res.setHeader(
|
|
7951
|
-
"PAYMENT-RESPONSE",
|
|
7952
|
-
Buffer.from(JSON.stringify(paymentResponse2)).toString("base64")
|
|
7953
|
-
);
|
|
7954
|
-
options.onPaymentSettled?.(req, { success: true, transaction: paymentProof.targetTxId, payer: paymentProof.sourceTxId });
|
|
7955
|
-
return next();
|
|
7956
|
-
}
|
|
7957
7924
|
let settlePayTo;
|
|
7958
7925
|
if (stripeConfig) {
|
|
7959
7926
|
settlePayTo = paymentProof.payload?.authorization?.to || paymentProof.accepted?.payTo || "";
|
|
@@ -8100,6 +8067,73 @@ var server_default = Relai;
|
|
|
8100
8067
|
// src/client.ts
|
|
8101
8068
|
var import_web3 = require("@solana/web3.js");
|
|
8102
8069
|
var import_spl_token = require("@solana/spl-token");
|
|
8070
|
+
|
|
8071
|
+
// src/bridge.ts
|
|
8072
|
+
var RELAI_API_BASE = "https://api.relai.fi";
|
|
8073
|
+
var _cacheMap = /* @__PURE__ */ new Map();
|
|
8074
|
+
var CACHE_TTL = 5 * 60 * 1e3;
|
|
8075
|
+
async function getBridgeInfo(baseUrl = RELAI_API_BASE) {
|
|
8076
|
+
const key = baseUrl.replace(/\/$/, "");
|
|
8077
|
+
const now = Date.now();
|
|
8078
|
+
const cached2 = _cacheMap.get(key);
|
|
8079
|
+
if (cached2 && now - cached2.time < CACHE_TTL) return cached2.info;
|
|
8080
|
+
const url2 = `${key}/bridge/info`;
|
|
8081
|
+
const res = await fetch(url2);
|
|
8082
|
+
if (!res.ok) {
|
|
8083
|
+
if (cached2) return cached2.info;
|
|
8084
|
+
throw new Error(`[relai:bridge] Failed to fetch ${url2}: ${res.status}`);
|
|
8085
|
+
}
|
|
8086
|
+
const data = await res.json();
|
|
8087
|
+
const info = {
|
|
8088
|
+
settleEndpoint: data.settleEndpoint,
|
|
8089
|
+
supportedSourceChains: data.supportedSourceChains || [],
|
|
8090
|
+
supportedSourceAssets: data.supportedSourceAssets || [],
|
|
8091
|
+
payTo: data.payTo || {},
|
|
8092
|
+
feePayerSvm: data.feePayerSvm ?? null,
|
|
8093
|
+
feeBps: data.feeBps ?? 100,
|
|
8094
|
+
paymentFacilitator: data.paymentFacilitator || "https://facilitator.x402.fi"
|
|
8095
|
+
};
|
|
8096
|
+
_cacheMap.set(key, { info, time: now });
|
|
8097
|
+
return info;
|
|
8098
|
+
}
|
|
8099
|
+
async function settleBridge(settleEndpoint, body) {
|
|
8100
|
+
const res = await fetch(settleEndpoint, {
|
|
8101
|
+
method: "POST",
|
|
8102
|
+
headers: { "Content-Type": "application/json" },
|
|
8103
|
+
body: JSON.stringify(body)
|
|
8104
|
+
});
|
|
8105
|
+
if (!res.ok) {
|
|
8106
|
+
const err = await res.json().catch(() => ({}));
|
|
8107
|
+
throw new Error(`[relai:bridge] settle failed: ${err.error || res.status}${err.details ? " \u2014 " + err.details : ""}`);
|
|
8108
|
+
}
|
|
8109
|
+
return res.json();
|
|
8110
|
+
}
|
|
8111
|
+
function selectSourceChain(supportedChains, hasEvmWallet, hasSolanaWallet, preferredSourceChainId) {
|
|
8112
|
+
if (preferredSourceChainId && hasEvmWallet) {
|
|
8113
|
+
const preferred = `eip155:${preferredSourceChainId}`;
|
|
8114
|
+
if (supportedChains.includes(preferred)) {
|
|
8115
|
+
return { type: "evm", chain: preferred };
|
|
8116
|
+
}
|
|
8117
|
+
}
|
|
8118
|
+
if (hasSolanaWallet) {
|
|
8119
|
+
const sol = supportedChains.find((c) => c.startsWith("solana:"));
|
|
8120
|
+
if (sol) return { type: "solana", chain: sol };
|
|
8121
|
+
}
|
|
8122
|
+
if (hasEvmWallet) {
|
|
8123
|
+
for (const chain of supportedChains) {
|
|
8124
|
+
if (chain.startsWith("eip155:")) {
|
|
8125
|
+
return { type: "evm", chain };
|
|
8126
|
+
}
|
|
8127
|
+
}
|
|
8128
|
+
}
|
|
8129
|
+
return null;
|
|
8130
|
+
}
|
|
8131
|
+
function computeSourceAmount(targetAmount, feeBps) {
|
|
8132
|
+
const fee = targetAmount * BigInt(feeBps) / 10000n;
|
|
8133
|
+
return targetAmount + fee;
|
|
8134
|
+
}
|
|
8135
|
+
|
|
8136
|
+
// src/client.ts
|
|
8103
8137
|
var PERMIT_NETWORKS = /* @__PURE__ */ new Set([]);
|
|
8104
8138
|
var DEFAULT_EVM_RPC_URLS = {
|
|
8105
8139
|
"skale-base": "https://skale-base.skalenodes.com/v1/base",
|
|
@@ -8125,7 +8159,8 @@ function createX402Client(config2) {
|
|
|
8125
8159
|
integritas,
|
|
8126
8160
|
verbose = false,
|
|
8127
8161
|
defaultHeaders = {},
|
|
8128
|
-
mpp
|
|
8162
|
+
mpp,
|
|
8163
|
+
bridge: bridgeConfig
|
|
8129
8164
|
} = config2;
|
|
8130
8165
|
const relayWsEnabled = relayWs?.enabled === true;
|
|
8131
8166
|
const relayWsPreflightTimeoutMs = relayWs?.preflightTimeoutMs ?? 5e3;
|
|
@@ -9240,6 +9275,70 @@ function createX402Client(config2) {
|
|
|
9240
9275
|
headers: { ...requestHeaders, "X-PAYMENT": paymentHeader }
|
|
9241
9276
|
});
|
|
9242
9277
|
}
|
|
9278
|
+
if (bridgeConfig?.enabled) {
|
|
9279
|
+
log("No direct wallet match \u2014 attempting auto-bridge via RelAI API");
|
|
9280
|
+
try {
|
|
9281
|
+
const info = await getBridgeInfo(bridgeConfig.baseUrl);
|
|
9282
|
+
const targetAccept = accepts[0];
|
|
9283
|
+
const hasEvm = !!effectiveWallets.evm;
|
|
9284
|
+
const hasSol = !!hasSolanaWallet;
|
|
9285
|
+
const source = selectSourceChain(info.supportedSourceChains, hasEvm, hasSol);
|
|
9286
|
+
if (source) {
|
|
9287
|
+
const bridgePayTo = info.payTo[source.chain];
|
|
9288
|
+
if (bridgePayTo) {
|
|
9289
|
+
const targetAmount = targetAccept.amount || targetAccept.maxAmountRequired;
|
|
9290
|
+
const sourceAmount = computeSourceAmount(BigInt(targetAmount), info.feeBps).toString();
|
|
9291
|
+
const sourceChainIdx = info.supportedSourceChains.indexOf(source.chain);
|
|
9292
|
+
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")) || "");
|
|
9293
|
+
let sourcePaymentHeader;
|
|
9294
|
+
const sourceAccept = {
|
|
9295
|
+
scheme: "exact",
|
|
9296
|
+
network: source.chain,
|
|
9297
|
+
asset: sourceAsset,
|
|
9298
|
+
payTo: bridgePayTo,
|
|
9299
|
+
amount: sourceAmount,
|
|
9300
|
+
extra: {
|
|
9301
|
+
...targetAccept.extra || {},
|
|
9302
|
+
...source.type === "solana" && info.feePayerSvm ? { feePayer: info.feePayerSvm } : {}
|
|
9303
|
+
}
|
|
9304
|
+
};
|
|
9305
|
+
if (source.type === "solana" && hasSolanaWallet) {
|
|
9306
|
+
sourcePaymentHeader = await buildSolanaPayment(sourceAccept, requirements, url2);
|
|
9307
|
+
} else if (source.type === "evm") {
|
|
9308
|
+
const evmNetwork = normalizeNetwork(source.chain);
|
|
9309
|
+
const usePermit = evmNetwork && PERMIT_NETWORKS.has(evmNetwork);
|
|
9310
|
+
sourcePaymentHeader = usePermit ? await buildEvmPermitPayment(sourceAccept, requirements, url2) : await buildEvmPayment(sourceAccept, requirements, url2);
|
|
9311
|
+
} else {
|
|
9312
|
+
throw new Error(`[relai-x402] No wallet for source chain type: ${source.type}`);
|
|
9313
|
+
}
|
|
9314
|
+
const settleData = await settleBridge(info.settleEndpoint, {
|
|
9315
|
+
sourcePayment: sourcePaymentHeader,
|
|
9316
|
+
sourceChain: source.chain,
|
|
9317
|
+
targetAccept: {
|
|
9318
|
+
scheme: "exact",
|
|
9319
|
+
network: targetAccept.network,
|
|
9320
|
+
asset: targetAccept.asset,
|
|
9321
|
+
payTo: targetAccept.payTo,
|
|
9322
|
+
amount: targetAmount
|
|
9323
|
+
},
|
|
9324
|
+
requirements,
|
|
9325
|
+
resource: url2,
|
|
9326
|
+
paymentFacilitator: info.paymentFacilitator
|
|
9327
|
+
});
|
|
9328
|
+
if (settleData.xPayment) {
|
|
9329
|
+
log(`Auto-bridge settled: target=${settleData.targetTxId}`);
|
|
9330
|
+
return fetch(input, {
|
|
9331
|
+
...requestInitWithHeaders,
|
|
9332
|
+
headers: { ...requestHeaders, "X-PAYMENT": settleData.xPayment }
|
|
9333
|
+
});
|
|
9334
|
+
}
|
|
9335
|
+
throw new Error("[relai-x402] Bridge settle did not return xPayment");
|
|
9336
|
+
}
|
|
9337
|
+
}
|
|
9338
|
+
} catch (bridgeErr) {
|
|
9339
|
+
log(`Auto-bridge failed: ${bridgeErr instanceof Error ? bridgeErr.message : bridgeErr}`);
|
|
9340
|
+
}
|
|
9341
|
+
}
|
|
9243
9342
|
throw new Error(buildNoWalletError(accepts, false));
|
|
9244
9343
|
}
|
|
9245
9344
|
const { accept, chain } = selected;
|
|
@@ -22935,8 +23034,50 @@ var charge = Method_exports.from({
|
|
|
22935
23034
|
}
|
|
22936
23035
|
});
|
|
22937
23036
|
|
|
22938
|
-
// src/mpp/
|
|
23037
|
+
// src/mpp/verify-erc20.ts
|
|
22939
23038
|
var TRANSFER_EVENT_TOPIC = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";
|
|
23039
|
+
async function verifyErc20Transfer(opts) {
|
|
23040
|
+
const { txHash, rpcUrl, tokenAddress, recipient, expectedAmount } = opts;
|
|
23041
|
+
let receipt = null;
|
|
23042
|
+
for (let attempt = 0; attempt < 5; attempt++) {
|
|
23043
|
+
const receiptRes = await fetch(rpcUrl, {
|
|
23044
|
+
method: "POST",
|
|
23045
|
+
headers: { "Content-Type": "application/json" },
|
|
23046
|
+
body: JSON.stringify({
|
|
23047
|
+
jsonrpc: "2.0",
|
|
23048
|
+
id: 1,
|
|
23049
|
+
method: "eth_getTransactionReceipt",
|
|
23050
|
+
params: [txHash]
|
|
23051
|
+
})
|
|
23052
|
+
});
|
|
23053
|
+
const receiptData = await receiptRes.json();
|
|
23054
|
+
if (receiptData.error) {
|
|
23055
|
+
throw new Error(`RPC error: ${receiptData.error.message}`);
|
|
23056
|
+
}
|
|
23057
|
+
receipt = receiptData.result;
|
|
23058
|
+
if (receipt) break;
|
|
23059
|
+
await new Promise((r) => setTimeout(r, (attempt + 1) * 1e3));
|
|
23060
|
+
}
|
|
23061
|
+
if (!receipt) {
|
|
23062
|
+
throw new Error("Transaction not found or not yet confirmed");
|
|
23063
|
+
}
|
|
23064
|
+
if (receipt.status !== "0x1") {
|
|
23065
|
+
throw new Error("Transaction failed on-chain");
|
|
23066
|
+
}
|
|
23067
|
+
const recipientPadded = "0x" + recipient.slice(2).toLowerCase().padStart(64, "0");
|
|
23068
|
+
const tokenLower = tokenAddress.toLowerCase();
|
|
23069
|
+
const matchingLog = receipt.logs.find((log) => {
|
|
23070
|
+
if (log.address.toLowerCase() !== tokenLower) return false;
|
|
23071
|
+
if (log.topics[0] !== TRANSFER_EVENT_TOPIC) return false;
|
|
23072
|
+
if (log.topics[2]?.toLowerCase() !== recipientPadded) return false;
|
|
23073
|
+
return BigInt(log.data) >= expectedAmount;
|
|
23074
|
+
});
|
|
23075
|
+
if (!matchingLog) {
|
|
23076
|
+
throw new Error("No matching ERC-20 Transfer found for recipient and amount");
|
|
23077
|
+
}
|
|
23078
|
+
}
|
|
23079
|
+
|
|
23080
|
+
// src/mpp/evm-server.ts
|
|
22940
23081
|
function evmCharge(config2) {
|
|
22941
23082
|
const {
|
|
22942
23083
|
recipient,
|
|
@@ -22978,39 +23119,13 @@ function evmCharge(config2) {
|
|
|
22978
23119
|
if (!txHash || !txHash.startsWith("0x")) {
|
|
22979
23120
|
throw new Error("Missing or invalid transaction hash in credential payload");
|
|
22980
23121
|
}
|
|
22981
|
-
|
|
22982
|
-
|
|
22983
|
-
|
|
22984
|
-
|
|
22985
|
-
|
|
22986
|
-
|
|
22987
|
-
id: 1,
|
|
22988
|
-
method: "eth_getTransactionReceipt",
|
|
22989
|
-
params: [txHash]
|
|
22990
|
-
})
|
|
22991
|
-
});
|
|
22992
|
-
const receiptData = await receiptRes.json();
|
|
22993
|
-
if (receiptData.error) {
|
|
22994
|
-
throw new Error(`RPC error: ${receiptData.error.message}`);
|
|
22995
|
-
}
|
|
22996
|
-
const receipt = receiptData.result;
|
|
22997
|
-
if (!receipt) {
|
|
22998
|
-
throw new Error("Transaction not found or not yet confirmed");
|
|
22999
|
-
}
|
|
23000
|
-
if (receipt.status !== "0x1") {
|
|
23001
|
-
throw new Error("Transaction failed on-chain");
|
|
23002
|
-
}
|
|
23003
|
-
const recipientPadded = "0x" + recipient.slice(2).toLowerCase().padStart(64, "0");
|
|
23004
|
-
const tokenLower = tokenAddress.toLowerCase();
|
|
23005
|
-
const matchingLog = receipt.logs.find((log) => {
|
|
23006
|
-
if (log.address.toLowerCase() !== tokenLower) return false;
|
|
23007
|
-
if (log.topics[0] !== TRANSFER_EVENT_TOPIC) return false;
|
|
23008
|
-
if (log.topics[2]?.toLowerCase() !== recipientPadded) return false;
|
|
23009
|
-
return BigInt(log.data) >= expectedAmount;
|
|
23122
|
+
await verifyErc20Transfer({
|
|
23123
|
+
txHash,
|
|
23124
|
+
rpcUrl,
|
|
23125
|
+
tokenAddress,
|
|
23126
|
+
recipient,
|
|
23127
|
+
expectedAmount: BigInt(cred.challenge.request.amount)
|
|
23010
23128
|
});
|
|
23011
|
-
if (!matchingLog) {
|
|
23012
|
-
throw new Error("No matching ERC-20 Transfer found for recipient and amount");
|
|
23013
|
-
}
|
|
23014
23129
|
return Receipt_exports.from({
|
|
23015
23130
|
method: "evm",
|
|
23016
23131
|
reference: txHash,
|
|
@@ -26336,6 +26451,65 @@ async function waitForReceipt(rpcUrl, txHash, timeoutMs = 3e4) {
|
|
|
26336
26451
|
}
|
|
26337
26452
|
return false;
|
|
26338
26453
|
}
|
|
26454
|
+
|
|
26455
|
+
// src/mpp/bridge-method.ts
|
|
26456
|
+
var charge2 = Method_exports.from({
|
|
26457
|
+
intent: "charge",
|
|
26458
|
+
name: "bridge",
|
|
26459
|
+
schema: {
|
|
26460
|
+
credential: {
|
|
26461
|
+
payload: zod_exports.object({
|
|
26462
|
+
/** "settled" = client called bridge settle, targetTxHash is proof */
|
|
26463
|
+
type: zod_exports.string(),
|
|
26464
|
+
/** Target chain tx hash (0x-prefixed) — server verifies on-chain */
|
|
26465
|
+
targetTxHash: zod_exports.optional(zod_exports.string()),
|
|
26466
|
+
/** Source chain tx hash/signature (for auditing) */
|
|
26467
|
+
sourceTxHash: zod_exports.optional(zod_exports.string()),
|
|
26468
|
+
/** CAIP-2 source chain used */
|
|
26469
|
+
sourceChain: zod_exports.optional(zod_exports.string())
|
|
26470
|
+
})
|
|
26471
|
+
},
|
|
26472
|
+
request: zod_exports.object({
|
|
26473
|
+
/** Amount in target token base units */
|
|
26474
|
+
amount: zod_exports.string(),
|
|
26475
|
+
/** Target ERC-20 token contract address */
|
|
26476
|
+
currency: zod_exports.string(),
|
|
26477
|
+
/** Target chain recipient address (merchant) */
|
|
26478
|
+
recipient: zod_exports.string(),
|
|
26479
|
+
/** Human-readable description */
|
|
26480
|
+
description: zod_exports.optional(zod_exports.string()),
|
|
26481
|
+
methodDetails: zod_exports.object({
|
|
26482
|
+
/** Target chain ID (where the merchant gets paid) */
|
|
26483
|
+
targetChainId: zod_exports.number(),
|
|
26484
|
+
/** Human-readable target network name (e.g. "skale-base") */
|
|
26485
|
+
targetNetwork: zod_exports.optional(zod_exports.string()),
|
|
26486
|
+
/** Target chain RPC URL (for server-side verification) */
|
|
26487
|
+
targetRpcUrl: zod_exports.optional(zod_exports.string()),
|
|
26488
|
+
/** Target token decimals */
|
|
26489
|
+
targetDecimals: zod_exports.optional(zod_exports.number()),
|
|
26490
|
+
/** Bridge settle endpoint URL */
|
|
26491
|
+
settleEndpoint: zod_exports.string(),
|
|
26492
|
+
/** Supported source chains (CAIP-2 format, e.g. ["eip155:8453", "solana:5eykt4..."]) */
|
|
26493
|
+
supportedSourceChains: zod_exports.array(zod_exports.string()),
|
|
26494
|
+
/** Supported source token addresses */
|
|
26495
|
+
supportedSourceAssets: zod_exports.optional(zod_exports.array(zod_exports.string())),
|
|
26496
|
+
/** Bridge receiver addresses per source chain: { [caip2]: address } */
|
|
26497
|
+
payToMap: zod_exports.record(zod_exports.string(), zod_exports.string()),
|
|
26498
|
+
/** Solana fee payer address (bridge facilitator sponsors gas) */
|
|
26499
|
+
feePayerSvm: zod_exports.optional(zod_exports.string()),
|
|
26500
|
+
/** Bridge fee in basis points */
|
|
26501
|
+
feeBps: zod_exports.optional(zod_exports.number()),
|
|
26502
|
+
/** Payment facilitator URL */
|
|
26503
|
+
paymentFacilitator: zod_exports.optional(zod_exports.string()),
|
|
26504
|
+
/** Unique reference ID (for replay protection) */
|
|
26505
|
+
reference: zod_exports.string()
|
|
26506
|
+
})
|
|
26507
|
+
})
|
|
26508
|
+
}
|
|
26509
|
+
});
|
|
26510
|
+
|
|
26511
|
+
// src/mpp/bridge-server.ts
|
|
26512
|
+
var BRIDGE_INFO_TTL_MS = 5 * 60 * 1e3;
|
|
26339
26513
|
// Annotate the CommonJS export names for ESM import in node:
|
|
26340
26514
|
0 && (module.exports = {
|
|
26341
26515
|
BASE_MAINNET_NETWORK,
|