Technical Documentation
Technical Specifications
Complete technical details about the x4pay-core payment system implementation, including Bluetooth (BLE) protocol specifications, ESP32 memory management, payment verification process, and mobile app integration patterns.
Bluetooth (BLE) Protocol
Service & Characteristics
Service UUID:
6e400002-b5a3-f393-e0a9-e50e24dcca9e
TX Characteristic:
6e400003-b5a3-f393-e0a9-e50e24dcca9e
RX Characteristic:
6e400004-b5a3-f393-e0a9-e50e24dcca9e
Protocol: Nordic
UART Service (NUS)
Connection Parameters
MTU Size: 150
bytes (set in code)
Connection Interval:
7.5ms - 4000ms
Advertising Interval:
100ms
Range: ~10
meters (Class 2)
Data Transfer Protocol
1. Device Advertisement
ESP32 advertises with device name containing payment info:
Device Name Format: "x402-[DEVICE_NAME]"
Advertisement Data: Service UUID + Device Name
Scan Response: Additional device info if needed
2. Connection Handshake
APP:
Scans for devices with Nordic UART service UUID
APP:
Connects to device via GATT
APP:
Discovers services and characteristics
APP:
Subscribes to TX characteristic for notifications
ESP32:
Sends payment requirements JSON via TX
characteristic
3. Payment Requirements JSON
{
"network": "base-sepolia",
"payTo": "0xa78eD39F695615315458Bb066ac9a5F28Dfd65FE",
"maxAmountRequired": "1000000",
"logoURL": "https://example.com/logo.jpg",
"description": "Coffee machine payment",
"options": ["Espresso", "Americano", "Latte"],
"dynamicPricing": true,
"recurring": {
"enabled": true,
"intervalSeconds": 30
}
}
4. Payment Response
APP:
User selects options and confirms payment in
wallet
APP:
Signs transaction with private key
(PIN-protected)
APP:
Sends payment payload JSON via RX characteristic
5. Payment Payload JSON
{
"network": "base-sepolia",
"from": "0x742d35Cc6C3C0532925a3b8D345A2E5E0E2F",
"to": "0xa78eD39F695615315458Bb066ac9a5F28Dfd65FE",
"amount": "1500000",
"signature": "0x1c2b4d...",
"nonce": 42,
"selectedOptions": ["Latte"],
"timestamp": 1729814400
}
ESP32 Memory Management
Memory Usage
X402-Aurdino:
~15KB program memory
X402-BLE-Aurdino:
~45KB program memory
RAM Usage: ~8KB
during operation
JSON Buffer: 2KB
allocated
Optimization Features
• Stack
monitoring with overflow detection
• Dynamic memory
allocation for JSON
• Automatic
garbage collection
• RTOS task
management
Multi-threading Architecture
X402-BLE-Aurdino uses FreeRTOS tasks for concurrent operation:
Task Structure
BLE Task: Handles
Bluetooth connections (Priority 2)
Payment Task:
Processes payment verification (Priority 3)
Main Task: User
code execution (Priority 1)
Watchdog Task:
System monitoring (Priority 4)
Synchronization
• Mutex locks for
shared resources
• Queue-based
message passing
• Semaphore
signaling for events
• Atomic
operations for counters
Code Example: Task Creation
void X402Ble::begin() {
// Set active instance for worker callbacks
s_active = this;
NimBLEDevice::init(device_name_.c_str());
NimBLEDevice::setDeviceName(device_name_.c_str());
NimBLEDevice::setPower(ESP_PWR_LVL_P7);
NimBLEDevice::setSecurityAuth(false, false, false);
NimBLEDevice::setMTU(150);
// Start payment verification worker with large stack on core 1
PaymentVerifyWorker::begin(/*stackBytes=*/8192, /*prio=*/3, /*core=*/1);
pServer = NimBLEDevice::createServer();
pServer->setCallbacks(new ServerCallbacks());
pService = pServer->createService(SERVICE_UUID);
}
Mobile App Connection Process
React Native Implementation
1. BLE Manager: Uses
react-native-ble-plx library
2. Device Scanning:
Filters by Nordic UART service UUID
3. Auto-connect:
Connects to strongest signal device
4. Service Discovery:
Discovers payment service characteristics
5. Data Exchange:
Subscribes to notifications, sends payments
Key Code: Device Connection
// Scan for devices
const scanForDevices = () => {
bleManager.startDeviceScan(
[NORDIC_UART_SERVICE_UUID],
{ allowDuplicates: false },
(error, device) => {
if (device?.name?.startsWith('x402-')) {
bleManager.stopDeviceScan();
connectToDevice(device);
}
}
);
};
// Connect and setup
const connectToDevice = async (device) => {
const connected = await device.connect();
await connected.discoverAllServicesAndCharacteristics();
// Subscribe to TX characteristic for incoming data
connected.monitorCharacteristicForService(
NORDIC_UART_SERVICE_UUID,
TX_CHARACTERISTIC_UUID,
(error, characteristic) => {
const data = JSON.parse(base64Decode(characteristic.value));
handlePaymentRequirements(data);
}
);
};
Web App Implementation
1. Web Bluetooth API:
navigator.bluetooth in Chrome/Edge
2. Service Filter:
Requests access to Nordic UART service
3. GATT Connection:
Connects via Bluetooth GATT protocol
4. Characteristic Access:
Reads/writes to TX/RX characteristics
Key Code: Web Bluetooth
const connectToDevice = async () => {
const device = await navigator.bluetooth.requestDevice({
filters: [{ services: ['6e400002-b5a3-f393-e0a9-e50e24dcca9e'] }]
});
const server = await device.gatt.connect();
const service = await server.getPrimaryService('6e400002-b5a3-f393-e0a9-e50e24dcca9e');
// Get characteristics
const txCharacteristic = await service.getCharacteristic('6e400003-b5a3-f393-e0a9-e50e24dcca9e');
const rxCharacteristic = await service.getCharacteristic('6e400004-b5a3-f393-e0a9-e50e24dcca9e');
// Listen for data from device
await txCharacteristic.startNotifications();
txCharacteristic.addEventListener('characteristicvaluechanged', (event) => {
const data = new TextDecoder().decode(event.target.value);
handlePaymentRequirements(JSON.parse(data));
});
};
Payment Verification Process
x402 Facilitator API
Endpoint:
https://x402-facilitator-a02bb8e9e6b3.herokuapp.com/verify
Method: POST with
JSON payload
Response: Transaction
hash or error
Timeout: 30 seconds
maximum
Verification Steps
1.
ESP32 receives payment payload from app via Bluetooth
(BLE)
2.
Device validates payload format and required
fields
3.
ESP32 sends HTTPS POST to x402 facilitator API over
WiFi
4.
Facilitator validates signature and submits transaction
to blockchain
5.
Facilitator returns transaction hash to ESP32
6.
ESP32 executes payment callback (e.g., dispense
coffee)
Code Example: Payment Verification
bool verifyPayment(const PaymentPayload &decodedSignedPayload, const String &paymentRequirements, const String &customHeaders) {
// Make API call using utility function
HttpResponse response = makePaymentApiCall("verify", decodedSignedPayload, paymentRequirements, customHeaders);
if (response.success && response.statusCode > 0) {
// Parse response manually for transaction hash
String txHash = extractJsonValue(response.body, "transactionHash");
if (txHash.length() > 0) {
Serial.println("Payment verified: " + txHash);
return true;
}
}
return false;
}
Security & Privacy
Mobile App Security
• Private keys
encrypted with PIN
• Biometric
authentication support
• Secure element
storage (Android)
• Transaction
signing happens locally
ESP32 Security
• No private keys
stored on device
• Payment
verification via external API
• WiFi
credentials in encrypted flash
• Bluetooth (BLE)
pairing not required
Data Privacy
• No personal
information stored on ESP32
• Payment amounts and
addresses are public (blockchain)
• Bluetooth (BLE)
connections are not logged
• Device can operate
without internet (offline mode)
Supported Blockchain Networks
Mainnet Networks
• Base (base)
• Polygon
(polygon)
• Avalanche
(avalanche)
• IoTeX (iotex)
• Sei (sei)
• Peaq (peaq)
Testnet Networks
• Base Sepolia
(base-sepolia)
• Polygon Mumbai
(polygon-mumbai)
• Avalanche Fuji
(avalanche-fuji)
• IoTeX Testnet
(iotex-testnet)
Token Support
• USDC (primary)
• Native gas tokens
• Custom ERC-20
tokens
• Micro-amounts
(1 wei precision)
Performance Metrics
Connection Times
BLE Discovery: 1-3
seconds
GATT Connection:
0.5-2 seconds
Service Discovery:
0.5-1 seconds
Total Connect Time:
2-6 seconds
Payment Processing
Data Transfer:
100-500ms
API Verification:
2-10 seconds
Blockchain Confirm:
5-60 seconds
Total Payment:
10-70 seconds
Throughput Limits
Concurrent Connections:
1 per ESP32 (BLE limitation)
Payments per Hour:
~60 (limited by API rate limits)
Data Rate: ~10KB/s
over Bluetooth (BLE)
Range: 10 meters
line-of-sight