{"_id":"@airwallet-ai/airwallet-sdk","name":"@airwallet-ai/airwallet-sdk","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@airwallet-ai/airwallet-sdk","version":"0.1.0","private":false,"description":"SDK for publisher websites to interact with the AirWallet extension","type":"module","main":"dist/index.cjs","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js","require":"./dist/react.cjs"},"./next":{"types":"./dist/next.d.ts","import":"./dist/next.js","require":"./dist/next.cjs"},"./express":{"types":"./dist/express.d.ts","import":"./dist/express.js","require":"./dist/express.cjs"},"./dist/index.global.js":"./dist/index.global.js"},"dependencies":{"x402":"^0.6.6","x402-fetch":"^0.6.6"},"devDependencies":{"@types/express":"^4.17.21","@types/node":"24.0.10","@types/react":"19.1.2","@types/react-dom":"19.1.2","@typescript-eslint/eslint-plugin":"8.33.1","@typescript-eslint/parser":"8.33.1","eslint":"^8.57.1","eslint-plugin-import":"2.31.0","eslint-plugin-prettier":"^5.2.1","fdir":"^6.1.0","globby":"^14.0.1","rimraf":"^5.0.0","tsup":"^8.5.1","typescript":"^5.4.5","vitest":"^1.5.0","@airwallet/tsconfig":"0.1.0"},"publishConfig":{"access":"public"},"msw":{"workerDirectory":["apps/admin-portal/public"]},"scripts":{"lint":"eslint . --ext ts,tsx","build":"tsc --build && tsup src/index.ts src/types.ts src/react.tsx src/next.ts src/express.ts --format esm,cjs --sourcemap --out-dir dist --external react,react-dom,express && tsup src/legacy-sdk.ts --format iife --global-name AirWalletSDK --out-dir dist --minify && mv dist/legacy-sdk.global.js dist/index.global.js","dev":"tsup src/index.ts src/types.ts src/react.tsx --format esm,cjs,iife --global-name AirWalletSDK --out-file dist/index.global.js --watch --sourcemap","test":"vitest run","test:watch":"vitest watch","coverage":"vitest run --coverage","typecheck":"tsc --noEmit","clean":"rm -rf dist && rm -rf node_modules && rm -rf .turbo","dev:complete":"echo \"No dev:complete command needed for this package\""},"_id":"@airwallet-ai/airwallet-sdk@0.1.0","_integrity":"sha512-jFmY0Z2yVACoYYF4rbgGUp8SGhWhvHK6XHS6RBDQ68b5WCqvtOTO7goTgCNf0/gKPnkbKMpE6rw3vMjjsJV/cw==","_resolved":"/private/var/folders/xr/7qf2jv454lzcvd3j7hjsj6q00000gn/T/a41d1c70507c3af0b22602caae8acae2/airwallet-ai-airwallet-sdk-0.1.0.tgz","_from":"file:airwallet-ai-airwallet-sdk-0.1.0.tgz","_nodeVersion":"22.17.1","_npmVersion":"11.6.2","dist":{"integrity":"sha512-jFmY0Z2yVACoYYF4rbgGUp8SGhWhvHK6XHS6RBDQ68b5WCqvtOTO7goTgCNf0/gKPnkbKMpE6rw3vMjjsJV/cw==","shasum":"60e3c767f93d9ff9bc52c8a592ea8bcd03941bb4","tarball":"https://registry.npmjs.org/@airwallet-ai/airwallet-sdk/-/airwallet-sdk-0.1.0.tgz","fileCount":50,"unpackedSize":1310879,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCqy4wkZYTL0J1T5+AXBRAdhoUsJ9DZilobK9t31hgYUQIgRIB7bGL32hD5fOXZvWG0KRL2OAN3WSzcLXBerHlaPu4="}]},"_npmUser":{"name":"airwallet-ai","email":"brsrao@gmail.com"},"directories":{},"maintainers":[{"name":"airwallet-ai","email":"brsrao@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/airwallet-sdk_0.1.0_1772154089895_0.37604056287786114"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-27T01:01:29.770Z","0.1.0":"2026-02-27T01:01:30.140Z","modified":"2026-02-27T01:01:30.356Z"},"maintainers":[{"name":"airwallet-ai","email":"brsrao@gmail.com"}],"description":"SDK for publisher websites to interact with the AirWallet extension","readme":"# AirWallet SDK (`@airwallet-ai/airwallet-sdk`)\n\n**Last Updated:** 2025-11-02 (ERC-8004 trust + agent endpoints)\n\n## QA & Release Checklist\n\n- Run repository-level gates to exercise SDK journeys (`@developer`, `@extension`, `@payments-analytics` suites):\n\n  ```bash\n  pnpm quality:gates\n  ```\n\n- Publish observability bundles (captures Playwright traces, API contracts, perf snapshots):\n\n  ```bash\n  pnpm observability:publish\n  ```\n\n## Overview\n\nThe AirWallet SDK now ships with a modular architecture centered around a configurable `createAirWalletClient()` factory and a legacy-compatible `AirWalletSDK` class. The new client separates capability detection, transport selection, UI callbacks, and telemetry so you can embed AirWallet flows in browsers, hybrid apps, or custom runtimes with finer control.\n\n> Note: `createAirWalletClient()` + `createPaidRouteHandler()` (Next.js) are the current recommended integration path. The legacy `AirWalletSDK` wrapper exists for backwards compatibility only.\n\n## Features\n\n- Detect AirWallet extension capabilities (EIP-1193 provider, postMessage transport).\n- Configure UI callbacks for extension-missing, pending, and completion states.\n- Select the optimal transport (provider or messaging) automatically, with graceful fallbacks.\n- Fetch programmatic payments with typed Coinbase X402 helpers (`fetchWithPayment`, selector overrides, mock requirements) on Base/USDC.\n- Discover monetized X402 resources with built-in pagination and network filters.\n- Query ERC-8004 registry data via `createAgentClient()` (trust scores, claims, attestations).\n- Publish and manage creator endpoints via `createCreatorClient()` (dynamic pricing + trust metadata).\n- Emit unlock events and telemetry signals for observability.\n\n## Installation\n\nInstall the package using your preferred package manager:\n\n```bash\n# Using pnpm (recommended for this monorepo)\npnpm add @airwallet-ai/airwallet-sdk\n\n# Using npm\nnpm install @airwallet-ai/airwallet-sdk\n\n# Using yarn\nyarn add @airwallet-ai/airwallet-sdk\n```\n\n## Configuration & Initialization\n\n### Option 1: New client factory (recommended)\n\n```typescript\nimport {\n  createAirWalletClient,\n  type SdkConfig,\n  type UnlockRequest,\n} from \"@airwallet-ai/airwallet-sdk\";\n\nconst client = createAirWalletClient({\n  publisher: { id: \"YOUR_PUBLISHER_ID\" },\n  environment: {\n    apiBaseUrl: \"https://api.airwallet.ai\",\n  },\n  ui: {\n    onExtensionMissing: ({ publisher }) => {\n      console.warn(\"Extension missing for\", publisher.id);\n    },\n    onPaymentPending: ({ contentId }) => {\n      console.log(\"Payment pending for\", contentId);\n    },\n    onPaymentComplete: ({ contentId, transactionId }) => {\n      console.log(\"Payment complete\", contentId, transactionId);\n    },\n  },\n});\n\nconst request: UnlockRequest = {\n  contentId: \"demo-article\",\n  price: { amount: 0.25, currency: \"USD\" },\n  metadata: { title: \"Premium Article\" },\n};\n\nawait client.unlock(request);\n```\n\n### Handling X402-protected APIs\n\nThe client now includes first-class helpers for Coinbase X402 flows. Configure the wallet signer and optional per-environment defaults:\n\n```ts\nimport { createAirWalletClient } from \"@airwallet-ai/airwallet-sdk\";\nimport { privateKeyToAccount } from \"viem/accounts\";\n\nconst wallet = privateKeyToAccount(\"0xYOUR_SIGNER_PRIVATE_KEY\");\n\nconst client = createAirWalletClient({\n  publisher: {\n    id: \"YOUR_PUBLISHER_ID\",\n    accessToken: process.env.AIRWALLET_PUBLISHER_TOKEN,\n  },\n  environment: {\n    apiBaseUrl: \"http://127.0.0.1:5180\",\n    x402: {\n      maxUsdCents: 10, // defaults to $0.10 in base units\n      defaultTimeoutMs: 15_000,\n      preferredNetworks: [\"base\"],\n      discoveryOrigin: \"https://airwallet.ai\",\n    },\n  },\n  x402: {\n    wallet,\n    // Optional: customize payment requirements selection\n    paymentRequirementsSelector: (requirements, networkHint) => {\n      return (\n        requirements.find((req) => req.network === networkHint) ??\n        requirements[0]\n      );\n    },\n    // Optional: provide pre-built requirements during tests\n    mockPaymentRequirements: [\n      {\n        scheme: \"exact\",\n        network: \"base\",\n        asset: \"usdc\",\n        maxAmountRequired: \"0.001\",\n        resource: \"https://api.airwallet.ai/api/monetized/echo\",\n        description: \"Mock pay-per-request endpoint\",\n        mimeType: \"application/json\",\n        payTo: \"0x0000000000000000000000000000000000000000\",\n        maxTimeoutSeconds: 30,\n      },\n    ],\n    disableAutoPay: false,\n    strictErrors: true,\n  },\n});\n\nconst response = await client.fetchWithPayment(\n  \"http://127.0.0.1:5180/api/monetized/echo?q=demo\",\n);\nconst payload = client.decodePaymentResponse(\n  response.headers.get(\"x-payment-response\") ?? \"\",\n);\n\nconsole.log(await response.json());\nconsole.log(\"Payment receipt\", payload);\n```\n\nThe helper automatically:\n\n- Retries the request when a `402 Payment Required` response is returned.\n- Verifies the payment amount is within the configured `maxUsdCents` threshold (converted to Base USDC units).\n- Applies the configured timeout via an `AbortController` to avoid hanging fetches.\n- Surfaces typed `AirWalletError` codes (`X402_PAYMENT_REQUIRED`, `X402_PAYMENT_LIMIT_EXCEEDED`, `X402_PAYMENT_FAILED`).\n\nIf no wallet client is supplied, `fetchWithPayment` will throw `X402_PAYMENT_FAILED` so you can render fallback UX.\n\n> Receipts: The decoded `X-PAYMENT-RESPONSE` mirrors server-side entries used to power the user receipts/library. Store this response if you need local audit trails; the server already records a canonical copy.\n\n### Next.js Paid Route Handlers\n\nFor sellers creating paid API endpoints, the SDK provides `createPaidRouteHandler()` for Next.js App Router:\n\n```typescript\n// app/api/paid/echo/route.ts\nimport { createPaidRouteHandler } from \"@airwallet-ai/airwallet-sdk\";\n\nexport const GET = createPaidRouteHandler(\n  {\n    price: \"$0.001\",\n    description: \"Echo service - pay per request\",\n    onEvent: (event) => console.log(`[x402] ${event.type}`),\n  },\n  async (req) => {\n    const url = new URL(req.url);\n    return Response.json({ echo: url.searchParams.get(\"q\") ?? \"ok\" });\n  },\n);\n```\n\n**Network defaults:**\n\n- In development, the paid route defaults to `base-sepolia`.\n- In production, it defaults to `base`.\n- Override with `X402_NETWORK=base` (or `base-sepolia`) or pass `network` explicitly.\n\n**Options:**\n\n- `price`: Price in `\"$0.01\"`, `\"0.01 USD\"`, or numeric format\n- `network`: `\"base\"` or `\"base-sepolia\"`\n- `description`: Shown in 402 challenge\n- `onEvent`: Callback for telemetry events\n\n**Bypass for development:**\n\n```bash\ncurl -H \"x-airwallet-bypass: true\" http://localhost:3000/api/paid/echo\n```\n\nSee [apps/template-paid-api](../../apps/template-paid-api/README.md) for a complete example.\n\n#### Discovery helper\n\nYou can fetch available X402-protected resources by origin, network, and kind:\n\n```ts\nconst resources = await client.discoverResources({\n  origin: \"https://api.airwallet.ai\",\n  kinds: [\"http\"],\n  network: \"base\",\n  limit: 25,\n});\n\nconsole.table(\n  resources.map((item) => ({\n    resource: item.resource,\n    network: item.accepts[0]?.network,\n    amount: item.accepts[0]?.maxAmountRequired,\n  })),\n);\n```\n\nWhen `environment.x402.discoveryOrigin` is provided, it becomes the default for subsequent calls, and `preferredNetworks` are forwarded to the selector. Discovery is sourced from Coinbase's x402 Bazaar and curated by AirWallet.\n\n### Agent registry client (ERC-8004)\n\n```ts\nimport { createAgentClient } from \"@airwallet-ai/airwallet-sdk\";\n\nconst agents = createAgentClient({\n  environment: { apiBaseUrl: \"http://127.0.0.1:5180\" },\n});\n\nconst list = await agents.listAgents({ query: \"search-term\", limit: 20 });\nconst detail = await agents.getAgentDetails(list[0].id);\n\nawait agents.submitAttestation(detail.agent.id, {\n  outcome: \"SUCCESS\",\n  confidence: 0.9,\n  metadata: { latencyMs: 350 },\n});\n```\n\n- Each agent response includes trust scores (latest window), verification markers, and published endpoints.\n- Attestation payloads map directly to `/api/agents/:id/attest` and are signed server-side when required.\n\n### Creator endpoints client\n\n```ts\nimport { createCreatorClient } from \"@airwallet-ai/airwallet-sdk\";\n\nconst creators = createCreatorClient({\n  environment: { apiBaseUrl: \"http://127.0.0.1:5180\" },\n  auth: { token: \"creator-session-token\" },\n});\n\nconst endpoints = await creators.listEndpoints(\"creator-id\", { limit: 10 });\n\nconst created = await creators.createEndpoint(\"creator-id\", {\n  contentId: \"demo-content\",\n  url: \"https://api.example.com/agents/demo\",\n  description: \"Premium agent endpoint\",\n  pricingPolicyId: \"policy-id\",\n});\n\nawait creators.updateEndpoint(\"creator-id\", created.id, {\n  description: \"Updated description\",\n  status: \"ACTIVE\",\n});\n```\n\n- The client manages pricing policy wiring, trust metadata, and SLO overrides.\n- Requires authenticated creator token; fetch via the user portal or the new `/api/auth` flows.\n\n## Telemetry & Correlation\n\nYou can enable lightweight tracing and consistent correlation IDs across SDK operations (manifest, ledger, attestation, unlock fallback):\n\n```ts\nimport { createAirWalletClient } from \"@airwallet-ai/airwallet-sdk\";\n\nconst tracer = {\n  startSpan: (name: string, attributes?: Record<string, unknown>) => {\n    // connect to your observability tool here\n    return {\n      end: () => {},\n      setAttribute: () => {},\n      recordException: () => {},\n    };\n  },\n};\n\nconst client = createAirWalletClient({\n  publisher: { id: \"YOUR_PUBLISHER_ID\", accessToken: \"<token>\" },\n  environment: { apiBaseUrl: \"http://127.0.0.1:5180\" },\n  telemetry: {\n    tracer,\n    correlationIdFactory: () => `site-${Date.now()}`,\n  },\n});\n\n// SDK will attach X-Correlation-Id and X-Trace-Id per request\nawait client.getPolicyManifest();\nawait client.getLedgerEntries();\nawait client.attestPolicyOutcome({\n  outcome: \"approved\",\n  manifest: {\n    version: 1,\n    signature: \"sig\",\n    issuedAt: \"now\",\n    expiresAt: \"later\",\n  },\n});\n```\n\n## Capability Ping\n\nDetect the preferred transport quickly, without initiating an unlock flow:\n\n```ts\nconst status = await client.ping();\n// status.transport is one of: \"provider\" | \"message\" | \"none\"\n// status.providerDetected, status.hasMessaging booleans available\n```\n\n## Retries & Backoff\n\nThe client will retry transient HTTP failures (5xx/429) for manifest and ledger requests using exponential backoff. Configure via `SdkConfig.retry`:\n\n```ts\nconst client = createAirWalletClient({\n  publisher: { id: \"YOUR_PUBLISHER_ID\", accessToken: \"<token>\" },\n  environment: { apiBaseUrl: \"https://api.airwallet.ai\" },\n  retry: {\n    requestMaxAttempts: 3, // default 3\n    requestBackoffMs: 200, // default 200ms per attempt (exponential)\n  },\n});\n```\n\n### Fallback behavior (BYO wallet / no extension)\n\nWhen neither transport is available, `createAirWalletClient()` triggers the `ui.onExtensionMissing` callback, emits an `extension_missing` event, and (for the legacy wrapper) renders a modal prompting users to install the extension. Both the client and legacy wrapper throw an `AirWalletError` with code `EXTENSION_NOT_FOUND` so you can render custom UX.\n\n### Migration guide\n\n1. Replace direct `AirWalletSDK` usage with `createAirWalletClient()` to gain access to events, telemetry, and custom UI callbacks.\n2. Configure your signer/provider to use Base USDC (e.g., viem wallet client or injected EIP-1193 provider). The AirWallet browser extension is optional; any EIP‑1193 wallet is supported.\n3. Update unlock calls to pass the new `UnlockRequest` shape (`price: { amount, currency }`).\n4. Handle the new unlock events (`extension_missing`, `payment_pending`, `payment_complete`) emitted via the returned client.\n5. Remove manual `window.postMessage` mocks; the SDK now encapsulates transport selection for you.\n\n## Development\n\n### Testing\n\nRun the Vitest suite for this package:\n\n```bash\npnpm --filter @airwallet-ai/airwallet-sdk test\n```\n\nTests cover the legacy wrapper, capability detection, and transport fallbacks. Add new cases under `packages/airwallet-sdk/tests/` following the existing patterns.\n\n## Building\n\nThe package is bundled via `tsup` (ESM/CJS/IIFE) with types emitted by the compiler. Run `pnpm build` to generate updated artifacts before publishing.\n\n## Security Notes\n\n- Your `publisherId` is used for identification with AirWallet systems.\n- The SDK communicates with the AirWallet browser extension via `window.postMessage`.\n\n## License\n\nThis package is part of the AirWallet project and is subject to the project's proprietary license. See the [LICENSE](../../LICENSE) file in the root directory for details.\n\n## Wallet Strategy & Providers\n\nAirWallet is moving to an open X402-first model where users can bring their own wallet. The SDK does not ship a custodial wallet. Instead, you should detect an existing EIP-1193 provider (MetaMask, Coinbase Wallet, Phantom, Rainbow, etc.) and pass a configured signer or provider into the client. The AirWallet browser extension remains optional and provides policy controls, spend limits, and history, but is not required for X402 payments.\n\n### Recommended defaults\n\n- **Network:** Base (`base`, `base-sepolia` for testing)\n- **Asset:** USDC\n- **Preferred providers:** any injected EIP-1193 wallet with `eth_signTypedData_v4` support\n- **SDK signer:** supply a viem-compatible account or `walletClient`\n\n```ts\nimport { createWalletClient, custom } from \"viem\";\nimport { base } from \"viem/chains\";\n\nconst walletClient = createWalletClient({\n  chain: base,\n  transport: custom(window.ethereum!),\n});\n\nconst client = createAirWalletClient({\n  publisher: { id: \"demo-publisher\" },\n  environment: {\n    apiBaseUrl: \"https://api.airwallet.ai\",\n    x402: {\n      preferredNetworks: [\"base\"],\n      discoveryOrigin: \"https://airwallet.ai\",\n    },\n  },\n  x402: {\n    wallet: walletClient,\n    disableAutoPay: true,\n  },\n  ui: {\n    onExtensionMissing: () => {\n      console.warn(\n        \"No AirWallet extension detected. Continuing with BYO wallet.\",\n      );\n    },\n  },\n});\n```\n\nIf you need to support both the AirWallet extension and third-party wallets, detect the extension via `client.ping()` and fall back to `window.ethereum` when the extension is not connected.\n","readmeFilename":"README.md","_rev":"1-27bd178f663880b1ddd75fefcca44afe"}