DEV Community

rene
rene

Posted on

No Backend? No Problem: How I Built a Static Crypto Checkout Using eth_call

No Backend? No Problem: How I Built a Static Crypto Checkout Using eth_call

Accepting crypto payments usually means running a server to watch the blockchain. But what if you could do it all from a static HTML page? No database, no backend, no websocket—just a browser and an RPC endpoint. Here's how I built a working USDT checkout that verifies payments using a single eth_call.

The Magic of eth_call and Selector 0x70a08231

Every ERC-20 token, including USDT, has a balanceOf(address) function. When you call this function via an RPC provider, the Ethereum Virtual Machine (EVM) returns the token balance for that address. The function signature is balanceOf(address) which hashes to the 4-byte selector 0x70a08231.

To call it from JavaScript, you encode the ABI:

const abi = [
  {
    constant: true,
    inputs: [{ name: "_owner", type: "address" }],
    name: "balanceOf",
    outputs: [{ name: "balance", type: "uint256" }],
    type: "function",
  },
];
const iface = new ethers.utils.Interface(abi);
const data = iface.encodeFunctionData("balanceOf", [customerAddress]);
Enter fullscreen mode Exit fullscreen mode

Then send it as an eth_call to any public RPC (e.g., Infura, Alchemy, or a free endpoint):

const response = await fetch(rpcUrl, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    jsonrpc: "2.0",
    id: 1,
    method: "eth_call",
    params: [{ to: usdtContract, data: data }, "latest"],
  }),
});
const { result } = await response.json();
const balance = ethers.BigNumber.from(result);
Enter fullscreen mode Exit fullscreen mode

That's it. No server, no API key needed if you use a public RPC. The entire payment verification runs in the browser.

The Verification Algorithm

My system uses three steps:

1. Baseline Balance Check

When a user initiates a checkout, the app records their current USDT balance. This baseline is stored in localStorage along with the expected payment amount.

2. Delta Comparison with 0.1% Tolerance

Every 20 seconds, the app fetches the current balance and compares it to the baseline. If the difference is within 0.1% of the expected amount, the payment is considered confirmed. The tolerance accounts for tiny fluctuations (dust) and rounding errors.

const delta = currentBalance.sub(baselineBalance);
const expected = ethers.utils.parseUnits(expectedAmount, 6); // 6 decimals for USDT
const tolerance = expected.mul(10).div(1000); // 0.1% tolerance

if (delta.gte(expected.sub(tolerance)) && delta.lte(expected.add(tolerance))) {
  // Payment confirmed!
  markAsPaid();
}
Enter fullscreen mode Exit fullscreen mode

3. Polling Loop

The verification runs in a simple polling loop that checks every 20 seconds. This interval balances responsiveness with RPC call efficiency.

Honest Limitations

While this approach is elegant, it's important to understand its limitations:

Balance-Delta Confusion with Concurrent Payments

If multiple payments are sent to the same address in quick succession, the system may struggle to distinguish which payment corresponds to which order. This is a known limitation of the balance-delta approach.

Manual Delivery

This system does not automate product delivery. Once a payment is verified, the merchant must manually fulfill the order. There's no webhook, no automated email, and no digital download trigger.

No Refunds

The system has no built-in refund mechanism. If a customer requests a refund, you'll need to handle it manually outside of this system.

Conclusion

This static crypto payment verification system demonstrates how you can accept cryptocurrency payments without running a backend server. By leveraging eth_call and a simple polling mechanism, you can create a trustless payment experience that works entirely in the user's browser.

The approach is particularly valuable for small businesses or developers who want to experiment with crypto payments without the infrastructure overhead of traditional payment gateways.

Live Demo: https://crypto-store-mvchv2id.netlify.app/

AI Assistance Disclosure: This article was assisted in its creation by AI technology to ensure comprehensive coverage of the topic and maintain a consistent writing style. The content has been reviewed and refined by human editors to ensure accuracy and coherence.

Top comments (0)