@aifinpay/agent

中文文档
2.14.1发布于 2026/11/07MITTypeScriptES Module近 30 天下载 4013

AiFinPay SDK for global Agent Passport identity and route-verified AIFP-1/AIFP-2 settlement for autonomous AI agents.

原始使用文档
文档目录15 节
  1. Aptos and NEAR deployment support
  2. Stablecoin-only chains
  3. Link the agent to its owner's dashboard
  4. Install
  5. Quick start
  6. Loading an existing keypair
  7. Inject an external EVM signer
  8. How x402 auth works under the hood
  9. Privacy
  10. License
  11. Payment receipt authorization
  12. A gateway site keeps its merchant
  13. Already paid: Aifp1ActiveReceiptError
  14. Name the AI client that pays
  15. Payment history

@aifinpay/agent (Node / TypeScript)

The signed AIFP-1 fetchPaid flow supports owner-selected v1.4 payment chains. Polygon is the default; select another chain explicitly with v14.chain. Client descriptors are not production approval: payment availability is determined by the installed deployment registry, runtime verification and backend/merchant capabilities. Runtime, signer, token, RPC-chain and current profile checks remain mandatory, along with a durable pre-broadcast journal and explicit native gas budget. Source builds and tests do not establish live payment acceptance.

Native purchases require a fresh independent nativeUsdPrice for POL, ETH, AVAX, BNB or XRP on the selected chain. Stablecoins use an independently pinned token address and decimals. USD micro-units remain unchanged; token_settlement binds exact6/18-decimal token units and every gross-inclusive leg to the signed gross and exact approval.18-decimal tokens require this metadata; legacy6-decimal quotes remain accepted. Inspect current assets through the SDK capability API and installed deployment registry.

maxGasWei covers approval plus settlement. OP chains (Base/Optimism/Unichain) include buffered L1/operator estimates; Nitro (Arbitrum/Robinhood) already includes parent-data gas in the RPC estimate, so it is counted once. Unavailable OP fees block signing. These are preflight estimates, not inclusion-time guarantees. Current admin profiles remain mutable; receipt and recovery policy is unchanged. See payment configuration and recovery.

Aptos and NEAR deployment support

The Node SDK generates typed Aptos and NEAR deployment pins from the installed @aifinpay/deployments package. Wallet derivation and Agent Passport already provide identifiers for both families. Select deployment metadata explicitly:

import { getAptosDeployment, getNearDeployment, resolveAptosDeployment } from "@aifinpay/agent";

const aptos = getAptosDeployment({ environment: "prod", network: "mainnet" });
const near = getNearDeployment({ environment: "dev", network: "testnet" });
// Selection additionally requires settlementEnabled in the packaged record.
const selected = resolveAptosDeployment({ environment: "prod", network: "mainnet", version: "v1.4" });

get*Deployment permits read-only inspection of disabled records. resolveAptosDeployment and resolveNearDeployment reject disabled records, unknown networks, environment mismatches, and unsupported versions; no legacy fallback or default network is selected. Aptos pins include module hashes, the referenced ABI digest, and per-network source provenance. NEAR pins include the account and WASM hash; council membership is not treated as governance authority. See the Aptos and NEAR registry guides.

Payment execution is not implemented for Aptos or NEAR. These resolvers read packaged metadata, not current chain state. Neither family is an EVM v14.chain, and fetchPaid cannot sign or settle their payments. Executable support requires backend quote/receipt contracts, independently verified runtime/profile checks, chain-specific signing, fee caps, and durable recovery; a registry flag or payout address does not supply these.

Stablecoin-only chains

On a stablecoinOnly chain (Arc) the gas token is the pinned stablecoin itself: set v14.asset to it, maxGasWei is in its 18-decimal native units, and gas and the gross are checked against one balance. A testnet chain accepts only network_mode: "test" quotes. On a noNativePayment chain (BOT Chain) the native token pays gas only and has no price, so v14.asset must name its pinned stablecoin.

The solanaV14 option provides owner-selected paid access for SOL and classic SPL assets. Network and environment, local Ed25519 payer, independently sourced SOL/USD and maxFeeLamports (transaction fees plus all nonce/ATA rent) are separate from EVM options. v14 and solanaV14 together are rejected. Availability is checked against the installed deployment registry and runtime/backend policy; application configuration cannot override an unavailable route.

The exact 216-byte quote and 297-byte instruction follow the packaged pinned IDL. Fresh genesis/config/profile/mint/nonce/account evidence and unsigned final-message simulation precede budget reservation and local signing. Signed bytes are saved before the single send. Unknown signature outcomes never expire or authorize a replacement transaction. A canonical finalized failure retains only its proven fee debit; missing proof retains the full reservation. Public history/quota select Solana cluster explicitly and never expose bearer receipts.

At https://dash.aifinpay.io → My Agents → Add agent by address the owner gets a challenge. Sign it and hand back the signature:

const signature = await agent.signDashboardClaim(challenge);

signDashboardClaim signs only AiFinPay-claim:polygon:<this address>:<nonce> and refuses any other text. The owner then sees the agent's balance, payments and receipts.

The accepted v1.4 contract model allows administrators to change profile fees and treasury. Preflight verifies current values; it does not make them immutable. See receipt configuration and recovery.

Non-custodial payment client for autonomous AI agents on AiFinPay. AIFP-1 is gross-inclusive: payer total equals the quote, merchant receives 99%, AiFinPay receives 1%, creator/referral receives 0%. AIFP-2/x402 currently charges 0% at the protocol layer. Legacy /api/b2b split-invoice methods are retired. The v1.3 executor checks the independently supplied deployment/runtime pin, chain, fee profile, merchant target and asset. A matching runtime value alone is not production approval; use the installed registry, capability APIs, executor tests and CI as evidence, and do not bypass runtime checks.

The Ed25519 keypair is generated locally with tweetnacl and never leaves your process. The SDK only sends a one-time SHA-256 + Ed25519 signature in the x-signature header to authenticate against AiFinPay-protected endpoints.

Install

Install the published stable package:

npm install @aifinpay/agent

Or build this source checkout:

# From the SDK repository root
cd node
npm ci --no-audit --no-fund
npm run build
npm pack

Install the resulting tarball in your application:

npm install /absolute/path/to/sdk/node/aifinpay-agent-<version>.tgz

Quick start

Load the wallet you already configured before sharing a deposit address:

import { AiFinPayAgent } from "@aifinpay/agent";

const agent = await AiFinPayAgent.fromEnvironment();
console.log({ evm: agent.evmAddress, solana: agent.solanaAddress });

fromEnvironment() is a load-only Node API. It selects one identity in this order, matching MCP:

  1. SEED_HASH: a 32-byte seed encoded as 64 hex characters, optionally 0x prefixed.
  2. ./aifinpay/agents.json relative to the process working directory. Set AIFINPAY_AGENTS_FILE for another path and AIFINPAY_AGENT_ID when selecting from multiple records ({"agents":[{"id":"crawler","seed_hash":"…"}]}).
  3. AIFINPAY_AGENT_SECRET: an existing base58 Solana secret.
  4. ~/.aifinpay/agent.json, or AIFINPAY_HOME/agent.json: the existing MCP keystore. Encrypted keystores require AIFINPAY_WALLET_PASSPHRASE.

The loader never creates or overwrites a wallet, prints its keys, or calls the network. Missing configuration, an invalid seed, an ambiguous project file or a decryption failure throws instead of selecting a new wallet. Load any .env through your runtime before calling it; this API reads process.env and does not read .env files. SEED_HEX is not an alias for SEED_HASH. Keep private inputs and wallet files out of chats, logs and version control.

The same configured inputs restore the same addresses after a process restart. An explicit evmPrivateKey option overrides the derived EVM identity; retain that separate key as well to recover the imported wallet. Loading a wallet does not by itself pay for anything; paid execution goes through fetchPaid and its checks.

AiFinPayAgent.fromSeed(seed, { derivationIndex }) deterministically selects a child wallet. Each chain uses its own versioned domain, followed by the decimal UTF-8 index after the domain's NUL separator and then the recovery seed. Omitting derivationIndex preserves existing addresses.

AiFinPayAgent.new() and Agent.new() intentionally create a fresh ephemeral wallet each time. They do not load existing environment variables or keystores and do not persist their generated keys. Use them only when you deliberately need a new identity and will store its recovery material privately before funding it. Never rerun new() to recover an existing funded address.

Loading an existing keypair

import { Agent } from "@aifinpay/agent";

// from solana-keygen JSON file (Node only)
const agent = await Agent.fromKeypairFile("./agent-wallet.json");

// from base58 secret string (works in browser too)
const agent2 = Agent.fromSecretB58("3RvZm7Gw...");

Inject an external EVM signer

Agent.new() and AiFinPayAgent.fromSeed() derive the EVM identity from the agent seed. To keep the key outside the SDK — an in-house signer, a hardware-backed key, or a future vendor adapter — inject any wallet matching the AgentWallet interface via evmWallet (any viem LocalAccount qualifies structurally):

import { Agent, evmPrivateKeyWallet } from "@aifinpay/agent";

// self-custodial default: the same key `evmPrivateKey` builds internally
const agent = Agent.new({ evmWallet: evmPrivateKeyWallet("0x…") });

Two zero-dependency adapters cover the rest of the wallet market through the same interface:

import { eip1193Wallet, viemWalletClientWallet } from "@aifinpay/agent";

// MetaMask and any generic EVM browser wallet (async: reads the address
// via eth_requestAccounts)
const injected = Agent.new({ evmWallet: await eip1193Wallet(window.ethereum) });

// Privy, Crossmint, ZeroDev, Coinbase Smart Wallet, custom transports —
// anything that hands out a viem WalletClient with an account
const embedded = Agent.new({ evmWallet: viemWalletClientWallet(walletClient) });

Server-side vendor SDKs (Coinbase CDP server wallets, Circle) are out of scope: they need vendor API credentials, which the SDK must not hold.

AgentWallet is address plus signMessage/signTypedData; it is sufficient for message-based x402 authorization. AiFinPayAgent also accepts evmWalletClient for EVM on-chain flows, using that exact viem client for signing. Its account must be a viem LocalAccount with signTransaction: v1.4 signs and journals exact raw bytes before the SDK broadcasts them through the independently selected chain RPC for recovery. JSON-RPC/send-only and smart-account clients are refused for this flow. The client must be configured for the selected chain. This option cannot be combined with evmWallet or evmPrivateKey. The MCP programmatic integration uses the same option; its local identity continues to provide Solana identity and signing.

How x402 auth works under the hood

Agent.pay(url) (and get/post/request) handles an AiFinPay-native 402 with request-bound auth (version 2). For a gated request the SDK:

  1. sends the request without credentials; the 402 body carries a one-time x-nonce, its expiry x-nonce-expires-at, x-aifinpay-auth-version: 2 and the SHA-256 of the request body it was issued for;
  2. refuses to sign unless the request went to the origin configured as the agent's baseUrl, the response came from that origin, and the body digest matches the body it sent;
  3. signs, with Ed25519, the SHA-256 of JSON.stringify(["AiFinPay-x402", "v2", nonce, pubkey, origin, METHOD, path+query, bodySha256, expiresAt]) and base58-encodes the signature;
  4. retries the original request with headers:
    • x-agent-pubkey: <base58 pubkey>
    • x-nonce: <nonce>
    • x-signature: <base58 sig>
    • x-aifinpay-auth-version: 2

The server verifies the signature, consumes the nonce, checks the agent has a live Seat PDA on-chain, and serves the resource. The retired v1 format (GET /nonce, SHA-256("AiFinPay-x402:{nonce}:{pubkey}")) is refused, and Agent.authHeaders() throws.

Privacy

  • The server never sees your private key. Period.
  • Nonces are consumed on use; replay-resistant.
  • Payments settle on public chains — the explicitly selected EVM network — and are visible on-chain.

License

MIT.

Payment receipt authorization

AIFP-1 receipts use the paying wallet signature. See authorize and recover payment receipts for retries and recovery without a second transfer.

A gateway site keeps its merchant

fetchPaid pins each gateway site (https://gateway.aifinpay.io/<slug>) to the merchant it was first paid as, before any money moves. A later 402 that names another merchant for the same site throws Aifp1MerchantChangedError (code: "AIFP1_MERCHANT_CHANGED") before anything is quoted. If the change is legitimate, say so for that call; paying re-pins the site:

await agent.fetchPaid(url, {}, { allowMerchantChange: true });
// or name the merchant you trust; any other one is refused:
await agent.fetchPaid(url, {}, { expectedMerchantId: "mrch_…" });

Pins are one file per site under ~/.aifinpay/merchant-pins (or AIFINPAY_STATE_DIR), so they survive restarts; pass merchantPins to the agent to keep them elsewhere. An unreadable pin refuses payment rather than pinning afresh. resourcePathMode: "direct" is not pinned, because its cache key already names the merchant. A slug the gateway retired answers 410 gateway_retired, which throws Aifp1GatewayRetiredError (code: "AIFP1_GATEWAY_RETIRED") after one request; do not retry it. Batches already held are kept.

Already paid: Aifp1ActiveReceiptError

Within a minute of a settled purchase, /v1/quote answers the same payer and resource with the existing receipt instead of a quote, so a retry cannot buy twice. A process that holds no receipt for it (a new process, or one whose fetchPaid failed after paying) gets Aifp1ActiveReceiptError (code: "AIFP1_ACTIVE_RECEIPT", a subclass of Aifp1QuoteError). Nothing was quoted or paid. It names receiptId, txRef, chain, merchantId, resource and settledAt; recover that receipt from the recovery your onPrepared saved for txRef:

try {
  return await agent.fetchPaid(url, {}, opts);
} catch (e) {
  if (!(e instanceof Aifp1ActiveReceiptError)) throw e;
  const paid = await agent.recoverPaidPayment(savedRecoveryFor(e.txRef));
  return fetch(url, { headers: { "AIFP-Receipt": paid.receipt } });
}

Do not retry fetchPaid to get past it: once the minute is over a new quote is a new purchase. With no saved recovery for txRef the receipt cannot be reissued; buying again is a new payment and the owner's decision.

Name the AI client that pays

Set framework to the AI client the agent runs in, and every request of the payment flow carries AIFP-Agent-Framework: <value>: the first request that may answer 402, /v1/quote, /v1/pay and the paid retry (and the generic x402 pay()). The merchant dashboard then shows which AI client paid.

const agent = await AiFinPayAgent.fromEnvironment({ framework: "claude" });

Accepted values (AGENT_FRAMEWORKS): chatgpt, claude, perplexity, gemini, cursor, openai-agents, windsurf, codex, custom. Anything else throws AiFinPayError when the agent is constructed. Leave it unset and no header is sent; the SDK never guesses. A host that learns its client after constructing the agent passes it per call: fetchPaid(url, init, { framework }) or recoverPaidPayment(recovery, { framework }).

Payment history

import { getAgentHistory } from "@aifinpay/agent";
const history = await getAgentHistory({ address: "0x…", source: "transactions" });
// Or { passport: 'AIFP-000000042', network: 'polygon', source: 'receipts' }

transactions covers indexed AiFinPay Polygon settlements, not arbitrary wallet transfers. receipts covers retained prepaid batches, including test payments. Follow next_offset with limit/offset. A passport requires a backend with the verified-wallet resolver deployed; passing both address and passport checks their match. Never pass a holder private key or API secret as an identifier. Public history does not return bearer receipt tokens.

版本与发布记录

@aifinpay/agent 共发布 53 个版本,首次发布于 2026/05/08;过去 12 个月发布了 53 个版本。

版本发布日期距今
2.14.1latest2026/11/07今天
2.14.02026/11/062 天前
2.12.32026/11/025 天前
2.12.12026/11/025 天前
2.11.22026/11/016 天前
2.11.12026/10/318 天前

其他发布通道:next → 2.0.0-rc.13。

关于 @aifinpay/agent 的常见问题

@aifinpay/agent 是什么?

AiFinPay SDK for global Agent Passport identity and route-verified AIFP-1/AIFP-2 settlement for autonomous AI agents.

如何安装 @aifinpay/agent?

在项目目录运行 npm install @aifinpay/agent,或使用 pnpm add / yarn add / bun add。

@aifinpay/agent 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@aifinpay/agent 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@aifinpay/agent 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@aifinpay/agent 可以商用吗?

@aifinpay/agent 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@aifinpay/agent 的下载量有多少?

根据 npm 官方下载统计,@aifinpay/agent 在 2026/10/05 – 2026/11/03 这 30 天内被下载 4,013 次,日均约 134 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@aifinpay/agent 还在维护吗?

最新版本 2.14.1 发布于 2026/11/07(今天);至今共发布 53 个版本,其中过去 12 个月发布了 53 个;首次发布于 2026/05/08。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。