My transactions return a 300 status when I route them via my merchant server.
When I call wallet_prepareCalls on my merchant server and call wallet_sendPreparedCalls (including the feeSignature, signature, etc) on Porto's relay, the transaction fails.
But when I send both calls to Porto's relay, the transaction succeeds.
The wallet I'm using in the client is a funded Porto Account.
The wallet on my merchant server is also a funded Porto Account.
I'm testing on Celo.
Here's a simplified version of what I'm doing in Typescript.
import { createClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
// Configuration
const MERCHANT_URL = "https://xxxx.ngrok-free.app/porto/merchant";
const RELAY_URL = "https://rpc.porto.sh";
const CHAIN_ID = 42220; // Celo
// User Credentials (from .env)
const USER_PRIVATE_KEY = process.env.USER_PRIVATE_KEY as `0x{string}`;
const account = privateKeyToAccount(USER_PRIVATE_KEY);
const USER_ADDRESS = account.address;
// Call Data (USDT Transfer)
const USDT_ADDRESS = "0x48065fbbe25f71c9282ddf5e1cd6d6a887483d5e";
const CALL_DATA =
"0xa9059cbb0000000000000000000000009afe6f1417638dd734596cf7af6fcc99c4bd96650000000000000000000000000000000000000000000000000000000000002710";
async function main() {
// 1. Prepare Calls (Merchant)
const merchantClient = createClient({ transport: http(MERCHANT_URL) });
const relayClient = createClient({ transport: http(RELAY_URL) });
console.log("\n1. Requesting wallet_prepareCalls from Merchant...");
let prepareResponse;
try {
prepareResponse = await merchantClient.request({
method: "wallet_prepareCalls" as any,
params: [
{
from: USER_ADDRESS,
chainId: `0x${CHAIN_ID.toString(16)}`,
calls: [
{
to: USDT_ADDRESS,
data: CALL_DATA,
value: "0x0",
},
],
capabilities: {
feeToken: USDT_ADDRESS,
meta: {},
},
},
],
});
console.log("Prepare Success. Digest:", prepareResponse.digest);
const quote = (prepareResponse as any).context?.quote?.quotes?.[0];
if (quote) {
console.log("Payment Token:", quote.intent?.paymentToken);
}
} catch (error) {
console.error("Prepare Failed:", error);
process.exit(1);
}
// 2. Sign Digest (User)
console.log("\n2. Signing digest with User Private Key...");
const signature = await account.sign({ hash: prepareResponse.digest });
console.log("Signature generated.");
// 3. Send Prepared Calls (Relay)
console.log("\n3. Sending wallet_sendPreparedCalls to Relay...");
let bundleId;
try {
const sendResponse = await relayClient.request({
method: "wallet_sendPreparedCalls" as any,
params: [
{
context: prepareResponse.context,
capabilities: prepareResponse.capabilities, // Includes feeSignature from merchant
signature: signature,
},
],
});
bundleId = sendResponse.id;
console.log("Send Success! Bundle ID:", bundleId);
} catch (error) {
console.error("Send Failed:", error);
process.exit(1);
}
// 4. Check Status
console.log(`\n4. Checking status for Bundle ID: ${bundleId}...`);
await new Promise((resolve) => setTimeout(resolve, 2000)); // Wait 2s
try {
const status = await relayClient.request({
method: "wallet_getCallsStatus" as any,
params: [bundleId],
});
console.log("Bundle Status:", JSON.stringify(status, null, 2));
} catch (error) {
console.error("Check Status Failed:", error);
}
}
main();
My merchant server looks like this:
import { Router, Route } from "porto/server";
const porto = Router({ basePath: "/porto" }).route(
"/merchant",
Route.merchant({
address: process.env.MERCHANT_ADDRESS as `0x{string}`,
key: process.env.MERCHANT_PRIVATE_KEY as `0x{string}`,
}),
);
Bun.serve({
...porto,
port: 3000,
});
console.log("Server running on http://localhost:3001/porto/merchant");
Am I doing something wrong here?
The lack of error messages coming from Relay makes it very hard to debug. Any plans to work on this?
My transactions return a 300 status when I route them via my merchant server.
When I call
wallet_prepareCallson my merchant server and callwallet_sendPreparedCalls(including the feeSignature, signature, etc) on Porto's relay, the transaction fails.But when I send both calls to Porto's relay, the transaction succeeds.
The wallet I'm using in the client is a funded Porto Account.
The wallet on my merchant server is also a funded Porto Account.
I'm testing on Celo.
Here's a simplified version of what I'm doing in Typescript.
My merchant server looks like this:
Am I doing something wrong here?
The lack of error messages coming from Relay makes it very hard to debug. Any plans to work on this?