import { ethers } from 'ethers';
// Configuration
const PRIVATE_KEY = process.env.PRIVATE_KEY;
const RPC_URL = 'https://bsc-dataseed1.binance.org';
const FACILITATOR_URL = 'https://facilitatorv3.b402.ai';
const TOKEN_ADDRESS = '0x8d0d000ee44948fc98c9b98a4fa4921476f08b0d'; // USD1
const RELAYER_ADDRESS = '0xE91b564EB8DFF305Ff8efA332f84c487b9da5171';
const RECIPIENT = '0x0553B926D6a599CAAc56377042cA6B40dd0b7F4e';
// EIP-712 domain and types
const domain = {
name: 'B402',
version: '1',
chainId: 56,
verifyingContract: RELAYER_ADDRESS,
};
const types = {
TransferWithAuthorization: [
{ name: 'token', type: 'address' },
{ name: 'from', type: 'address' },
{ name: 'to', type: 'address' },
{ name: 'value', type: 'uint256' },
{ name: 'validAfter', type: 'uint256' },
{ name: 'validBefore', type: 'uint256' },
{ name: 'nonce', type: 'bytes32' },
],
};
async function main() {
if (!PRIVATE_KEY) {
throw new Error('Set PRIVATE_KEY environment variable');
}
// Initialize wallet
const provider = new ethers.JsonRpcProvider(RPC_URL);
const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
console.log('Wallet:', wallet.address);
// Build authorization
const authorization = {
token: TOKEN_ADDRESS,
from: wallet.address,
to: RECIPIENT,
value: ethers.parseUnits('0.01', 18).toString(),
validAfter: 0,
validBefore: Math.floor(Date.now() / 1000) + 3600,
nonce: ethers.hexlify(ethers.randomBytes(32)),
};
console.log('Authorization:', JSON.stringify(authorization, null, 2));
// Sign EIP-712 message
const signature = await wallet.signTypedData(domain, types, authorization);
console.log('Signature:', signature);
// Build Facilitator payload
const payload = {
paymentPayload: {
token: TOKEN_ADDRESS,
payload: {
authorization,
signature,
},
},
paymentRequirements: {
network: 'mainnet',
relayerContract: RELAYER_ADDRESS,
},
};
// Step 1: Verify
console.log('\nVerifying payment...');
const verifyRes = await fetch(`${FACILITATOR_URL}/verify`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
});
const verifyData = await verifyRes.json();
console.log('Verify result:', verifyData);
if (!verifyData.isValid) {
console.error('Verification failed:', verifyData.invalidReason);
process.exit(1);
}
// Step 2: Settle
console.log('\nSettling payment...');
const settleRes = await fetch(`${FACILITATOR_URL}/settle`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
});
const settleData = await settleRes.json();
console.log('Settle result:', settleData);
if (settleData.success) {
// Use https://basescan.org/tx/ for Base transactions
console.log(`\nPayment settled: https://bscscan.com/tx/${settleData.transaction}`);
} else {
console.error('Settlement failed:', settleData.errorReason);
}
}
main().catch(console.error);