Skip to content

NEAR

NEAR is the “user-owned AI” chain (its co-founder co-authored the Transformer paper), with both Circle USDC and Tether USDT native on-chain. Name chain: 'near' and the driver auto-mounts on first use — a pure-EVM install never downloads its library.

NEAR is unusual in PipRail: it uses both proof templates. Native NEAR is digest-bound (the easy, zero-setup path); the NEP-141 token path is memo-bound and needs a one-time storage_deposit. Both are covered below.

The NEAR library is an optional peer, lazy-loaded the first time you name chain: 'near':

Terminal window
npm install near-api-js

A NEAR wallet is { accountId, key }, where key is an ed25519:… secret key — NEAR signing needs both an account id and the secret key (not just a private key). The presence of accountId is what tells the SDK this is a NEAR wallet.

import { PipRailClient } from '@piprail/sdk'
const client = new PipRailClient({
wallet: { accountId: 'agent.near', key: process.env.AGENT_KEY }, // ed25519:… secret
chain: 'near',
})

payTo is a NEAR account id — a named account like merchant.near, or a 64-hex implicit account. See Wallets by family for every family’s shape.

Name a token by symbol, 'native', or a custom NEP-141 contract:

tokenWhat it is
'native'Native NEAR (24 decimals). Zero-setup — digest-bound, no storage_deposit.
'USDC'Circle’s native USDC (17208628…36133a1, 6dp) — not the bridged …factory.bridge.near (USDC.e).
'USDT'Tether’s native USDt (usdt.tether-token.near, 6dp).
{ contractId, decimals }Any other NEP-141 token, by contract account id.
import { requirePayment } from '@piprail/sdk'
// Express/Connect middleware that turns this route paid-only:
requirePayment({ chain: 'near', token: 'USDC', amount: '0.10', payTo: 'merchant.near' })

NEAR is the volatile gas coin, so for stable pricing pay in USDC/USDT; for no-setup flows, native NEAR is ideal.

token: 'native' pays in NEAR via a plain Transfer, digest-bound like EVM/Solana/Sui: the proof is <accountId>:<txHash>, verified by tx hash + a recency window + the gate’s single-use proof set. Native needs no storage_deposit and a transfer even creates a fresh implicit recipient — there is nothing to register first.

requirePayment({ chain: 'near', token: 'native', amount: '0.10', payTo: 'merchant.near' })

Tokens need storage_deposit (the receive prerequisite)

Section titled “Tokens need storage_deposit (the receive prerequisite)”

Before an account can receive a NEP-141 token it must be storage-registered on that exact token contract (NEP-145) — a one-time ~0.00125 NEAR call, per account per token. Both the merchant (payTo) and the payer must be registered, or the payer’s ft_transfer panics.

planPayment() surfaces an unregistered recipient as a RECIPIENT_NOT_READY blocker before you spend, and a payment to an unready recipient raises a RecipientNotReadyError:

const url = 'https://api.example.com/report'
const plan = await client.planPayment(url) // → PaymentPlan | null (null when not 402-gated)
if (!plan) {
await client.fetch(url) // not payment-gated — just fetch it
} else if (plan.payable) {
await client.fetch(url) // safe — we checked
} else {
console.log(plan.fundingHint) // e.g. "recipient isn't registered on usdt.tether-token.near"
}

The payer needs a little NEAR for gas either way — native or token.

client.fetch(url) pays the cheapest settleable rail. If the wallet or recipient isn’t ready it throws a typed PipRailError — branch on the stable .code rather than the message. On NEAR the two you’ll meet are RECIPIENT_NOT_READY (the payTo account isn’t storage_deposit-registered on the token) and INSUFFICIENT_FUNDS (the payer is short on the token or on NEAR for gas):

import {
RecipientNotReadyError,
InsufficientFundsError,
} from '@piprail/sdk'
try {
const res = await client.fetch(url)
// → a normal Response once the proof verifies (200 + the gated resource)
} catch (err) {
if (err instanceof RecipientNotReadyError) {
// fix the RECIPIENT: storage_deposit-register payTo on the token (~0.00125 NEAR)
console.error('recipient not ready:', err.message)
} else if (err instanceof InsufficientFundsError) {
// fix the PAYER: top up the token, or add NEAR for gas
console.error('payer is short:', err.message)
} else {
throw err
}
}

NEAR is the one family that uses both proof templates:

AssetTemplateHow it’s bound
Native NEARB — digest-boundproof <accountId>:<txHash>, verified by tx hash + recency + single-use set
NEP-141 tokensA — memo-boundthe challenge nonce rides in the ft_transfer memo

NEAR has no account-history RPC, so the token path verifies by tx hash and only trusts an ft_transfer event emitted by the real token contract — verify() re-derives every checked field from the trusted accept, never the client-supplied ref. See Replay protection for the single-use proof set.

Standard exact rail — gasless for the buyer via NEP-366 (NEP-141 tokens)

Section titled “Standard exact rail — gasless for the buyer via NEP-366 (NEP-141 tokens)”

Beside the default onchain-proof rail, PipRail also speaks the ratified x402 exact scheme for NEAR (scheme_exact_near.md, x402 v2). The buyer signs a NEP-366 SignedDelegateAction authorizing exactly one NEP-141 ft_transfer (to payTo, the exact amount, the mandatory 1 yoctoNEAR) with a full-access key — and never broadcasts it or holds any NEAR. A relayer wraps that delegate in its own outer transaction, prepays the gas + the yocto, and submits it. The agent (buyer) is completely gasless.

This rail is opt-in and only ever offered for NEP-141 tokens (USDC / USDT, or a custom token you pass). Native NEAR is not exact-payable — the scheme is defined over ft_transfer — so native always stays on the zero-setup onchain-proof rail. Defaults are unchanged: an onchain-proof-only client behaves exactly as before.

Enable 'exact' in schemes and the client builds + signs the SignedDelegateAction for any NEAR exact rail it’s offered. It spends zero NEAR (the merchant’s relayer pays):

const client = new PipRailClient({
chain: 'near',
wallet: { accountId: 'agent.near', key: 'ed25519:…' }, // MUST be a full-access key (see below)
schemes: ['onchain-proof', 'exact'],
})
await client.fetch('https://api.example.com/data') // 402 → signs a delegate (0 NEAR) → 200

Receiving (the merchant) — self-settle today

Section titled “Receiving (the merchant) — self-settle today”

NEAR exact is self-settled today: the merchant runs a small relayer (a funded NEAR account) that the gate uses to submit the buyer’s signed delegate. The buyer stays gasless; the merchant’s relayer pays the sub-cent NEAR network fee to receive — exactly like PipRail’s self-settle on Solana / Algorand / Aptos. This is the standard, working configuration:

createPaymentGate({
chain: 'near',
token: 'USDC', // or 'USDT' — any NEP-141; native is onchain-proof only
amount: '0.01',
payTo: 'merchant.near',
exact: {
settle: 'self',
relayer: { accountId: 'relayer.near', key: 'ed25519:…' }, // a funded NEAR key that pays settle gas
},
})

The relayer:

  • needs a little NEAR for gas (each settle costs ≈ 0.0003 NEAR — well under a cent);
  • must not equal the payer (that’s the buyer), but may equal payTo (the merchant can relay its own incoming payment — NEAR’s outer/inner-transaction split allows it);
  • should use a dedicated key you can fund + rotate, not your cold treasury key (it’s a hot key the gate signs with on every settle).

Unlike EVM/Solana/Algorand — where the merchant co-signs one slot of the buyer’s transaction — the NEAR relayer wraps the delegate in a separate outer transaction it fully owns, then waits for the inner ft_transfer receipt to finish executing across shards before the gate returns 200.

PartyPays gas?
Buyer / agentNo — signs off-chain, holds zero NEAR
Merchant relayer (self-settle)Yes — the sub-cent settle fee + the 1 yoctoNEAR, prepaid on submit

Because the relayer prepays both the gas and the attached deposit of the delegated call, a hostile buyer could try to drain it by signing a valid sub-cent transfer with a huge gas or a large deposit. PipRail’s gate re-derives every field from your trusted rail and refuses the delegate before the relayer ever signs if the attached deposit ≠ exactly 1 yoctoNEAR or the gas exceeds 300 TGas (an honest payload uses ~30 TGas). It also re-checks the token contract, payTo, amount, single-action shape, and expiry against the rail — never the client’s echo.

Storage registration (NEP-145) — required to send AND receive

Section titled “Storage registration (NEP-145) — required to send AND receive”

A NEP-141 token only moves between accounts that are storage-registered on that token (storage_deposit, ≈ 0.00125 NEAR once per account+token). For the exact rail that means both the buyer (sender) and payTo (recipient) must be registered on the token, or the ft_transfer panics. Check the recipient with planPayment() / recipientReady() (planPayment() surfaces the RECIPIENT_NOT_READY blocker; recipientReady() returns the NOT_REGISTERED reason) before you rely on the rail. Register out of band once; it persists.