POST /wallet/verify builds an unsigned ERC-4337 UserOperation for a smart wallet payment. The facilitator validates the wallet, checks balances, injects the fee, estimates gas via the bundler, and returns a UserOp ready for the client to sign.
Base URL
https://facilitatorv3.b402.ai
Request
curl -X POST https://facilitatorv3.b402.ai/wallet/verify \
-H "Content-Type: application/json" \
-d '{
"walletAddress": "0x...nexus_smart_wallet",
"transactions": [
{
"to": "0x...recipient",
"amount": "10000000000000000",
"token": "0x55d398326f99059fF775485246999027B3197955"
}
],
"paymentRequirements": {
"network": "bsc"
}
}'
const response = await fetch('https://facilitatorv3.b402.ai/wallet/verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
walletAddress: '0x...nexus_smart_wallet',
transactions: [
{
to: '0x...recipient',
amount: '10000000000000000',
token: '0x55d398326f99059fF775485246999027B3197955',
},
],
paymentRequirements: {
network: 'bsc', // or 'base'
},
}),
});
const data = await response.json();
// data.userOp -> unsigned UserOp to sign
// data.userOpHash -> hash the client must sign
// data.totalAmount -> original amount + facilitator fee
Request Body
| Field | Type | Required | Description |
|---|
walletAddress | string | Yes | Nexus smart wallet address (must already be deployed) |
transactions | array | Yes | Array of payment recipients (1-20 items) |
transactions[].to | string | Yes | Recipient address |
transactions[].amount | string | Yes | Amount in wei (token smallest unit) |
transactions[].token | string | Yes | ERC-20 token contract address |
paymentRequirements | object | Yes | Payment configuration |
paymentRequirements.network | string | Yes | Target network ("bsc" or "base") |
All transactions in a batch must use the same token address. Mixed-token batches are rejected.
Response
200 - Unsigned UserOp
{
"isValid": true,
"payer": "0x...wallet_owner",
"userOp": {
"sender": "0x...wallet_address",
"nonce": "0x...",
"callData": "0x...encoded_batch_call",
"callGasLimit": "0x...",
"verificationGasLimit": "0x...",
"preVerificationGas": "0x...",
"maxFeePerGas": "0x...",
"maxPriorityFeePerGas": "0x...",
"paymaster": "0x...",
"paymasterVerificationGasLimit": "0x...",
"paymasterPostOpGasLimit": "0x...",
"paymasterData": "0x...",
"signature": "0x"
},
"userOpHash": "0x...hash_to_sign",
"feeAmount": "50000000000000",
"totalAmount": "10050000000000000"
}
Response Fields
| Field | Type | Description |
|---|
isValid | boolean | Whether the payment can proceed |
payer | string | Address of the wallet owner (EOA that controls the smart wallet) |
userOp | object | Unsigned ERC-4337 UserOperation |
userOp.sender | string | Smart wallet address executing the operation |
userOp.nonce | string | Wallet nonce (hex) |
userOp.callData | string | Encoded batch call: approve(relayer, totalAmount) + transfers (hex) |
userOp.callGasLimit | string | Gas limit for the main execution (hex) |
userOp.verificationGasLimit | string | Gas limit for signature verification (hex) |
userOp.preVerificationGas | string | Gas overhead for bundler processing (hex) |
userOp.maxFeePerGas | string | Maximum fee per gas unit (hex) |
userOp.maxPriorityFeePerGas | string | Maximum priority fee per gas unit (hex) |
userOp.paymaster | string | Paymaster contract address (covers gas for the user) |
userOp.paymasterVerificationGasLimit | string | Gas limit for paymaster verification (hex) |
userOp.paymasterPostOpGasLimit | string | Gas limit for paymaster post-operation (hex) |
userOp.paymasterData | string | Signed paymaster authorization data (hex) |
userOp.signature | string | Empty (0x) - client must sign and populate this |
userOpHash | string | Hash of the UserOp that the client must sign |
feeAmount | string | Facilitator fee in token wei |
totalAmount | string | amount + feeAmount - total deducted from wallet |
Error Responses
| Status | Code | Description |
|---|
| 400 | validation_error | Invalid request body, missing fields, or mixed tokens in batch |
| 400 | validation_error | Wallet not deployed at the given address |
| 400 | validation_error | Insufficient token balance in wallet |
| 400 | validation_error | Batch exceeds 20 transactions |
| 500 | blockchain_error | Failed to read on-chain state or estimate gas |
What Happens Server-Side
- Validates wallet - Confirms a deployed contract exists at
walletAddress
- Checks balance - Reads the token balance in the smart wallet
- Builds batch call - Encodes
approve(relayer, totalAmount) followed by the transfer calls into a single callData
- Injects fee - Adds the facilitator fee to the total
- Estimates gas - Calls the ERC-4337 bundler to estimate
callGasLimit, verificationGasLimit, and preVerificationGas
- Signs paymaster data - The paymaster signs off on sponsoring the gas for this UserOp
- Returns unsigned UserOp - The client signs
userOpHash and submits via /wallet/settle
Batch Payments
The transactions array supports 1 to 20 recipients in a single UserOp. All recipients must use the same token.
curl -X POST https://facilitatorv3.b402.ai/wallet/verify \
-H "Content-Type: application/json" \
-d '{
"walletAddress": "0x...nexus_smart_wallet",
"transactions": [
{
"to": "0x...recipient_1",
"amount": "5000000000000000",
"token": "0x55d398326f99059fF775485246999027B3197955"
},
{
"to": "0x...recipient_2",
"amount": "3000000000000000",
"token": "0x55d398326f99059fF775485246999027B3197955"
}
],
"paymentRequirements": {
"network": "bsc"
}
}'
The facilitator sums all amounts, adds a single fee, and encodes the full batch into one UserOp.
Next Step
After receiving the response, sign the userOpHash with the wallet owner’s private key and submit the signed UserOp to POST /wallet/settle.