{"_id":"@arch-network/wallet-connect-kit","_rev":"2-40509dc7426f83dc02788960c09919bf","name":"@arch-network/wallet-connect-kit","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.0":{"name":"@arch-network/wallet-connect-kit","version":"0.1.0","keywords":["arch-network","wallet","wallet-connect","bitcoin","bip322","lasereyes","react"],"license":"MIT","_id":"@arch-network/wallet-connect-kit@0.1.0","maintainers":[{"name":"hoffmabc","email":"brian@ob1.io"},{"name":"0xfinetuned","email":"amine@arch.network"},{"name":"jsblair9","email":"james@lionsmouth.digital"}],"homepage":"https://github.com/Arch-Network/arch-wallet-connect-kit#readme","bugs":{"url":"https://github.com/Arch-Network/arch-wallet-connect-kit/issues"},"dist":{"shasum":"33ed70a08a6e557f64c22250a2c8f03e91de4a84","tarball":"https://registry.npmjs.org/@arch-network/wallet-connect-kit/-/wallet-connect-kit-0.1.0.tgz","fileCount":64,"integrity":"sha512-o2u5hmLcEXywaPh/CEfjw4po2mCcyPc9xjFUHK8IxDrgZEMvMTuRbPVfzbbpbuefvTHaAgx2mwXc+o58P975eg==","signatures":[{"sig":"MEQCIE9zqcJyH4/CWDFHnwH82KOzVeN56U6b+hCENRbEU0fZAiAyK78nDU+chyISLLptf2G6Pmo+LNGo8bN7tczSxYCmuQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":220430},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./styles.css":"./styles.css"},"gitHead":"f13527d8da86ac11f1db1040dabc593587d9ef10","scripts":{"test":"vitest run","build":"tsc -p tsconfig.build.json","typecheck":"tsc --noEmit","prepublishOnly":"pnpm typecheck && pnpm test && pnpm build"},"_npmUser":{"name":"jsblair9","email":"james@lionsmouth.digital"},"repository":{"url":"git+https://github.com/Arch-Network/arch-wallet-connect-kit.git","type":"git"},"_npmVersion":"11.16.0","description":"Wallet connect SDK for Arch Network apps: Bitcoin wallets (via LaserEyes), the Arch Wallet extension, and Turnkey Wallet Hub passkey/email wallets — headless core, React hooks, and a themeable connect modal.","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.18.0","dependencies":{"buffer":"^6.0.3","zustand":"^5.0.8","bip322-js":"^3.0.0","@turnkey/http":"^4.0.0","bitcoinjs-lib":"^7.0.1","@turnkey/crypto":"^2.9.0","@turnkey/sdk-browser":"^6.0.0","@saturnbtcio/bip322-js":"^3.0.1","@turnkey/api-key-stamper":"^0.6.6"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.12.4","devDependencies":{"jsdom":"^22.1.0","react":"19.2.3","vitest":"^3.2.4","react-dom":"19.2.3","typescript":"^5.9.3","@types/react":"^19.0.0","@types/react-dom":"^19.0.0","@omnisat/lasereyes":"^0.0.162","@testing-library/react":"^16.1.0"},"peerDependencies":{"react":">=18","react-dom":">=18","@omnisat/lasereyes":"^0.0.162"},"_npmOperationalInternal":{"tmp":"tmp/wallet-connect-kit_0.1.0_1785937601625_0.3492224941873705","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@arch-network/wallet-connect-kit","version":"0.1.1","description":"Wallet connect SDK for Arch Network apps: Bitcoin wallets (via LaserEyes), the Arch Wallet extension, and Turnkey Wallet Hub passkey/email wallets — headless core, React hooks, and a themeable connect modal.","license":"MIT","type":"module","repository":{"type":"git","url":"git+https://github.com/Arch-Network/arch-wallet-connect-kit.git"},"homepage":"https://github.com/Arch-Network/arch-wallet-connect-kit#readme","bugs":{"url":"https://github.com/Arch-Network/arch-wallet-connect-kit/issues"},"publishConfig":{"access":"public"},"keywords":["arch-network","wallet","wallet-connect","bitcoin","bip322","lasereyes","react"],"sideEffects":["*.css"],"main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./styles.css":"./styles.css"},"scripts":{"build":"tsc -p tsconfig.build.json","prepublishOnly":"pnpm typecheck && pnpm test && pnpm build","typecheck":"tsc --noEmit","test":"vitest run"},"packageManager":"pnpm@10.12.4","peerDependencies":{"@omnisat/lasereyes":"^0.0.162","react":">=18","react-dom":">=18"},"dependencies":{"@saturnbtcio/bip322-js":"^3.0.1","@turnkey/api-key-stamper":"^0.6.6","@turnkey/crypto":"^2.9.0","@turnkey/http":"^4.0.0","@turnkey/sdk-browser":"^6.0.0","bip322-js":"^3.0.0","bitcoinjs-lib":"^7.0.1","buffer":"^6.0.3","zustand":"^5.0.8"},"devDependencies":{"@omnisat/lasereyes":"^0.0.162","@testing-library/react":"^16.1.0","@types/react":"^19.0.0","@types/react-dom":"^19.0.0","jsdom":"^22.1.0","react":"19.2.3","react-dom":"19.2.3","typescript":"^5.9.3","vitest":"^3.2.4"},"gitHead":"ad82ec81a27b16368fef4c77820a2d2bc652a021","_id":"@arch-network/wallet-connect-kit@0.1.1","_nodeVersion":"22.23.1","_npmVersion":"12.0.2","dist":{"integrity":"sha512-kIWCnRaPBrL4NYoF9A5PkwqVdSP+r6DwTHhGHbL/JbCYFNl/IydUxrHjriJVTb7hfJVISUtl2617CUM1HQ+EZg==","shasum":"371a8504620de7cf30fca2ee4f34e30cde2c40a7","tarball":"https://registry.npmjs.org/@arch-network/wallet-connect-kit/-/wallet-connect-kit-0.1.1.tgz","fileCount":64,"unpackedSize":226764,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@arch-network%2fwallet-connect-kit@0.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIGlkPS8jfeqzWbYxfttVc6ylaU5D1JK0+I9Iws1E3fLVAiB+cTaJinbdFan5CTDDJr3015yvR14959ZwzUW8Z2BSvQ=="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:09c33f04-a097-497b-b86b-a8c40b236bb4"}},"directories":{},"maintainers":[{"name":"hoffmabc","email":"brian@ob1.io"},{"name":"0xfinetuned","email":"amine@arch.network"},{"name":"jsblair9","email":"james@lionsmouth.digital"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/wallet-connect-kit_0.1.1_1785943368991_0.262986416417226"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-05T13:46:41.400Z","modified":"2026-08-05T15:22:49.508Z","0.1.0":"2026-08-05T13:46:41.778Z","0.1.1":"2026-08-05T15:22:49.129Z"},"bugs":{"url":"https://github.com/Arch-Network/arch-wallet-connect-kit/issues"},"license":"MIT","homepage":"https://github.com/Arch-Network/arch-wallet-connect-kit#readme","keywords":["arch-network","wallet","wallet-connect","bitcoin","bip322","lasereyes","react"],"repository":{"type":"git","url":"git+https://github.com/Arch-Network/arch-wallet-connect-kit.git"},"description":"Wallet connect SDK for Arch Network apps: Bitcoin wallets (via LaserEyes), the Arch Wallet extension, and Turnkey Wallet Hub passkey/email wallets — headless core, React hooks, and a themeable connect modal.","maintainers":[{"name":"hoffmabc","email":"brian@ob1.io"},{"name":"0xfinetuned","email":"amine@arch.network"},{"name":"jsblair9","email":"james@lionsmouth.digital"}],"readme":"# @arch-network/wallet-connect-kit\n\n[![npm](https://img.shields.io/npm/v/%40arch-network%2Fwallet-connect-kit)](https://www.npmjs.com/package/@arch-network/wallet-connect-kit)\n\nWallet connect SDK for [Arch Network](https://arch.network) dApps. Drop in a\nconnect button and modal, get back a connected wallet identity and a signer —\nfor every wallet type Arch users have:\n\n- **Bitcoin extension wallets** via [LaserEyes](https://github.com/omnisat/lasereyes) — Xverse, Phantom, UniSat, Leather (incl. silent session restore, network-switch settling, and the per-wallet signing quirks).\n- **Arch Wallet browser extension** (`window.arch`) with its Arch-native digest signer.\n- **Turnkey Wallet Hub** passkey + email (OTP) wallets, signing client-side.\n\nShips in three layers — use as much as you need:\n\n| Layer | What you get |\n|---|---|\n| Headless core | Connect flows, identity derivation (`pubkeyXCoord`, base58 arch address), network guard, storage, signers, a vanilla zustand store |\n| React | `ArchWalletKitProvider`, `useWallet`, `useWalletSigner`, `useWalletHubAccount` |\n| UI | `WalletConnectModal` (picker / email + OTP / connecting / connected / install views) and `ConnectWalletButton`, themeable via CSS variables |\n\nA runnable consumer lives in [`examples/vite-react`](examples/vite-react).\n\n## Requirements\n\n- React 18+ and a bundler (Next.js, Vite, …). `dist/` uses extensionless\n  relative imports and is not consumable by plain Node ESM.\n- On **Vite**: add\n  [`vite-plugin-node-polyfills`](https://www.npmjs.com/package/vite-plugin-node-polyfills)\n  — transitive deps of the bip322 stack import node builtins (`crypto`,\n  `stream`, `events`). Next.js ships fallbacks for these out of the box. See\n  [`examples/vite-react/vite.config.ts`](examples/vite-react/vite.config.ts).\n\n## Setup\n\n**1. Install** the package and its peers:\n\n```bash\npnpm add @arch-network/wallet-connect-kit @omnisat/lasereyes react react-dom\n# or: npm install / yarn add — same packages\n```\n\nInstalls from the public [npm registry](https://www.npmjs.com/package/@arch-network/wallet-connect-kit).\nReleases are also mirrored to GitHub Packages (see the sidebar), but npmjs is\ncanonical — GitHub Packages requires a GitHub token even for public installs.\n\n> `@omnisat/lasereyes` must be a single instance shared with your app, which\n> is why it's a peer. The range pins `0.0.162`: the kit's Xverse/UniSat\n> signing workarounds are coded against that release's adapter bugs — bump it\n> deliberately, not automatically.\n\n**2. Copy the wallet icons** from this repo's [`assets/`](./assets) into your\napp's `public/` directory (`/arch-icon.jpeg`, `/xverse-logo.png`,\n`/phantom-icon.svg`, `/unisat-logo.png`, `/leather-icon.svg`). (Or skip this\nand pass your own `archWallet` / `otherWallets` descriptors to the modal.)\n\n**3. Mount the provider, button, and modal** — this is the whole integration:\n\n```tsx\n\"use client\"; // Next.js app router only\n\nimport {\n  ArchWalletKitProvider,\n  ConnectWalletButton,\n  WalletConnectModal,\n  type WalletKitConfig,\n} from \"@arch-network/wallet-connect-kit\";\nimport \"@arch-network/wallet-connect-kit/styles.css\";\n\nconst config: WalletKitConfig = {\n  network: \"testnet4\", // \"mainnet\" | \"testnet\" | \"testnet4\" | \"regtest\"\n  appName: \"My Arch App\",\n};\n\nexport function App({ children }: { children: React.ReactNode }) {\n  return (\n    <ArchWalletKitProvider config={config}>\n      <ConnectWalletButton />\n      {children}\n      <WalletConnectModal />\n    </ArchWalletKitProvider>\n  );\n}\n```\n\nThe provider owns session restore (silent reconnect on page load) and modal\nstate; the button and modal wire themselves from context. There is nothing\nelse to wire.\n\n**4. Read the connection** anywhere under the provider:\n\n```tsx\nimport { useWallet } from \"@arch-network/wallet-connect-kit\";\n\nfunction Balance() {\n  const { wallet } = useWallet();\n  if (!wallet) return <p>Not connected</p>;\n  return <p>{wallet.archAddress}</p>;\n}\n```\n\n`useWallet()` returns:\n\n| Field | What it is |\n|---|---|\n| `wallet` | `WalletState \\| null` — address, pubkey, `pubkeyXCoord`, `archAddress`, balances |\n| `connectionPhase` / `connectionError` | Connect-flow progress and failure copy |\n| `openConnectModal()` / `handleDisconnect()` | Open the picker / tear down the session |\n| `handleConnect(walletId, options?)` | Start a connect flow imperatively |\n| `repairOnboarding()` | Re-run your `onboard` hook without disconnecting — surface it when a transaction fails with an account-not-ready error |\n| `laserEyes`, `detectedWallets`, `showConnect`, … | Lower-level state for custom UIs |\n\n**5. Sign** with the active wallet:\n\n```tsx\nimport { useWalletSigner } from \"@arch-network/wallet-connect-kit\";\n\nconst signer = useWalletSigner(); // ChallengeSigner | DigestSigner\nconst signature =\n  typeof signer === \"function\"\n    ? await signer(challenge)          // BIP-322 challenge signer\n    : await signer.signDigest(digestHex); // digest signer (Arch ext, Turnkey)\n```\n\nAll wallet types produce signatures your transaction runner can treat\nidentically (BIP-322 witness / raw 64-byte Schnorr shapes). Outside React,\nuse `resolveActiveTransactionSigner(...)`.\n\n## Configuration reference\n\n```ts\nconst config: WalletKitConfig = {\n  // Required. A network name, or the full triple\n  // { bitcoinNetwork, xverseNetworkType, networkId } when the derived\n  // Xverse network.type / Hub x-network values don't fit your deployment.\n  network: \"testnet4\",\n\n  // Optional — names the app in passkey prompts and Hub wallet labels.\n  appName: \"My Arch App\", // default \"Arch\"\n\n  // Optional — prefix for every localStorage/sessionStorage key.\n  storagePrefix: \"myapp\", // default \"arch\"\n\n  // Optional — Turnkey Wallet Hub endpoint (see \"Wallet Hub\" below).\n  hub: { baseUrl: \"/api/wallet-hub\", apiKey: undefined },\n\n  // Optional — console diagnostics, filterable with \"[WalletConnect]\".\n  debug: false,\n\n  // Optional host hooks — see \"Host hooks\" below.\n  onboard: async ({ identity, signer, onPhase }) => {},\n  fetchBalances: async (identity) => ({ balances: {}, totalUsdValue: null }),\n};\n```\n\nThe config is captured once on mount. To switch networks, remount the\nprovider (`key={network}`) or reload the page — per-network derived state is\nnot valid across networks.\n\n## Host hooks\n\nThe kit owns *connecting*; your app owns *what happens on-chain afterwards*:\n\n- **`onboard({ identity, signer, onPhase })`** — run post-connect provisioning\n  (e.g. Arch `create_account` + associated token accounts). Report progress via\n  `onPhase(\"checking-account\" | \"creating-account\" | …)` and the modal renders\n  stage copy for each step. Throwing aborts the connect and tears down partial\n  state. Omit it and connect finishes after identity validation.\n- **`fetchBalances(identity)`** — return the initial\n  `{ balances, totalUsdValue }` snapshot committed with the wallet. Omit it and\n  the wallet connects with empty balances; keep your own polling layer updating\n  `walletKitStore` afterwards.\n\n## Wallet Hub (passkey / email wallets)\n\n- `hub.baseUrl` may be `https://hub.arch.network` or (recommended in\n  browsers) a same-origin proxy that attaches `x-api-key` server-side and\n  avoids CORS.\n- `hub.apiKey` is a public platform gate, not a user credential.\n- The Hub derives wallets on the network named by `network.networkId`\n  (`x-network` header).\n\n### Same-origin proxy (Next.js)\n\nBrowser requests to the hosted Hub with `x-api-key`/`x-network` trigger a CORS\npreflight the Hub doesn't serve on every route. Keep the browser on your\norigin and attach the key server-side:\n\n```ts\n// app/api/wallet-hub/[...path]/route.ts\nimport { NextRequest } from \"next/server\";\n\nconst UPSTREAM = process.env.WALLET_HUB_BASE_URL ?? \"https://hub.arch.network\";\n\nasync function proxy(request: NextRequest, { params }: { params: Promise<{ path?: string[] }> }) {\n  const { path } = await params;\n  const headers = new Headers(request.headers);\n  headers.delete(\"host\");\n  headers.delete(\"connection\");\n  headers.delete(\"content-length\");\n  if (process.env.WALLET_HUB_API_KEY) headers.set(\"x-api-key\", process.env.WALLET_HUB_API_KEY);\n  // Trust the client's x-network (the kit always sends it); default otherwise.\n  if (!headers.has(\"x-network\")) headers.set(\"x-network\", \"mainnet\");\n\n  const method = request.method.toUpperCase();\n  const upstream = await fetch(\n    `${UPSTREAM.replace(/\\/+$/, \"\")}/${(path ?? []).join(\"/\")}${request.nextUrl.search}`,\n    {\n      method,\n      headers,\n      body: [\"GET\", \"HEAD\"].includes(method) ? undefined : await request.text(),\n      cache: \"no-store\",\n    },\n  );\n  return new Response(upstream.body, { status: upstream.status, headers: upstream.headers });\n}\n\nexport const GET = proxy;\nexport const POST = proxy;\nexport async function OPTIONS() {\n  return new Response(null, { status: 204 });\n}\n```\n\nThen set `hub: { baseUrl: \"/api/wallet-hub\" }` — the kit appends `/v1`\nitself. On Vite, the dev server can do the same with a `server.proxy` entry\n(see the example app).\n\n## Customization\n\n### Theming\n\n- Import `@arch-network/wallet-connect-kit/styles.css` once.\n- Override `--awck-*` CSS variables (`--awck-surface`, `--awck-fg`,\n  `--awck-primary`, `--awck-accent`, …). Dark mode follows\n  `prefers-color-scheme` and can be forced with `data-awck-theme=\"dark\"` on\n  `<html>`.\n\n### Component props\n\nEvery modal/button prop overrides its context default, so partial\ncustomization is a prop away:\n\n```tsx\n<WalletConnectModal\n  network={{ label: \"Testnet4\", tone: \"test\", onSwitch: flipNetwork }}\n  explorerAccountUrl={(arch) => `https://explorer.arch.network/accounts/${arch}`}\n  archWallet={myArchDescriptor}\n  otherWallets={myWalletList}\n/>\n```\n\nOutside the provider, both components run fully controlled — pass the\ncomplete prop set (they throw a named error if something's missing).\n\n### Picker tags and analytics\n\nThe modal's `recentWalletId` / `connectedWalletId` props and\nconnect/disconnect analytics are host concerns:\n\n```tsx\nimport { getStoredWalletProvider, useWallet, type WalletId } from \"@arch-network/wallet-connect-kit\";\n\nconst LASEREYES_IDS = new Set([\"xverse\", \"phantom\", \"unisat\", \"leather\"]);\n\nfunction asWalletId(value: unknown): WalletId | null {\n  return typeof value === \"string\" && LASEREYES_IDS.has(value)\n    ? (value as WalletId)\n    : null;\n}\n\nfunction AppShell() {\n  const { wallet, laserEyes } = useWallet();\n\n  // \"Recent\" tag in the picker: the last provider we stored.\n  const recentWalletId = asWalletId(getStoredWalletProvider());\n  // Source of truth for the active connection is the live LaserEyes provider;\n  // fall back to the persisted id.\n  const liveProvider = asWalletId(laserEyes.provider);\n  const connectedWalletId = wallet ? (liveProvider ?? recentWalletId) : null;\n\n  // Analytics: watch the wallet transition edges with an effect on `wallet`\n  // and emit your own events.\n\n  return (\n    <WalletConnectModal\n      recentWalletId={recentWalletId}\n      connectedWalletId={connectedWalletId}\n    />\n  );\n}\n```\n\n### Headless usage\n\nEverything the UI does is exported: `runConnectFlow`,\n`runArchExtensionConnectFlow`, `runTurnkeyHubConnectFlow`, the vanilla\n`walletKitStore` (+ selectors), identity/encoding helpers, and the signers.\nBuild your own UI on `useWallet()` — or skip React entirely and drive the\ncore. If you skip `<ArchWalletKitProvider>`, mount `useSyncWalletSession`\nyourself to get silent reconnect.\n\n## Storage\n\nEverything the kit persists is prefixed with `storagePrefix` (default\n`\"arch\"`): `\"<prefix>:last-connected-wallet\"` (localStorage) plus the Turnkey\naccount/session keys (`<prefix>_turnkey_*`). Wallet state itself is\ndeliberately session-only — every page load starts disconnected and\nsilent-reconnects.\n\n## Not included (by design)\n\n- On-chain onboarding and balance/indexer reads — inject via `onboard` /\n  `fetchBalances`.\n- Analytics — observe `walletKitStore` (or `useWallet()`) and emit your own\n  events.\n\n## Development\n\n```bash\npnpm install\npnpm typecheck\npnpm build     # tsc → dist/ (preserves \"use client\" directives)\npnpm test      # vitest\n```\n\nCI runs typecheck + build + test on PRs and `main` pushes. Releases are\nautomated from Conventional Commits — see [RELEASING.md](RELEASING.md).\nEngineering invariants (BIP-322 port, LaserEyes pin, layering rules) live in\n[AGENTS.md](AGENTS.md).\n\n## License\n\n[MIT](LICENSE)\n","readmeFilename":"README.md"}