create-mantle-facilitator
v0.4.4
Published
[](https://www.npmjs.com/package/create-mantle-facilitator) [](https://opensource.org/licenses/MIT)
Readme
create-mantle-facilitator
CLI tool to scaffold a self-hosted x402 payment facilitator for Mantle blockchain.
Quick Start
npx create-mantle-facilitator
cd my-facilitator # or the name you chose
npm install
npm run devThe CLI will guide you through the setup:
Welcome to Mantle Facilitator Setup!
? Where should we create the facilitator? my-facilitator
? RPC URL for Mantle network: https://rpc.mantle.xyz
? Facilitator wallet private key: (optional, set later)
? USDC contract address: 0x09Bc4E0D864854c6aFB6eB9A9cdF58aC190D0dF9
? Enable telemetry? (Send anonymous usage stats) No
✓ Done! Your facilitator is ready.Configuration
After creation, edit the .env file:
# Required
FACILITATOR_PRIVATE_KEY=0x... # Wallet that pays gas fees
RPC_URL=https://rpc.mantle.xyz # Mantle RPC endpoint
FACILITATOR_SECRET=fac_xxx... # Auto-generated security secret
# Optional
USDC_ADDRESS=0x09Bc4E0D864854c6aFB6eB9A9cdF58aC190D0dF9
PORT=8080
NETWORK_ID=mantle-mainnet
CHAIN_ID=5000
# Telemetry (Optional - always present in .env)
# TELEMETRY_PROJECT_KEY=your_project_key_here
# Get your key from https://x402mantlesdk.xyz/dashboardNote: The telemetry section is always added to .env (commented out if disabled during setup). To enable later, just uncomment and add your project key.
Important Notes
- FACILITATOR_PRIVATE_KEY: This wallet will pay gas fees for all settlements. Make sure it has MNT for gas.
- FACILITATOR_SECRET: Auto-generated during setup. Copy this to your backend's environment variables to enable secure authentication.
- Security: Never commit
.envto version control. The generated.gitignorealready excludes it.
Connecting to Your Backend
Add FACILITATOR_SECRET to your backend and configure the SDK:
import { mantlePaywall } from '@puga-labs/x402-mantle-sdk/server/express';
// Self-hosted facilitator (requires facilitatorUrl + facilitatorSecret)
const pay = mantlePaywall({
priceUsd: 0.01,
payTo: '0xYourWallet',
facilitatorUrl: 'https://your-facilitator.com', // Required for self-hosted
facilitatorSecret: process.env.FACILITATOR_SECRET!, // Required for self-hosted
// projectKey: process.env.PROJECT_KEY, // Optional: for analytics
});Note: When using facilitatorSecret (self-hosted mode), facilitatorUrl is required. The URL is automatically passed to clients via 402 responses, so frontend code doesn't need to configure it.
Running Locally
# Development mode (hot reload)
npm run dev
# Build for production
npm run build
# Run production build
npm startFacilitator runs on http://localhost:8080 by default.
Startup Banner
When the facilitator starts successfully, you'll see a banner:
+--------------------------------------------------+
| Mantle x402 Facilitator |
+--------------------------------------------------+
| Network: mantle-mainnet (5000) |
| Address: 0xAbcd...ef01 |
| Port: 8080 |
| Telemetry: disabled |
+--------------------------------------------------+
Note: Telemetry is disabled.
To enable analytics, set TELEMETRY_PROJECT_KEY in .env
Get your key at https://x402mantlesdk.xyz/dashboard
Server listening on http://localhost:8080Configuration Validation
The facilitator validates all required environment variables at startup with helpful error messages:
- FACILITATOR_PRIVATE_KEY: Must be 66 chars (0x + 64 hex digits)
- FACILITATOR_SECRET: Required for secure authentication
- RPC_URL: Must be valid URL (http:// or https://)
- USDC_ADDRESS: Must be valid Ethereum address
If validation fails, you'll see step-by-step fix instructions in the console.
Deployment
Deploy your facilitator to any Node.js hosting platform.
Docker
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
EXPOSE 8080
CMD ["npm", "start"]docker build -t my-facilitator .
docker run -p 8080:8080 --env-file .env my-facilitatorRailway
npm install -g @railway/cli
railway login
railway init
railway upThen add environment variables in Railway dashboard.
API Endpoints
GET /health
Returns facilitator status and wallet info.
curl http://localhost:8080/health{
"status": "ok",
"network": "mantle-mainnet",
"chainId": 5000,
"facilitatorAddress": "0x...",
"blockNumber": 12345678,
"mntBalance": "1.5"
}GET /supported
Returns supported networks and assets.
curl http://localhost:8080/supported{
"x402Version": 1,
"schemes": ["exact"],
"networks": ["mantle-mainnet"],
"assets": {
"mantle-mainnet": [{
"address": "0x09Bc4E0D864854c6aFB6eB9A9cdF58aC190D0dF9",
"symbol": "USDC",
"decimals": 6
}]
}
}POST /verify
Verifies a payment header without executing.
curl -X POST http://localhost:8080/verify \
-H "Content-Type: application/json" \
-d '{
"x402Version": 1,
"paymentHeader": "base64...",
"paymentRequirements": {...}
}'{
"isValid": true
}POST /settle
Executes the USDC transfer on-chain. Requires a valid settleToken for authentication.
curl -X POST http://localhost:8080/settle \
-H "Content-Type: application/json" \
-d '{
"x402Version": 1,
"paymentHeader": "base64...",
"paymentRequirements": {...},
"settleToken": "base64..."
}'{
"success": true,
"txHash": "0x..."
}Note: The settleToken is automatically generated by the SDK when facilitatorSecret is configured, and passed through the client to authenticate with your facilitator.
How It Works
┌─────────────────────────────────────────────────────────────────┐
│ Settlement Flow │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. Client signs EIP-712 authorization (gasless for user) │
│ │ │
│ ▼ │
│ 2. Client sends to facilitator POST /settle │
│ │ │
│ ▼ │
│ 3. Facilitator verifies signature │
│ │ │
│ ▼ │
│ 4. Facilitator calls USDC.transferWithAuthorization() │
│ - Pays gas in MNT │
│ - USDC transfers from user → merchant │
│ │ │
│ ▼ │
│ 5. Returns txHash to client │
│ │
└─────────────────────────────────────────────────────────────────┘The facilitator uses EIP-3009 transferWithAuthorization which allows:
- Gasless for users: Users only sign, never pay gas
- Atomic transfers: Signature + transfer in one transaction
- Replay protection: Nonces prevent double-spending
Supported Tokens
Currently, the facilitator supports USDC only for gasless payments.
Why only USDC?
Gasless payments require tokens that implement the EIP-3009 standard (transferWithAuthorization). This standard allows users to sign a payment authorization off-chain, while the facilitator submits the transaction and pays gas fees.
On Mantle mainnet, USDC is currently the only token that implements EIP-3009. As other stablecoins and tokens adopt this standard, we will add support for them.
| Token | EIP-3009 Support | Status | |-------|------------------|--------| | USDC | Yes | Supported | | USDT | No | Not available | | DAI | No | Not available | | Other tokens | — | Pending EIP-3009 adoption |
Telemetry
When TELEMETRY_PROJECT_KEY is set, the facilitator sends anonymous analytics:
What is sent:
- Payment metadata (buyer address, amount, asset, network)
- Transaction hash
- Timestamp
- Facilitator address
What is NOT sent:
- Private keys
- Personal information
- Request/response payloads
Get your project key from Dashboard.
Telemetry errors never affect payment processing — if analytics backend is down, payments continue normally.
Security Considerations
Facilitator Secret (REQUIRED)
FACILITATOR_SECRETprevents unauthorized usage of your facilitator- Without it, anyone could use your facilitator URL to settle their payments and drain your gas wallet
- The secret creates a secure token flow: Backend → Client → Facilitator
- Always set
facilitatorSecretin your backend SDK configuration
Private Key Security
- Never commit
.envto git - Use secret management in production (Railway secrets, Fly secrets, etc.)
- Never commit
Links
License
MIT
