Built for developers,
by developers.

Testnet betaArc Testnet

On most chains the payer holds the asset in one token and pays gas in another, and sending an ERC-20 needs a separate approval first: two wallet confirmations, and the second one is where crypto checkouts lose people. On Arc, USDC is the gas. No approve(), no permit(), nothing extra to hold. One confirmation, start to finish.

Where this stands
Running on Arc Testnet
CHAIN_ID5042002
ROUTER_ADDR0x033d59E97223f172C9c3661c5bf003d06e84Ab4EVerified source on ArcScan
Technical architecture

Atomic settlement

The payment does not go wallet-to-wallet. It goes through the router, which does two things in the same transaction: it splits off the 0.5% fee and forwards the rest to you, and it emits a receipt carrying your link’s ID. If you do not get paid, no fee is collected. The two cannot come apart.

<1sSettlement, final
0.5%Protocol fee
PAYERSIGNATUREROUTERMERCHANTUSDC (net)TREASURYfee (0.5%)
Integration

Simple primitive

You do not need any of this to get paid; create a link and send it. But if you want payments inside your own product, it is a single call: pass the link ID and the destination address, and the router handles the split and the receipt. A background service watches the chain for those receipts and turns them into dashboard rows, emails and Telegram alerts.

terminalnpm install @leyline/sdk
// Execute a native USDC payment on Arc
async function processPayment(linkId, merchantAddress) {
  /*
   * The pay() function is non-custodial and
   * atomic. No separate approval required.
   */
  const tx = await leyline.pay(
    linkId,
    merchantAddress,
    { gasLimit: 210000, priority: 'high' }
  );

  return tx.wait();
}
Proof of solvency

The router contract holds a zero balance at the end of every transaction.

This is the single most important decision in the project. Because we never hold funds, we are software rather than a payment processor, which keeps us out of money-transmitter licensing and means we cannot lose your money or freeze it. There is a test in the codebase asserting the router’s balance is zero. That test is the claim.