From 2da50b854d14ec8fc0f629a5b6d389cda14f5753 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Thu, 2 Apr 2026 10:02:09 -0300 Subject: [PATCH 01/37] feat: x402 payment protocol POC for Hathor Network Implements the x402 protocol (HTTP 402 + nano contract escrow) as a proof of concept. Includes: - X402Escrow nano contract blueprint (Python 3.11) - Facilitator server with /x402/verify and /x402/settle endpoints - Resource server with x402 middleware (weather API demo) - Client script demonstrating the full payment flow - Dockerfile for containerized deployment Tested end-to-end on Hathor Forge localnet: buyer deposits HTR into escrow, resource server verifies via facilitator, serves data, then facilitator releases funds to seller. Co-Authored-By: Claude Opus 4.6 (1M context) --- .env.example | 27 ++ .gitignore | 4 + Dockerfile | 14 + LICENSE | 21 + README.md | 306 +++++++++++++- blueprint/x402_escrow.py | 85 ++++ client.js | 123 ++++++ config.js | 34 ++ facilitator.js | 111 +++++ helpers.js | 49 +++ package-lock.json | 870 +++++++++++++++++++++++++++++++++++++++ package.json | 22 + resource-server.js | 125 ++++++ 13 files changed, 1790 insertions(+), 1 deletion(-) create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 LICENSE create mode 100644 blueprint/x402_escrow.py create mode 100644 client.js create mode 100644 config.js create mode 100644 facilitator.js create mode 100644 helpers.js create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 resource-server.js diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..ceb3062 --- /dev/null +++ b/.env.example @@ -0,0 +1,27 @@ +# Hathor services +FULLNODE_URL=http://127.0.0.1:8080 +WALLET_HEADLESS_URL=http://localhost:8000 + +# X402Escrow blueprint ID (published on-chain) +BLUEPRINT_ID= + +# Wallet IDs (must exist in wallet-headless) +BUYER_WALLET_ID=buyer +FACILITATOR_WALLET_ID=facilitator +SELLER_WALLET_ID=seller + +# Wallet addresses +BUYER_ADDRESS= +FACILITATOR_ADDRESS= +SELLER_ADDRESS= + +# Token +TOKEN_UID=00 + +# Ports +FACILITATOR_PORT=8402 +RESOURCE_SERVER_PORT=3000 + +# Escrow settings +ESCROW_DEADLINE_SECONDS=300 +PAYMENT_AMOUNT=100 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8a433ab --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +*.log +.env +.DS_Store diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..95b6a94 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,14 @@ +FROM node:22-alpine + +WORKDIR /app + +COPY package.json package-lock.json ./ +RUN npm ci --production + +COPY *.js ./ +COPY blueprint/ ./blueprint/ + +EXPOSE 8402 3000 + +# Default: run the facilitator. Override CMD for other components. +CMD ["node", "facilitator.js"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..231ccf2 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Hathor Network + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 790c76a..58396ce 100644 --- a/README.md +++ b/README.md @@ -2,4 +2,308 @@ > Machines paying machines. HTTP 402 meets nano contract escrow. -See the [x402 RFC](https://github.com/HathorNetwork/rfcs/blob/feat/x402-support/projects/x402/0001-x402-support.md) for the full protocol design. +This is a proof-of-concept implementation of the [x402 protocol](https://www.x402.org/) on [Hathor Network](https://hathor.network/). It enables pay-per-request HTTP APIs settled natively on Hathor's DAG-based L1 blockchain using **nano contract escrow** — no pre-signed transactions, no double-spend risk, no trust required. + +## How It Works + +``` + x402 Payment Flow + + CLIENT (AI agent) RESOURCE SERVER FACILITATOR HATHOR + ───────────────── ─────────────── ─────────── ────── + │ │ │ │ + 1. │── GET /weather ──────────▶ │ │ │ + │ │ │ │ + 2. │◀── 402 Payment Required ── │ │ │ + │ {scheme, amount, │ │ │ + │ seller, facilitator, │ │ │ + │ blueprintId} │ │ │ + │ │ │ │ + 3. │── create escrow ──────────────────────────────────────────────────────────▶ │ + │ (deposit 1 HTR) │ │ LOCKED │ + │◀── ncId ──────────────────────────────────────────────────────────────────── │ + │ │ │ │ + 4. │── GET /weather ──────────▶ │ │ │ + │ + X-Payment {ncId} │ │ │ + │ │── POST /x402/verify ────▶ │ │ + │ │ │── query state ─────▶│ + │ │ │◀── {LOCKED, 100} ── │ + │ │◀── {valid: true} ──────── │ │ + │ │ │ │ + 5. │◀── 200 + weather data ──── │ │ │ + │ │ │ │ + 6. │ │── POST /x402/settle ────▶ │ │ + │ │ │── release() ───────▶│ + │ │ │ (withdraw to seller)│ + │ │ │◀── txId ─────────── │ + │ │◀── {success, txId} ────── │ RELEASED│ + │ │ │ │ +``` + +### The Three Components + +**1. Facilitator** (`facilitator.js` — port 8402) + +The trusted intermediary that verifies payments and triggers settlement. It exposes two endpoints: + +- `POST /x402/verify` — Queries the nano contract state on the Hathor full node. Checks that the escrow is `LOCKED`, the amount is sufficient, the seller address matches, and the facilitator address matches. Returns `{valid: true}` or `{valid: false, invalidReason: "..."}`. +- `POST /x402/settle` — Calls `release()` on the escrow contract, which withdraws the escrowed funds to the seller's address. Returns the settlement transaction ID. + +The facilitator needs its own funded wallet to sign `release()` transactions. + +**2. Resource Server** (`resource-server.js` — port 3000) + +Any HTTP server that sells access to a resource. This POC sells weather data for 1 HTR per request. The x402 middleware: + +1. If no `X-Payment` header → returns **402** with payment requirements (scheme, amount, seller, facilitator, blueprint ID) +2. If `X-Payment` present → calls the facilitator to **verify** the escrow +3. If valid → serves the resource, then asks the facilitator to **settle** (async) + +**3. Client** (`client.js`) + +An AI agent / script that wants to access a paid resource. The flow: + +1. Makes a regular HTTP request → gets **402 Payment Required** +2. Parses the payment requirements from the 402 response +3. Creates an **X402Escrow nano contract** on Hathor — deposits the required amount +4. Retries the request with the `X-Payment` header containing the `ncId` +5. Receives the resource + +## The X402Escrow Blueprint + +The heart of the system is a [Hathor nano contract](https://hathor.network/resources/nano-contracts/) deployed on-chain. It implements a simple three-phase escrow: + +``` + ┌─────────────────────┐ + │ │ + initialize() │ LOCKED │ + + deposit ───────▶│ │ + │ funds held in │ + │ contract on-chain │ + │ │ + └──────┬────────┬─────┘ + │ │ + release() │ │ refund() + by facilitator│ │ by buyer/facilitator + withdraw to │ │ or anyone after deadline + seller │ │ withdraw to buyer + ▼ ▼ + ┌──────────┐ ┌──────────┐ + │ RELEASED │ │ REFUNDED │ + └──────────┘ └──────────┘ +``` + +**Key properties:** +- **Zero double-spend risk** — funds are locked on-chain, not in a pre-signed transaction +- **Built-in refunds** — buyer can cancel anytime; anyone can refund after the deadline (dead man's switch) +- **Trustless verification** — anyone can query the contract state on a public full node +- **One escrow per payment** — clean isolation, each `ncId` is a receipt + +The blueprint source is in [`blueprint/x402_escrow.py`](blueprint/x402_escrow.py). + +## Why Nano Contracts (Not Pre-Signed Transactions) + +The naive approach for UTXO chains is pre-signed transactions — the client signs a transaction offline and hands it to the facilitator. But this has a fundamental flaw: **the client can double-spend the UTXOs before the facilitator submits**. + +| | Pre-Signed TX | Nano Contract Escrow | +| ------------------ | --------------------------------------- | ------------------------------------------- | +| Double-spend risk | **High** — client can spend UTXOs | **Zero** — funds locked on-chain | +| Verification | Off-chain signature check | **On-chain state query** — trustless | +| Refund on timeout | Impossible without timelock hacks | **Built-in** — contract refunds | +| Trust model | Must trust facilitator won't hold tx | **Trustless** — contract enforces rules | + +## Quick Start with Hathor Forge + +The fastest way to run this POC is with [Hathor Forge](https://github.com/HathorNetwork/hathor-forge), which spins up a local Hathor blockchain with all services. + +### Prerequisites + +- Node.js 18+ +- [Hathor Forge](https://github.com/HathorNetwork/hathor-forge) installed + +### 1. Start Hathor Forge + +```bash +hathor-forge-cli --start +``` + +This starts a local full node, miner, tx-mining service, and wallet-headless. + +### 2. Create and fund wallets + +Using the Hathor Forge MCP tools or CLI: + +```bash +# Create wallets +hathor-forge create-wallet buyer +hathor-forge create-wallet facilitator +hathor-forge create-wallet seller + +# Fund the buyer (needs HTR to pay for resources) +hathor-forge fund-wallet buyer --amount 100 + +# Fund the facilitator (needs HTR for tx fees on release/refund) +hathor-forge fund-wallet facilitator --amount 10 +``` + +### 3. Publish the X402Escrow blueprint + +```bash +hathor-forge publish-blueprint facilitator --code blueprint/x402_escrow.py +``` + +Note the returned `blueprint_id`. + +### 4. Configure + +```bash +cp .env.example .env +# Edit .env with your values: +# FULLNODE_URL, WALLET_HEADLESS_URL (from hathor-forge) +# BLUEPRINT_ID (from step 3) +# BUYER_ADDRESS, FACILITATOR_ADDRESS, SELLER_ADDRESS (from wallet creation) +``` + +### 5. Install and run + +```bash +npm install + +# Terminal 1: Start the facilitator +node facilitator.js + +# Terminal 2: Start the resource server +node resource-server.js + +# Terminal 3: Run the client +node client.js +``` + +### Expected output + +``` +[CLIENT] === x402 Payment Flow Demo === +[CLIENT] Step 1: Requesting weather data... +[CLIENT] Got 402 Payment Required +[CLIENT] Amount: 100 cents (1 HTR) +[CLIENT] Pay to: WZe3ty22NNua6N6BWRPXFqfmcTJyr2zrdq +[CLIENT] +[CLIENT] Step 2: Creating escrow nano contract... +[CLIENT] Escrow created! ncId=00000832e422... +[CLIENT] Escrow tx confirmed on-chain +[CLIENT] +[CLIENT] Step 3: Retrying request with payment proof... +[CLIENT] +[CLIENT] === Resource Received! === +[CLIENT] { + "location": "Sao Paulo, Brazil", + "temperature": 28, + "humidity": 65, + "condition": "Partly cloudy" +} +[CLIENT] +[CLIENT] === x402 Payment Flow Complete === +``` + +On the facilitator side: + +``` +[FACILITATOR] Verify request for ncId=00000832e422... +[FACILITATOR] Verification PASSED +[FACILITATOR] Settle request for ncId=00000832e422... +[FACILITATOR] Calling release() — withdrawing 100 to seller WZe3ty22... +[FACILITATOR] Settlement SUCCESS — txId=0000286c14be... +``` + +## Docker + +```bash +# Build +docker build -t x402-poc . + +# Run facilitator +docker run -p 8402:8402 --env-file .env x402-poc + +# Run resource server +docker run -p 3000:3000 --env-file .env x402-poc node resource-server.js + +# Run client +docker run --env-file .env x402-poc node client.js +``` + +## Protocol Messages + +### 402 Response (Server -> Client) + +```json +{ + "accepts": [{ + "scheme": "hathor-escrow", + "network": "hathor:privatenet", + "maxAmountRequired": "100", + "payTo": "WZe3ty22...", + "tokenUid": "00", + "extra": { + "facilitatorUrl": "http://localhost:8402", + "facilitatorAddress": "WcwKaUE5...", + "blueprintId": "00000022..." + } + }] +} +``` + +### X-Payment Header (Client -> Server) + +```json +{ + "scheme": "hathor-escrow", + "network": "hathor:privatenet", + "payload": { + "ncId": "00000832...", + "depositTxId": "00000832...", + "buyerAddress": "Wk1PQJJk..." + } +} +``` + +### Verify / Settle (Server -> Facilitator) + +See [`facilitator.js`](facilitator.js) for the full request/response formats. + +## Project Structure + +``` +x402-poc/ +├── blueprint/ +│ └── x402_escrow.py # Nano contract blueprint (Python 3.11) +├── facilitator.js # Facilitator server (:8402) +├── resource-server.js # Example paid API (:3000) +├── client.js # AI agent / buyer script +├── config.js # Shared configuration (env vars) +├── helpers.js # Shared HTTP helpers +├── Dockerfile # Container image +├── .env.example # Environment template +└── package.json +``` + +## What's Next + +This is a POC. A production implementation would include: + +- **`@hathor/x402-client`** — TypeScript SDK wrapping the client flow +- **`@hathor/x402-server`** — Express/Fastify middleware (one-liner to add x402 to any API) +- **Facilitator as headless plugin** — Runs inside `hathor-wallet-headless` process, not as a standalone server +- **Refund monitor** — Background job watching for expired escrows +- **Payment channels** — Pre-funded escrows for repeat clients (lower latency) +- **Explorer integration** — X402Escrow detection and dashboard in hathor-explorer + +## References + +- [x402 Protocol Specification](https://www.x402.org/) +- [Hathor Nano Contracts](https://hathor.network/resources/nano-contracts/) +- [RFC: x402 Support for Hathor Network](https://github.com/HathorNetwork/rfcs/blob/feat/x402-support/projects/x402/0001-x402-support.md) +- [Hathor Forge](https://github.com/HathorNetwork/hathor-forge) — Local development environment + +## License + +MIT diff --git a/blueprint/x402_escrow.py b/blueprint/x402_escrow.py new file mode 100644 index 0000000..860d927 --- /dev/null +++ b/blueprint/x402_escrow.py @@ -0,0 +1,85 @@ +from hathor import ( + Address, Amount, Blueprint, Context, NCDepositAction, NCFail, + NCWithdrawalAction, Timestamp, TokenUid, export, public, view +) + +PHASE_LOCKED = 'LOCKED' +PHASE_RELEASED = 'RELEASED' +PHASE_REFUNDED = 'REFUNDED' + + +@export +class X402Escrow(Blueprint): + buyer: Address + seller: Address + facilitator: Address + token_uid: TokenUid + amount: Amount + phase: str + deadline: Timestamp + resource_url: str + request_hash: str + + @public(allow_deposit=True) + def initialize( + self, + ctx: Context, + seller: Address, + facilitator: Address, + token_uid: TokenUid, + deadline: Timestamp, + resource_url: str, + request_hash: str, + ) -> None: + action = ctx.get_single_action(token_uid) + if not isinstance(action, NCDepositAction): + raise NCFail("Must include a deposit action") + + self.buyer = ctx.get_caller_address() + self.seller = seller + self.facilitator = facilitator + self.token_uid = token_uid + self.amount = action.amount + self.phase = PHASE_LOCKED + self.deadline = deadline + self.resource_url = resource_url + self.request_hash = request_hash + + @public(allow_withdrawal=True) + def release(self, ctx: Context) -> None: + caller = ctx.get_caller_address() + if caller != self.facilitator: + raise NCFail("Only the facilitator can release funds") + if self.phase != PHASE_LOCKED: + raise NCFail("Escrow is not locked") + + action = ctx.get_single_action(self.token_uid) + if not isinstance(action, NCWithdrawalAction): + raise NCFail("Must include a withdrawal action") + if action.amount != self.amount: + raise NCFail("Withdrawal amount must equal escrow amount") + + self.phase = PHASE_RELEASED + + @public(allow_withdrawal=True) + def refund(self, ctx: Context) -> None: + caller = ctx.get_caller_address() + + if self.phase != PHASE_LOCKED: + raise NCFail("Escrow is not locked") + + if caller != self.buyer and caller != self.facilitator: + if ctx.block.timestamp < self.deadline: + raise NCFail("Only buyer or facilitator can refund before deadline") + + action = ctx.get_single_action(self.token_uid) + if not isinstance(action, NCWithdrawalAction): + raise NCFail("Must include a withdrawal action") + if action.amount != self.amount: + raise NCFail("Withdrawal amount must equal escrow amount") + + self.phase = PHASE_REFUNDED + + @view + def get_phase(self) -> str: + return self.phase diff --git a/client.js b/client.js new file mode 100644 index 0000000..9896c2a --- /dev/null +++ b/client.js @@ -0,0 +1,123 @@ +// x402 Client (Buyer / AI Agent) +// Demonstrates the full x402 payment flow: +// 1. Request resource -> get 402 +// 2. Create escrow nano contract (deposit funds) +// 3. Retry request with payment proof +// 4. Receive resource + +const fetch = require('node-fetch'); +const config = require('./config'); +const { walletRequest, waitForTxConfirmation, log } = require('./helpers'); + +async function main() { + log('CLIENT', '=== x402 Payment Flow Demo ==='); + log('CLIENT', `Buyer address: ${config.buyerAddress}`); + log('CLIENT', ''); + + // Step 1: Request the paid resource (expect 402) + log('CLIENT', 'Step 1: Requesting weather data...'); + const initialResp = await fetch(`http://localhost:${config.resourceServerPort}/weather`); + const statusCode = initialResp.status; + + if (statusCode !== 402) { + log('CLIENT', `Expected 402 but got ${statusCode}`); + process.exit(1); + } + + const paymentRequired = await initialResp.json(); + log('CLIENT', `Got 402 Payment Required`); + + const requirements = paymentRequired.accepts[0]; + log('CLIENT', ` Scheme: ${requirements.scheme}`); + log('CLIENT', ` Amount: ${requirements.maxAmountRequired} cents (${parseInt(requirements.maxAmountRequired) / 100} HTR)`); + log('CLIENT', ` Pay to: ${requirements.payTo}`); + log('CLIENT', ` Facilitator: ${requirements.extra.facilitatorAddress}`); + log('CLIENT', ` Blueprint: ${requirements.extra.blueprintId}`); + log('CLIENT', ''); + + // Step 2: Create escrow nano contract (deposit funds) + log('CLIENT', 'Step 2: Creating escrow nano contract...'); + + const deadline = Math.floor(Date.now() / 1000) + requirements.extra.deadlineSeconds; + const amount = parseInt(requirements.maxAmountRequired); + const resourceUrl = requirements.resource; + + const createResult = await walletRequest('POST', '/wallet/nano-contracts/create', { + blueprint_id: requirements.extra.blueprintId, + address: config.buyerAddress, + data: { + args: [ + requirements.payTo, // seller + requirements.extra.facilitatorAddress, // facilitator + requirements.tokenUid, // token_uid + deadline, // deadline + resourceUrl, // resource_url + 'poc-request-hash', // request_hash + ], + actions: [{ + type: 'deposit', + token: requirements.tokenUid, + amount: amount, + }], + }, + }, config.buyerWalletId); + + if (!createResult.success) { + log('CLIENT', `Failed to create escrow: ${JSON.stringify(createResult)}`); + process.exit(1); + } + + const ncId = createResult.hash; + log('CLIENT', `Escrow created! ncId=${ncId}`); + log('CLIENT', 'Waiting for tx confirmation...'); + + await waitForTxConfirmation(ncId); + log('CLIENT', 'Escrow tx confirmed on-chain'); + log('CLIENT', ''); + + // Step 3: Retry request with payment proof + log('CLIENT', 'Step 3: Retrying request with payment proof...'); + + const paymentPayload = { + scheme: 'hathor-escrow', + network: 'hathor:privatenet', + payload: { + ncId: ncId, + depositTxId: ncId, + buyerAddress: config.buyerAddress, + }, + }; + + const paidResp = await fetch(`http://localhost:${config.resourceServerPort}/weather`, { + headers: { + 'X-Payment': JSON.stringify(paymentPayload), + }, + }); + + if (paidResp.status !== 200) { + const err = await paidResp.json(); + log('CLIENT', `Payment rejected: ${JSON.stringify(err)}`); + process.exit(1); + } + + const result = await paidResp.json(); + log('CLIENT', ''); + log('CLIENT', '=== Resource Received! ==='); + log('CLIENT', JSON.stringify(result.data, null, 2)); + log('CLIENT', ''); + log('CLIENT', `Payment ncId: ${result.payment.ncId}`); + log('CLIENT', ''); + log('CLIENT', 'Waiting a few seconds for settlement to complete...'); + + // Give the async settlement time to complete + await new Promise(r => setTimeout(r, 15000)); + + log('CLIENT', ''); + log('CLIENT', '=== x402 Payment Flow Complete ==='); +} + +main().catch(err => { + log('CLIENT', `Error: ${err.message}`); + console.error(err); + process.exit(1); +}); diff --git a/config.js b/config.js new file mode 100644 index 0000000..c0124f5 --- /dev/null +++ b/config.js @@ -0,0 +1,34 @@ +// x402 POC Configuration +// Override any value with environment variables + +const env = process.env; + +module.exports = { + // Hathor services + fullnodeUrl: env.FULLNODE_URL || 'http://127.0.0.1:8080', + walletHeadlessUrl: env.WALLET_HEADLESS_URL || 'http://localhost:8000', + + // Blueprint published on-chain + blueprintId: env.BLUEPRINT_ID || '', + + // Wallet IDs (must be pre-created in wallet-headless) + buyerWalletId: env.BUYER_WALLET_ID || 'buyer', + facilitatorWalletId: env.FACILITATOR_WALLET_ID || 'facilitator', + sellerWalletId: env.SELLER_WALLET_ID || 'seller', + + // Addresses (first address of each wallet) + buyerAddress: env.BUYER_ADDRESS || '', + facilitatorAddress: env.FACILITATOR_ADDRESS || '', + sellerAddress: env.SELLER_ADDRESS || '', + + // HTR token UID + htrTokenUid: env.TOKEN_UID || '00', + + // Ports + facilitatorPort: parseInt(env.FACILITATOR_PORT || '8402'), + resourceServerPort: parseInt(env.RESOURCE_SERVER_PORT || '3000'), + + // Escrow settings + escrowDeadlineSeconds: parseInt(env.ESCROW_DEADLINE_SECONDS || '300'), + paymentAmount: parseInt(env.PAYMENT_AMOUNT || '100'), +}; diff --git a/facilitator.js b/facilitator.js new file mode 100644 index 0000000..bcdc155 --- /dev/null +++ b/facilitator.js @@ -0,0 +1,111 @@ +// x402 Facilitator Server +// Exposes /x402/verify and /x402/settle endpoints +// Talks to hathor-forge fullnode for state queries and wallet-headless for settlement + +const express = require('express'); +const config = require('./config'); +const { walletRequest, getNanoContractState, waitForTxConfirmation, log } = require('./helpers'); + +const app = express(); +app.use(express.json()); + +// POST /x402/verify +// Resource server calls this to verify an escrow is valid +app.post('/x402/verify', async (req, res) => { + const { paymentPayload, paymentRequirements } = req.body; + const { ncId } = paymentPayload.payload; + + log('FACILITATOR', `Verify request for ncId=${ncId}`); + + const stateResp = await getNanoContractState(ncId); + if (!stateResp.success) { + return res.json({ valid: false, invalidReason: `Cannot query contract: ${stateResp.message}` }); + } + + const fields = stateResp.fields; + const errors = []; + + if (fields.phase.value !== 'LOCKED') { + errors.push(`phase is ${fields.phase.value}, expected LOCKED`); + } + if (fields.amount.value < parseInt(paymentRequirements.maxAmountRequired)) { + errors.push(`amount ${fields.amount.value} < required ${paymentRequirements.maxAmountRequired}`); + } + if (fields.seller.value !== paymentRequirements.payTo) { + errors.push(`seller ${fields.seller.value} != payTo ${paymentRequirements.payTo}`); + } + if (fields.facilitator.value !== config.facilitatorAddress) { + errors.push(`facilitator ${fields.facilitator.value} != expected ${config.facilitatorAddress}`); + } + + if (errors.length > 0) { + log('FACILITATOR', `Verification FAILED: ${errors.join('; ')}`); + return res.json({ valid: false, invalidReason: errors.join('; ') }); + } + + log('FACILITATOR', `Verification PASSED for ncId=${ncId}`); + res.json({ valid: true }); +}); + +// POST /x402/settle +// Resource server calls this after serving the resource +app.post('/x402/settle', async (req, res) => { + const { ncId } = req.body.paymentPayload.payload; + + log('FACILITATOR', `Settle request for ncId=${ncId}`); + + // Get escrow state to know amount and seller + const stateResp = await getNanoContractState(ncId); + if (!stateResp.success) { + return res.json({ success: false, error: `Cannot query contract: ${stateResp.message}` }); + } + + const fields = stateResp.fields; + if (fields.phase.value !== 'LOCKED') { + return res.json({ success: false, error: `Escrow not locked (phase=${fields.phase.value})` }); + } + + const amount = fields.amount.value; + const seller = fields.seller.value; + const tokenUid = fields.token_uid.value; + + // Execute release() on the nano contract via wallet-headless + log('FACILITATOR', `Calling release() — withdrawing ${amount} to seller ${seller}`); + const result = await walletRequest('POST', '/wallet/nano-contracts/execute', { + nc_id: ncId, + method: 'release', + address: config.facilitatorAddress, + data: { + args: [], + actions: [{ + type: 'withdrawal', + token: tokenUid, + amount: amount, + address: seller, + }], + }, + }, config.facilitatorWalletId); + + if (!result.success) { + log('FACILITATOR', `Settlement FAILED: ${JSON.stringify(result)}`); + return res.json({ success: false, error: result.message || 'release() failed' }); + } + + log('FACILITATOR', `Settlement SUCCESS — txId=${result.hash}`); + + // Wait for the release tx to confirm + await waitForTxConfirmation(result.hash); + log('FACILITATOR', `Release tx confirmed: ${result.hash}`); + + res.json({ + success: true, + txId: result.hash, + network: 'hathor:privatenet', + }); +}); + +app.listen(config.facilitatorPort, () => { + log('FACILITATOR', `x402 Facilitator running on port ${config.facilitatorPort}`); + log('FACILITATOR', `Facilitator address: ${config.facilitatorAddress}`); + log('FACILITATOR', `Blueprint ID: ${config.blueprintId}`); +}); diff --git a/helpers.js b/helpers.js new file mode 100644 index 0000000..47c1320 --- /dev/null +++ b/helpers.js @@ -0,0 +1,49 @@ +// Shared helpers for talking to wallet-headless and fullnode + +const fetch = require('node-fetch'); +const config = require('./config'); + +async function walletRequest(method, path, body, walletId) { + const url = `${config.walletHeadlessUrl}${path}`; + const headers = { 'Content-Type': 'application/json' }; + if (walletId) headers['X-Wallet-Id'] = walletId; + + const opts = { method, headers }; + if (body && method !== 'GET') opts.body = JSON.stringify(body); + + const resp = await fetch(url, opts); + return resp.json(); +} + +async function fullnodeRequest(path) { + const url = `${config.fullnodeUrl}/v1a${path}`; + const resp = await fetch(url); + return resp.json(); +} + +async function getNanoContractState(ncId) { + return fullnodeRequest(`/nano_contract/state?id=${ncId}&fields[]=buyer&fields[]=seller&fields[]=facilitator&fields[]=token_uid&fields[]=amount&fields[]=phase&fields[]=deadline&fields[]=resource_url&fields[]=request_hash&balances[]=00`); +} + +async function waitForTxConfirmation(txId, maxAttempts = 30) { + for (let i = 0; i < maxAttempts; i++) { + const resp = await fullnodeRequest(`/transaction?id=${txId}`); + if (resp.success && resp.tx && resp.meta && resp.meta.first_block) { + return resp; + } + await new Promise(r => setTimeout(r, 1000)); + } + throw new Error(`Transaction ${txId} not confirmed after ${maxAttempts}s`); +} + +function log(component, msg) { + console.log(`[${component}] ${msg}`); +} + +module.exports = { + walletRequest, + fullnodeRequest, + getNanoContractState, + waitForTxConfirmation, + log, +}; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..0830a88 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,870 @@ +{ + "name": "x402-poc", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "x402-poc", + "version": "0.1.0", + "dependencies": { + "express": "^4.21.0", + "node-fetch": "^2.7.0" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/body-parser": { + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", + "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.14.0", + "raw-body": "~2.5.3", + "type-is": "~1.6.18", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", + "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "~1.20.3", + "content-disposition": "~0.5.4", + "content-type": "~1.0.4", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "~0.1.12", + "proxy-addr": "~2.0.7", + "qs": "~6.14.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "~0.19.0", + "serve-static": "~1.16.2", + "setprototypeof": "1.2.0", + "statuses": "~2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/finalhandler": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "statuses": "~2.0.2", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", + "license": "MIT" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/send": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.4.1", + "range-parser": "~1.2.1", + "statuses": "~2.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "~0.19.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..1247d33 --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "name": "x402-poc", + "version": "0.1.0", + "description": "x402 Payment Protocol POC for Hathor Network — Machine-to-machine payments via HTTP 402 + nano contract escrow", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/HathorNetwork/x402-poc.git" + }, + "scripts": { + "facilitator": "node facilitator.js", + "resource-server": "node resource-server.js", + "client": "node client.js" + }, + "dependencies": { + "express": "^4.21.0", + "node-fetch": "^2.7.0" + }, + "engines": { + "node": ">=18" + } +} diff --git a/resource-server.js b/resource-server.js new file mode 100644 index 0000000..beff3e1 --- /dev/null +++ b/resource-server.js @@ -0,0 +1,125 @@ +// x402 Resource Server (Seller) +// A simple API server that sells weather data for 1 HTR per request +// Uses x402 middleware to gate access + +const express = require('express'); +const fetch = require('node-fetch'); +const config = require('./config'); +const { log } = require('./helpers'); + +const app = express(); +app.use(express.json()); + +// x402 middleware — checks for payment, returns 402 if none +function x402Middleware(req, res, next) { + const paymentHeader = req.headers['x-payment']; + + if (!paymentHeader) { + // No payment — return 402 with payment requirements + log('RESOURCE-SERVER', `402 — No payment for ${req.path}`); + return res.status(402).json({ + accepts: [{ + scheme: 'hathor-escrow', + network: 'hathor:privatenet', + maxAmountRequired: String(config.paymentAmount), + resource: `http://localhost:${config.resourceServerPort}${req.path}`, + description: 'Pay 1.00 HTR to access weather data', + mimeType: 'application/json', + payTo: config.sellerAddress, + tokenUid: config.htrTokenUid, + maxTimeoutSeconds: config.escrowDeadlineSeconds, + extra: { + facilitatorUrl: `http://localhost:${config.facilitatorPort}`, + facilitatorAddress: config.facilitatorAddress, + blueprintId: config.blueprintId, + deadlineSeconds: config.escrowDeadlineSeconds, + }, + }], + version: '1', + }); + } + + // Payment present — verify it + const payment = JSON.parse(paymentHeader); + req.x402Payment = payment; + next(); +} + +// Verify payment with facilitator, serve resource, then settle +app.get('/weather', x402Middleware, async (req, res) => { + const payment = req.x402Payment; + const { ncId } = payment.payload; + + log('RESOURCE-SERVER', `Verifying payment ncId=${ncId}`); + + // Step 1: Verify with facilitator + const verifyResp = await fetch(`http://localhost:${config.facilitatorPort}/x402/verify`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + paymentPayload: payment, + paymentRequirements: { + scheme: 'hathor-escrow', + network: 'hathor:privatenet', + maxAmountRequired: String(config.paymentAmount), + payTo: config.sellerAddress, + tokenUid: config.htrTokenUid, + }, + }), + }); + const verification = await verifyResp.json(); + + if (!verification.valid) { + log('RESOURCE-SERVER', `Payment INVALID: ${verification.invalidReason}`); + return res.status(402).json({ error: 'Payment invalid', reason: verification.invalidReason }); + } + + log('RESOURCE-SERVER', `Payment VALID — serving resource`); + + // Step 2: Serve the resource + const weatherData = { + location: 'Sao Paulo, Brazil', + temperature: 28, + humidity: 65, + condition: 'Partly cloudy', + wind: '12 km/h NE', + forecast: 'Warm with chance of afternoon showers', + timestamp: new Date().toISOString(), + }; + + // Step 3: Settle with facilitator (async — don't block response) + log('RESOURCE-SERVER', `Requesting settlement for ncId=${ncId}`); + fetch(`http://localhost:${config.facilitatorPort}/x402/settle`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + paymentPayload: payment, + }), + }) + .then(r => r.json()) + .then(result => { + if (result.success) { + log('RESOURCE-SERVER', `Settlement complete — txId=${result.txId}`); + } else { + log('RESOURCE-SERVER', `Settlement FAILED: ${result.error}`); + } + }) + .catch(err => log('RESOURCE-SERVER', `Settlement error: ${err.message}`)); + + // Return the resource immediately after verification + res.json({ + data: weatherData, + payment: { + success: true, + scheme: 'hathor-escrow', + network: 'hathor:privatenet', + ncId, + }, + }); +}); + +app.listen(config.resourceServerPort, () => { + log('RESOURCE-SERVER', `Weather API running on port ${config.resourceServerPort}`); + log('RESOURCE-SERVER', `Seller address: ${config.sellerAddress}`); + log('RESOURCE-SERVER', `Price: ${config.paymentAmount} cents HTR per request`); +}); From e990b56f87df20abbe3772a6e91cca1651377a00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Thu, 2 Apr 2026 10:31:29 -0300 Subject: [PATCH 02/37] feat: multi-token support and asset field alignment with x402 spec - Rename `tokenUid` to `asset` in all protocol messages per x402 spec - Resource server returns multiple payment options in `accepts` array (HTR + optional custom token like hUSDC) - Facilitator verifies against array of payment requirements, matching the on-chain escrow state to any accepted token - Client supports `--token htr` and `--token custom` flags to choose which token to pay with - Config updated with separate HTR and custom token amount settings - Tested end-to-end with both HTR and a custom hUSDC token Co-Authored-By: Claude Opus 4.6 (1M context) --- .env.example | 10 ++++-- README.md | 56 +++++++++++++++++++++---------- client.js | 82 +++++++++++++++++++++++++++++++--------------- config.js | 10 ++++-- facilitator.js | 59 ++++++++++++++++++++++----------- resource-server.js | 82 +++++++++++++++++++++++++++++++--------------- 6 files changed, 202 insertions(+), 97 deletions(-) diff --git a/.env.example b/.env.example index ceb3062..ee648ee 100644 --- a/.env.example +++ b/.env.example @@ -15,8 +15,9 @@ BUYER_ADDRESS= FACILITATOR_ADDRESS= SELLER_ADDRESS= -# Token -TOKEN_UID=00 +# Custom token UID (optional — leave empty for HTR-only) +# The server will accept both HTR and this token if set +CUSTOM_TOKEN_UID= # Ports FACILITATOR_PORT=8402 @@ -24,4 +25,7 @@ RESOURCE_SERVER_PORT=3000 # Escrow settings ESCROW_DEADLINE_SECONDS=300 -PAYMENT_AMOUNT=100 + +# Payment amounts (in smallest unit — 1 HTR = 100) +HTR_PAYMENT_AMOUNT=100 +CUSTOM_TOKEN_PAYMENT_AMOUNT=1000 diff --git a/README.md b/README.md index 58396ce..b5cd1bd 100644 --- a/README.md +++ b/README.md @@ -46,14 +46,14 @@ This is a proof-of-concept implementation of the [x402 protocol](https://www.x40 The trusted intermediary that verifies payments and triggers settlement. It exposes two endpoints: -- `POST /x402/verify` — Queries the nano contract state on the Hathor full node. Checks that the escrow is `LOCKED`, the amount is sufficient, the seller address matches, and the facilitator address matches. Returns `{valid: true}` or `{valid: false, invalidReason: "..."}`. +- `POST /x402/verify` — Queries the nano contract state on the Hathor full node. Checks that the escrow is `LOCKED`, the amount is sufficient, the seller address matches, the facilitator address matches, and the `token_uid` matches the requested `asset`. Returns `{valid: true}` or `{valid: false, invalidReason: "..."}`. - `POST /x402/settle` — Calls `release()` on the escrow contract, which withdraws the escrowed funds to the seller's address. Returns the settlement transaction ID. The facilitator needs its own funded wallet to sign `release()` transactions. **2. Resource Server** (`resource-server.js` — port 3000) -Any HTTP server that sells access to a resource. This POC sells weather data for 1 HTR per request. The x402 middleware: +Any HTTP server that sells access to a resource. This POC sells weather data and accepts **multiple tokens** — HTR and an optional custom token (e.g. hUSDC). The x402 middleware: 1. If no `X-Payment` header → returns **402** with payment requirements (scheme, amount, seller, facilitator, blueprint ID) 2. If `X-Payment` present → calls the facilitator to **verify** the escrow @@ -63,12 +63,14 @@ Any HTTP server that sells access to a resource. This POC sells weather data for An AI agent / script that wants to access a paid resource. The flow: -1. Makes a regular HTTP request → gets **402 Payment Required** -2. Parses the payment requirements from the 402 response -3. Creates an **X402Escrow nano contract** on Hathor — deposits the required amount +1. Makes a regular HTTP request → gets **402 Payment Required** with one or more payment options +2. **Picks a payment option** from the `accepts` array (by token preference) +3. Creates an **X402Escrow nano contract** on Hathor — deposits the required amount in the chosen token 4. Retries the request with the `X-Payment` header containing the `ncId` 5. Receives the resource +Supports `--token htr` or `--token custom` to choose which token to pay with. + ## The X402Escrow Blueprint The heart of the system is a [Hathor nano contract](https://hathor.network/resources/nano-contracts/) deployed on-chain. It implements a simple three-phase escrow: @@ -98,6 +100,7 @@ The heart of the system is a [Hathor nano contract](https://hathor.network/resou - **Built-in refunds** — buyer can cancel anytime; anyone can refund after the deadline (dead man's switch) - **Trustless verification** — anyone can query the contract state on a public full node - **One escrow per payment** — clean isolation, each `ncId` is a receipt +- **Token-agnostic** — works with HTR or any custom Hathor token (stablecoins, etc.) The blueprint source is in [`blueprint/x402_escrow.py`](blueprint/x402_escrow.py). @@ -175,8 +178,11 @@ node facilitator.js # Terminal 2: Start the resource server node resource-server.js -# Terminal 3: Run the client +# Terminal 3: Run the client (defaults to HTR) node client.js + +# Or pay with a custom token (e.g. hUSDC) +node client.js --token custom ``` ### Expected output @@ -235,23 +241,39 @@ docker run --env-file .env x402-poc node client.js ### 402 Response (Server -> Client) +The `accepts` array can contain **multiple payment options** with different tokens. The client picks whichever it can pay with: + ```json { - "accepts": [{ - "scheme": "hathor-escrow", - "network": "hathor:privatenet", - "maxAmountRequired": "100", - "payTo": "WZe3ty22...", - "tokenUid": "00", - "extra": { - "facilitatorUrl": "http://localhost:8402", - "facilitatorAddress": "WcwKaUE5...", - "blueprintId": "00000022..." + "accepts": [ + { + "scheme": "hathor-escrow", + "network": "hathor:privatenet", + "asset": "00", + "amount": "100", + "description": "Pay 1.00 HTR", + "payTo": "WZe3ty22...", + "extra": { + "facilitatorUrl": "http://localhost:8402", + "facilitatorAddress": "WcwKaUE5...", + "blueprintId": "00000022..." + } + }, + { + "scheme": "hathor-escrow", + "network": "hathor:privatenet", + "asset": "000003e3...", + "amount": "1000", + "description": "Or pay 10.00 hUSDC", + "payTo": "WZe3ty22...", + "extra": { "..." : "..." } } - }] + ] } ``` +> **Note on `asset` field:** Following the x402 spec, the field is called `asset` (not `tokenUid`). For Hathor, the asset value is the token UID — `"00"` for HTR or the hex hash of a custom token. + ### X-Payment Header (Client -> Server) ```json diff --git a/client.js b/client.js index 9896c2a..a73dd9a 100644 --- a/client.js +++ b/client.js @@ -1,14 +1,38 @@ // x402 Client (Buyer / AI Agent) // Demonstrates the full x402 payment flow: // 1. Request resource -> get 402 -// 2. Create escrow nano contract (deposit funds) -// 3. Retry request with payment proof -// 4. Receive resource +// 2. Pick a payment option from the accepts array +// 3. Create escrow nano contract (deposit funds) +// 4. Retry request with payment proof +// 5. Receive resource +// +// Usage: +// node client.js # pay with first accepted token (HTR) +// node client.js --token htr # pay with HTR explicitly +// node client.js --token custom # pay with the custom token (e.g. hUSDC) const fetch = require('node-fetch'); const config = require('./config'); const { walletRequest, waitForTxConfirmation, log } = require('./helpers'); +// Parse --token arg +const tokenArg = process.argv.find(a => a.startsWith('--token='))?.split('=')[1] + || (process.argv.includes('--token') ? process.argv[process.argv.indexOf('--token') + 1] : null); + +function pickPaymentOption(accepts) { + if (tokenArg === 'custom' && config.customTokenUid) { + const match = accepts.find(a => a.asset === config.customTokenUid); + if (match) return match; + log('CLIENT', `Custom token ${config.customTokenUid} not accepted, falling back`); + } + if (tokenArg === 'htr') { + const match = accepts.find(a => a.asset === '00'); + if (match) return match; + } + // Default: pick first option + return accepts[0]; +} + async function main() { log('CLIENT', '=== x402 Payment Flow Demo ==='); log('CLIENT', `Buyer address: ${config.buyerAddress}`); @@ -17,46 +41,50 @@ async function main() { // Step 1: Request the paid resource (expect 402) log('CLIENT', 'Step 1: Requesting weather data...'); const initialResp = await fetch(`http://localhost:${config.resourceServerPort}/weather`); - const statusCode = initialResp.status; - if (statusCode !== 402) { - log('CLIENT', `Expected 402 but got ${statusCode}`); + if (initialResp.status !== 402) { + log('CLIENT', `Expected 402 but got ${initialResp.status}`); process.exit(1); } const paymentRequired = await initialResp.json(); log('CLIENT', `Got 402 Payment Required`); + log('CLIENT', ` ${paymentRequired.accepts.length} payment option(s) available:`); + for (const opt of paymentRequired.accepts) { + log('CLIENT', ` - ${opt.description} (asset: ${opt.asset}, amount: ${opt.amount})`); + } + log('CLIENT', ''); - const requirements = paymentRequired.accepts[0]; - log('CLIENT', ` Scheme: ${requirements.scheme}`); - log('CLIENT', ` Amount: ${requirements.maxAmountRequired} cents (${parseInt(requirements.maxAmountRequired) / 100} HTR)`); - log('CLIENT', ` Pay to: ${requirements.payTo}`); - log('CLIENT', ` Facilitator: ${requirements.extra.facilitatorAddress}`); - log('CLIENT', ` Blueprint: ${requirements.extra.blueprintId}`); + // Step 2: Pick a payment option + const chosen = pickPaymentOption(paymentRequired.accepts); + log('CLIENT', `Step 2: Chose payment option: ${chosen.description}`); + log('CLIENT', ` Asset: ${chosen.asset}`); + log('CLIENT', ` Amount: ${chosen.amount}`); + log('CLIENT', ` Pay to: ${chosen.payTo}`); + log('CLIENT', ` Facilitator: ${chosen.extra.facilitatorAddress}`); log('CLIENT', ''); - // Step 2: Create escrow nano contract (deposit funds) - log('CLIENT', 'Step 2: Creating escrow nano contract...'); + // Step 3: Create escrow nano contract (deposit funds) + log('CLIENT', 'Step 3: Creating escrow nano contract...'); - const deadline = Math.floor(Date.now() / 1000) + requirements.extra.deadlineSeconds; - const amount = parseInt(requirements.maxAmountRequired); - const resourceUrl = requirements.resource; + const deadline = Math.floor(Date.now() / 1000) + chosen.extra.deadlineSeconds; + const amount = parseInt(chosen.amount); const createResult = await walletRequest('POST', '/wallet/nano-contracts/create', { - blueprint_id: requirements.extra.blueprintId, + blueprint_id: chosen.extra.blueprintId, address: config.buyerAddress, data: { args: [ - requirements.payTo, // seller - requirements.extra.facilitatorAddress, // facilitator - requirements.tokenUid, // token_uid - deadline, // deadline - resourceUrl, // resource_url - 'poc-request-hash', // request_hash + chosen.payTo, // seller + chosen.extra.facilitatorAddress, // facilitator + chosen.asset, // token_uid + deadline, // deadline + chosen.resource, // resource_url + 'poc-request-hash', // request_hash ], actions: [{ type: 'deposit', - token: requirements.tokenUid, + token: chosen.asset, amount: amount, }], }, @@ -75,8 +103,8 @@ async function main() { log('CLIENT', 'Escrow tx confirmed on-chain'); log('CLIENT', ''); - // Step 3: Retry request with payment proof - log('CLIENT', 'Step 3: Retrying request with payment proof...'); + // Step 4: Retry request with payment proof + log('CLIENT', 'Step 4: Retrying request with payment proof...'); const paymentPayload = { scheme: 'hathor-escrow', diff --git a/config.js b/config.js index c0124f5..84b5662 100644 --- a/config.js +++ b/config.js @@ -21,8 +21,9 @@ module.exports = { facilitatorAddress: env.FACILITATOR_ADDRESS || '', sellerAddress: env.SELLER_ADDRESS || '', - // HTR token UID - htrTokenUid: env.TOKEN_UID || '00', + // Token UIDs + htrTokenUid: '00', + customTokenUid: env.CUSTOM_TOKEN_UID || '', // Ports facilitatorPort: parseInt(env.FACILITATOR_PORT || '8402'), @@ -30,5 +31,8 @@ module.exports = { // Escrow settings escrowDeadlineSeconds: parseInt(env.ESCROW_DEADLINE_SECONDS || '300'), - paymentAmount: parseInt(env.PAYMENT_AMOUNT || '100'), + + // Payment amounts (in smallest unit — 1 HTR = 100, 1 hUSDC = 100) + htrPaymentAmount: parseInt(env.HTR_PAYMENT_AMOUNT || '100'), + customTokenPaymentAmount: parseInt(env.CUSTOM_TOKEN_PAYMENT_AMOUNT || '1000'), }; diff --git a/facilitator.js b/facilitator.js index bcdc155..f1ecacc 100644 --- a/facilitator.js +++ b/facilitator.js @@ -9,8 +9,30 @@ const { walletRequest, getNanoContractState, waitForTxConfirmation, log } = requ const app = express(); app.use(express.json()); +// Validate escrow state against a single payment requirement +function validateAgainstRequirement(fields, req) { + const errors = []; + if (fields.phase.value !== 'LOCKED') { + errors.push(`phase is ${fields.phase.value}, expected LOCKED`); + } + if (fields.amount.value < parseInt(req.maxAmountRequired)) { + errors.push(`amount ${fields.amount.value} < required ${req.maxAmountRequired}`); + } + if (fields.seller.value !== req.payTo) { + errors.push(`seller ${fields.seller.value} != payTo ${req.payTo}`); + } + if (fields.facilitator.value !== config.facilitatorAddress) { + errors.push(`facilitator ${fields.facilitator.value} != expected ${config.facilitatorAddress}`); + } + if (req.asset && fields.token_uid.value !== req.asset) { + errors.push(`token_uid ${fields.token_uid.value} != asset ${req.asset}`); + } + return errors; +} + // POST /x402/verify // Resource server calls this to verify an escrow is valid +// paymentRequirements can be a single object or an array (multi-token) app.post('/x402/verify', async (req, res) => { const { paymentPayload, paymentRequirements } = req.body; const { ncId } = paymentPayload.payload; @@ -23,28 +45,25 @@ app.post('/x402/verify', async (req, res) => { } const fields = stateResp.fields; - const errors = []; - - if (fields.phase.value !== 'LOCKED') { - errors.push(`phase is ${fields.phase.value}, expected LOCKED`); - } - if (fields.amount.value < parseInt(paymentRequirements.maxAmountRequired)) { - errors.push(`amount ${fields.amount.value} < required ${paymentRequirements.maxAmountRequired}`); - } - if (fields.seller.value !== paymentRequirements.payTo) { - errors.push(`seller ${fields.seller.value} != payTo ${paymentRequirements.payTo}`); - } - if (fields.facilitator.value !== config.facilitatorAddress) { - errors.push(`facilitator ${fields.facilitator.value} != expected ${config.facilitatorAddress}`); - } - if (errors.length > 0) { - log('FACILITATOR', `Verification FAILED: ${errors.join('; ')}`); - return res.json({ valid: false, invalidReason: errors.join('; ') }); + // Support both single requirement and array of requirements + const requirements = Array.isArray(paymentRequirements) + ? paymentRequirements + : [paymentRequirements]; + + // Try each requirement — if any matches, the payment is valid + let lastErrors = []; + for (const requirement of requirements) { + const errors = validateAgainstRequirement(fields, requirement); + if (errors.length === 0) { + log('FACILITATOR', `Verification PASSED for ncId=${ncId} (asset: ${fields.token_uid.value})`); + return res.json({ valid: true }); + } + lastErrors = errors; } - log('FACILITATOR', `Verification PASSED for ncId=${ncId}`); - res.json({ valid: true }); + log('FACILITATOR', `Verification FAILED: ${lastErrors.join('; ')}`); + res.json({ valid: false, invalidReason: lastErrors.join('; ') }); }); // POST /x402/settle @@ -70,7 +89,7 @@ app.post('/x402/settle', async (req, res) => { const tokenUid = fields.token_uid.value; // Execute release() on the nano contract via wallet-headless - log('FACILITATOR', `Calling release() — withdrawing ${amount} to seller ${seller}`); + log('FACILITATOR', `Calling release() — withdrawing ${amount} of token ${tokenUid} to seller ${seller}`); const result = await walletRequest('POST', '/wallet/nano-contracts/execute', { nc_id: ncId, method: 'release', diff --git a/resource-server.js b/resource-server.js index beff3e1..f5ded93 100644 --- a/resource-server.js +++ b/resource-server.js @@ -1,5 +1,6 @@ // x402 Resource Server (Seller) -// A simple API server that sells weather data for 1 HTR per request +// A simple API server that sells weather data +// Accepts payment in HTR or a custom token (e.g. hUSDC) // Uses x402 middleware to gate access const express = require('express'); @@ -10,31 +11,48 @@ const { log } = require('./helpers'); const app = express(); app.use(express.json()); +// Build the list of accepted payment options +function buildAcceptsList(path) { + const base = { + scheme: 'hathor-escrow', + network: 'hathor:privatenet', + resource: `http://localhost:${config.resourceServerPort}${path}`, + mimeType: 'application/json', + payTo: config.sellerAddress, + maxTimeoutSeconds: config.escrowDeadlineSeconds, + extra: { + facilitatorUrl: `http://localhost:${config.facilitatorPort}`, + facilitatorAddress: config.facilitatorAddress, + blueprintId: config.blueprintId, + deadlineSeconds: config.escrowDeadlineSeconds, + }, + }; + + const accepts = [ + { ...base, asset: config.htrTokenUid, amount: String(config.htrPaymentAmount), description: 'Pay 1.00 HTR' }, + ]; + + // If a custom token is configured, offer it as an alternative + if (config.customTokenUid) { + accepts.push({ + ...base, + asset: config.customTokenUid, + amount: String(config.customTokenPaymentAmount), + description: 'Or pay 10.00 hUSDC', + }); + } + + return accepts; +} + // x402 middleware — checks for payment, returns 402 if none function x402Middleware(req, res, next) { const paymentHeader = req.headers['x-payment']; if (!paymentHeader) { - // No payment — return 402 with payment requirements log('RESOURCE-SERVER', `402 — No payment for ${req.path}`); return res.status(402).json({ - accepts: [{ - scheme: 'hathor-escrow', - network: 'hathor:privatenet', - maxAmountRequired: String(config.paymentAmount), - resource: `http://localhost:${config.resourceServerPort}${req.path}`, - description: 'Pay 1.00 HTR to access weather data', - mimeType: 'application/json', - payTo: config.sellerAddress, - tokenUid: config.htrTokenUid, - maxTimeoutSeconds: config.escrowDeadlineSeconds, - extra: { - facilitatorUrl: `http://localhost:${config.facilitatorPort}`, - facilitatorAddress: config.facilitatorAddress, - blueprintId: config.blueprintId, - deadlineSeconds: config.escrowDeadlineSeconds, - }, - }], + accepts: buildAcceptsList(req.path), version: '1', }); } @@ -45,6 +63,18 @@ function x402Middleware(req, res, next) { next(); } +// Find which accepted option the client paid with by querying the facilitator. +// The server sends ALL accepted options and the facilitator checks which one matches. +function buildPaymentRequirements(path) { + return buildAcceptsList(path).map(opt => ({ + scheme: opt.scheme, + network: opt.network, + maxAmountRequired: opt.amount, + payTo: opt.payTo, + asset: opt.asset, + })); +} + // Verify payment with facilitator, serve resource, then settle app.get('/weather', x402Middleware, async (req, res) => { const payment = req.x402Payment; @@ -52,19 +82,17 @@ app.get('/weather', x402Middleware, async (req, res) => { log('RESOURCE-SERVER', `Verifying payment ncId=${ncId}`); + // Build all accepted payment requirements — the facilitator will match + // the on-chain escrow state against each one to find a valid match + const allRequirements = buildPaymentRequirements(req.path); + // Step 1: Verify with facilitator const verifyResp = await fetch(`http://localhost:${config.facilitatorPort}/x402/verify`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ paymentPayload: payment, - paymentRequirements: { - scheme: 'hathor-escrow', - network: 'hathor:privatenet', - maxAmountRequired: String(config.paymentAmount), - payTo: config.sellerAddress, - tokenUid: config.htrTokenUid, - }, + paymentRequirements: allRequirements, }), }); const verification = await verifyResp.json(); @@ -121,5 +149,5 @@ app.get('/weather', x402Middleware, async (req, res) => { app.listen(config.resourceServerPort, () => { log('RESOURCE-SERVER', `Weather API running on port ${config.resourceServerPort}`); log('RESOURCE-SERVER', `Seller address: ${config.sellerAddress}`); - log('RESOURCE-SERVER', `Price: ${config.paymentAmount} cents HTR per request`); + log('RESOURCE-SERVER', `Accepts: HTR (${config.htrPaymentAmount} cents)${config.customTokenUid ? `, hUSDC (${config.customTokenPaymentAmount} cents)` : ''}`); }); From 9ebb1c70857effe90efda37905689cca243dd3fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Thu, 2 Apr 2026 12:20:51 -0300 Subject: [PATCH 03/37] feat: add x402 payment client dApp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Browser-based x402 payment client built with create-hathor-dapp. Demonstrates the full x402 protocol flow through a UI: 1. User enters a URL of an x402-enabled API 2. dApp fetches it, gets 402 Payment Required 3. Shows payment requirements (amount, token, seller, facilitator) 4. User approves — wallet signs the escrow deposit tx 5. Waits for on-chain confirmation 6. Retries with X-Payment header containing the escrow proof 7. Displays the received resource data Key components: - X402Fetch: Main flow component handling 402 -> pay -> retry - EscrowList/Detail: Track and manage existing escrows - CreateEscrowForm: Manual escrow creation - Privatenet support for hathor-forge local development - WalletConnect (Reown) integration for real wallet signing Also adds CORS headers to resource-server.js for browser access. Co-Authored-By: Claude Opus 4.6 (1M context) --- dapp/.claude/commands/hathor-dapp.md | 270 + dapp/.env.example | 43 + dapp/.env.local.example | 16 + dapp/.eslintrc.json | 3 + dapp/.github/actions/deploy-dapp/action.yml | 48 + dapp/.github/workflows/deploy.yml | 78 + dapp/.github/workflows/test.yml | 118 + dapp/.gitignore | 14 + dapp/AGENTS.md | 439 + dapp/Dockerfile | 76 + dapp/Makefile | 14 + dapp/QUICKSTART.md | 103 + dapp/README.md | 330 + dapp/__mocks__/hathorCoreAPI.ts | 181 + dapp/__mocks__/metamask.ts | 179 + dapp/__mocks__/testUtils.tsx | 118 + dapp/__mocks__/walletConnect.ts | 140 + .../integration/MetaMaskContext.test.tsx | 303 + dapp/__tests__/unit/hathorCoreAPI.test.ts | 412 + dapp/__tests__/unit/hathorRPC.test.ts | 320 + dapp/__tests__/unit/utils.test.ts | 172 + dapp/app/escrow/[id]/page.tsx | 76 + dapp/app/globals.css | 62 + dapp/app/layout.tsx | 43 + dapp/app/page.tsx | 90 + dapp/components/BalanceCard.tsx | 66 + dapp/components/ContractInfoPanel.tsx | 77 + dapp/components/CreateEscrowForm.tsx | 173 + dapp/components/EscrowDetail.tsx | 121 + dapp/components/EscrowList.tsx | 81 + dapp/components/EscrowStatusBadge.tsx | 16 + dapp/components/Header.tsx | 92 + dapp/components/HelpIcon.tsx | 46 + dapp/components/NetworkSelector.tsx | 34 + dapp/components/TokenSelector.tsx | 32 + dapp/components/WalletConnectionModal.tsx | 125 + dapp/components/X402Fetch.tsx | 426 + dapp/components/ui/button.tsx | 44 + dapp/components/ui/card.tsx | 79 + dapp/components/ui/dialog.tsx | 68 + dapp/components/ui/select.tsx | 126 + dapp/contexts/HathorContext.tsx | 216 + dapp/contexts/MetaMaskContext.tsx | 212 + dapp/contexts/UnifiedWalletContext.tsx | 96 + dapp/contexts/WalletConnectContext.tsx | 298 + dapp/contexts/WalletContext.tsx | 241 + dapp/e2e/homepage.spec.ts | 136 + dapp/lib/config.ts | 17 + dapp/lib/escrowStore.ts | 21 + dapp/lib/hathorCoreAPI.ts | 153 + dapp/lib/hathorRPC.ts | 130 + dapp/lib/toast.tsx | 162 + dapp/lib/utils.ts | 62 + dapp/lib/version.ts | 1 + dapp/lib/walletConnectClient.ts | 29 + dapp/lib/walletConnectConfig.ts | 11 + dapp/next.config.js | 6 + dapp/next.config.production.js | 9 + dapp/package-lock.json | 11057 ++++++++++++++++ dapp/package.json | 62 + dapp/playwright.config.ts | 43 + dapp/postcss.config.js | 6 + dapp/public/.gitkeep | 0 dapp/public/favicon.png | Bin 0 -> 807680 bytes dapp/public/images/icon.png | Bin 0 -> 249329 bytes dapp/scripts/deploy.sh | 104 + dapp/tailwind.config.js | 24 + dapp/tsconfig.json | 27 + dapp/types/hathor.ts | 91 + dapp/types/index.ts | 6 + dapp/types/metamask.d.ts | 15 + dapp/types/wallet.ts | 21 + dapp/vitest.config.ts | 44 + dapp/vitest.setup.ts | 81 + resource-server.js | 9 + 75 files changed, 18644 insertions(+) create mode 100644 dapp/.claude/commands/hathor-dapp.md create mode 100644 dapp/.env.example create mode 100644 dapp/.env.local.example create mode 100644 dapp/.eslintrc.json create mode 100644 dapp/.github/actions/deploy-dapp/action.yml create mode 100644 dapp/.github/workflows/deploy.yml create mode 100644 dapp/.github/workflows/test.yml create mode 100644 dapp/.gitignore create mode 100644 dapp/AGENTS.md create mode 100644 dapp/Dockerfile create mode 100644 dapp/Makefile create mode 100644 dapp/QUICKSTART.md create mode 100644 dapp/README.md create mode 100644 dapp/__mocks__/hathorCoreAPI.ts create mode 100644 dapp/__mocks__/metamask.ts create mode 100644 dapp/__mocks__/testUtils.tsx create mode 100644 dapp/__mocks__/walletConnect.ts create mode 100644 dapp/__tests__/integration/MetaMaskContext.test.tsx create mode 100644 dapp/__tests__/unit/hathorCoreAPI.test.ts create mode 100644 dapp/__tests__/unit/hathorRPC.test.ts create mode 100644 dapp/__tests__/unit/utils.test.ts create mode 100644 dapp/app/escrow/[id]/page.tsx create mode 100644 dapp/app/globals.css create mode 100644 dapp/app/layout.tsx create mode 100644 dapp/app/page.tsx create mode 100644 dapp/components/BalanceCard.tsx create mode 100644 dapp/components/ContractInfoPanel.tsx create mode 100644 dapp/components/CreateEscrowForm.tsx create mode 100644 dapp/components/EscrowDetail.tsx create mode 100644 dapp/components/EscrowList.tsx create mode 100644 dapp/components/EscrowStatusBadge.tsx create mode 100644 dapp/components/Header.tsx create mode 100644 dapp/components/HelpIcon.tsx create mode 100644 dapp/components/NetworkSelector.tsx create mode 100644 dapp/components/TokenSelector.tsx create mode 100644 dapp/components/WalletConnectionModal.tsx create mode 100644 dapp/components/X402Fetch.tsx create mode 100644 dapp/components/ui/button.tsx create mode 100644 dapp/components/ui/card.tsx create mode 100644 dapp/components/ui/dialog.tsx create mode 100644 dapp/components/ui/select.tsx create mode 100644 dapp/contexts/HathorContext.tsx create mode 100644 dapp/contexts/MetaMaskContext.tsx create mode 100644 dapp/contexts/UnifiedWalletContext.tsx create mode 100644 dapp/contexts/WalletConnectContext.tsx create mode 100644 dapp/contexts/WalletContext.tsx create mode 100644 dapp/e2e/homepage.spec.ts create mode 100644 dapp/lib/config.ts create mode 100644 dapp/lib/escrowStore.ts create mode 100644 dapp/lib/hathorCoreAPI.ts create mode 100644 dapp/lib/hathorRPC.ts create mode 100644 dapp/lib/toast.tsx create mode 100644 dapp/lib/utils.ts create mode 100644 dapp/lib/version.ts create mode 100644 dapp/lib/walletConnectClient.ts create mode 100644 dapp/lib/walletConnectConfig.ts create mode 100644 dapp/next.config.js create mode 100644 dapp/next.config.production.js create mode 100644 dapp/package-lock.json create mode 100644 dapp/package.json create mode 100644 dapp/playwright.config.ts create mode 100644 dapp/postcss.config.js create mode 100644 dapp/public/.gitkeep create mode 100644 dapp/public/favicon.png create mode 100644 dapp/public/images/icon.png create mode 100755 dapp/scripts/deploy.sh create mode 100644 dapp/tailwind.config.js create mode 100644 dapp/tsconfig.json create mode 100644 dapp/types/hathor.ts create mode 100644 dapp/types/index.ts create mode 100644 dapp/types/metamask.d.ts create mode 100644 dapp/types/wallet.ts create mode 100644 dapp/vitest.config.ts create mode 100644 dapp/vitest.setup.ts diff --git a/dapp/.claude/commands/hathor-dapp.md b/dapp/.claude/commands/hathor-dapp.md new file mode 100644 index 0000000..87fecc3 --- /dev/null +++ b/dapp/.claude/commands/hathor-dapp.md @@ -0,0 +1,270 @@ +# Hathor dApp Development Assistant + +You are an expert assistant for building decentralized applications on the Hathor Network using the create-hathor-dapp template. + +## Your Capabilities + +You help developers with: +1. **Scaffolding** - Setting up new dApps, configuring environment, project structure +2. **Nano Contract Integration** - Adding contract methods, reading state, handling transactions +3. **Wallet Integration** - Reown (WalletConnect) and MetaMask Snaps setup +4. **Feature Development** - Building complete features following template patterns +5. **Testing** - Unit, integration, and E2E tests + +## Template Architecture + +### Context Providers (in order of wrapping) +``` +ToastProvider + └── WalletConnectProvider (Reown integration) + └── MetaMaskProvider (Snaps integration) + └── UnifiedWalletProvider (unified adapter) + └── WalletProvider (balance/transactions) + └── HathorProvider (network/contracts) +``` + +### Key Files +- `contexts/HathorContext.tsx` - Network, contract state, connection status +- `contexts/WalletContext.tsx` - Balance management, `sendNanoContractTx()` +- `contexts/WalletConnectContext.tsx` - Reown/WalletConnect client +- `contexts/MetaMaskContext.tsx` - MetaMask Snaps integration +- `lib/hathorRPC.ts` - RPC service for wallet communication +- `lib/hathorCoreAPI.ts` - Blockchain data queries (state, history, transactions) +- `lib/config.ts` - Environment configuration + +### Wallet Connection Flow +1. User clicks "Connect Wallet" → `WalletConnectionModal` opens +2. User selects Reown or MetaMask Snaps +3. Provider's `connect()` is called +4. `UnifiedWalletContext` provides unified `WalletAdapter` interface +5. `HathorContext` syncs address and network +6. `WalletContext` fetches balance via `HathorRPCService` + +## Common Patterns + +### Sending a Nano Contract Transaction +```typescript +import { useWallet } from '@/contexts/WalletContext'; +import { useHathor } from '@/contexts/HathorContext'; +import { toast } from '@/lib/toast'; + +function MyComponent() { + const { sendNanoContractTx, refreshBalance } = useWallet(); + const { network, getContractIdForToken, getContractStateForToken } = useHathor(); + + const handleAction = async () => { + const contractId = getContractIdForToken('HTR'); + const contractState = getContractStateForToken('HTR'); + const tokenUid = contractState?.token_uid || '00'; + + try { + toast.info('Please confirm in your wallet...'); + + const result = await sendNanoContractTx({ + network, + nc_id: contractId, + method: 'your_method_name', + args: [arg1, arg2], + actions: [ + { + type: 'deposit', // or 'withdrawal' + amount: '1000', // in cents (10.00 tokens) + token: tokenUid, + }, + ], + push_tx: true, + }); + + toast.success(`TX: ${result.response?.hash?.slice(0, 10)}...`); + refreshBalance(tokenUid, network); + } catch (error: any) { + toast.error(error.message || 'Transaction failed'); + } + }; +} +``` + +### Reading Contract State +```typescript +import { useHathor } from '@/contexts/HathorContext'; + +function ContractInfo() { + const { getContractStateForToken, coreAPI } = useHathor(); + + // Cached state from context + const state = getContractStateForToken('HTR'); + + // Direct API calls + const fetchData = async () => { + const state = await coreAPI.getContractState('contract_id', ['field1', 'field2']); + const history = await coreAPI.getContractHistory('contract_id', 100); + const balance = await coreAPI.getClaimableBalance('contract_id', userAddress); + }; +} +``` + +### Creating a New Page +```typescript +// app/my-feature/page.tsx +'use client'; + +import { useHathor } from '@/contexts/HathorContext'; +import { useWallet } from '@/contexts/WalletContext'; +import Header from '@/components/Header'; + +export default function MyFeaturePage() { + const { isConnected, network } = useHathor(); + const { balance } = useWallet(); + + return ( +
+
{}} appName="My dApp" /> +
+ {isConnected ? ( +
{/* Your connected UI */}
+ ) : ( +
{/* Connect wallet prompt */}
+ )} +
+
+ ); +} +``` + +### Adding Contract State Fields +1. Update `types/hathor.ts`: +```typescript +export interface ContractState { + token_uid: string; + available_tokens: bigint; + total_liquidity_provided: bigint; + your_new_field: number; // Add your field + [key: string]: any; +} +``` + +2. Update `lib/hathorCoreAPI.ts` to fetch the field: +```typescript +async getContractState(contractId: string, fields: string[] = [ + 'token_uid', 'available_tokens', 'total_liquidity_provided', 'your_new_field' +]): Promise +``` + +## Reown (WalletConnect) Integration + +### Configuration +Edit `lib/walletConnectConfig.ts`: +```typescript +export const walletConnectMetadata = { + name: 'Your dApp Name', + description: 'Your dApp description', + url: 'https://yourdapp.com', + icons: ['https://yourdapp.com/icon.png'], +}; +``` + +### Environment Variables +```env +NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=your_project_id # From https://cloud.walletconnect.com/ +``` + +### How It Works +- `WalletConnectContext` manages the SignClient +- Sessions are persisted and restored on page load +- Network is synced from wallet session +- RPC calls go through `HathorRPCService` with WalletConnect client + +## MetaMask Snaps Integration + +### How It Works +- `MetaMaskContext` manages Snap connection +- Uses `wallet_requestSnaps` to install/connect +- RPC calls use `wallet_invokeSnap` with Hathor Snap ID +- Supports same methods as WalletConnect + +### Snap ID +The Hathor Snap ID is configured in `MetaMaskContext.tsx`. + +## Testing + +### Unit Tests +```typescript +// __tests__/unit/myComponent.test.ts +import { describe, it, expect, vi } from 'vitest'; +import { render, screen } from '@testing-library/react'; + +describe('MyComponent', () => { + it('should render correctly', () => { + // Test implementation + }); +}); +``` + +### Mocking Contexts +```typescript +vi.mock('@/contexts/HathorContext', () => ({ + useHathor: () => ({ + isConnected: true, + network: 'testnet', + getContractStateForToken: vi.fn(), + }), +})); +``` + +### E2E Tests +```typescript +// e2e/my-feature.spec.ts +import { test, expect } from '@playwright/test'; + +test('my feature works', async ({ page }) => { + await page.goto('/'); + // Test implementation +}); +``` + +## Environment Setup + +### Required Variables +```env +NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=xxx # Required for Reown +NEXT_PUBLIC_DEFAULT_NETWORK=testnet # testnet or mainnet +NEXT_PUBLIC_CONTRACT_IDS_TESTNET=["..."] # Your contract IDs +NEXT_PUBLIC_CONTRACT_IDS_MAINNET=[] +``` + +### Optional Variables +```env +NEXT_PUBLIC_USE_MOCK_WALLET=true # Enable mock mode for development +NEXT_PUBLIC_APP_NAME=My dApp +NEXT_PUBLIC_APP_DESCRIPTION=Description +``` + +## Development Workflow + +1. **Start with mock mode** - `NEXT_PUBLIC_USE_MOCK_WALLET=true` +2. **Build your UI** - Create components and pages +3. **Add contract integration** - Use `sendNanoContractTx` and `coreAPI` +4. **Test with real wallet** - Set `NEXT_PUBLIC_USE_MOCK_WALLET=false` +5. **Write tests** - Unit tests for logic, E2E for flows + +## Commands +```bash +npm run dev # Development server +npm run build # Production build +npm run test # Unit tests +npm run test:coverage # Tests with coverage +npm run test:e2e # E2E tests +npm run lint # ESLint +``` + +## When Helping Users + +1. **Always read relevant files first** before suggesting changes +2. **Follow existing patterns** in the codebase +3. **Use the template's utilities** (toast, formatBalance, etc.) +4. **Maintain type safety** - update types when adding features +5. **Consider both wallet types** - Reown and MetaMask Snaps +6. **Handle loading and error states** appropriately +7. **Write tests** for new functionality + +$ARGUMENTS diff --git a/dapp/.env.example b/dapp/.env.example new file mode 100644 index 0000000..0a77d09 --- /dev/null +++ b/dapp/.env.example @@ -0,0 +1,43 @@ +# =========================================== +# Hathor dApp Configuration +# =========================================== + +# WalletConnect Project ID (Required) +# Get your project ID from https://cloud.walletconnect.com/ +NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=your_project_id_here + +# =========================================== +# Network Configuration +# =========================================== + +# Default network: 'testnet' or 'mainnet' +NEXT_PUBLIC_DEFAULT_NETWORK=testnet + +# Enable mock wallet for development (no real wallet needed) +NEXT_PUBLIC_USE_MOCK_WALLET=false + +# Hathor Node URLs (optional - uses defaults if not set) +NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET=https://node1.testnet.hathor.network/v1a +NEXT_PUBLIC_HATHOR_NODE_URL_MAINNET=https://node1.mainnet.hathor.network/v1a + +# =========================================== +# Contract Configuration +# =========================================== + +# Contract IDs for each network (JSON array format) +# Add your nano contract IDs here +NEXT_PUBLIC_CONTRACT_IDS_TESTNET=[] +NEXT_PUBLIC_CONTRACT_IDS_MAINNET=[] + +# Legacy format (still supported) +# NEXT_PUBLIC_CONTRACT_IDS=["your_contract_id_here"] + +# =========================================== +# App Metadata (Optional) +# =========================================== + +# App name displayed in WalletConnect +NEXT_PUBLIC_APP_NAME=Hathor dApp + +# App description for WalletConnect +NEXT_PUBLIC_APP_DESCRIPTION=Decentralized application on Hathor Network diff --git a/dapp/.env.local.example b/dapp/.env.local.example new file mode 100644 index 0000000..5a2f7b8 --- /dev/null +++ b/dapp/.env.local.example @@ -0,0 +1,16 @@ +# Wallet Configuration +# Set to true to use mock wallet for development/testing +NEXT_PUBLIC_USE_MOCK_WALLET=true + +# Network Configuration +# Options: 'india-testnet' or 'mainnet' +NEXT_PUBLIC_DEFAULT_NETWORK=india-testnet + +# Hathor Node URLs +NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET=https://node1.india-testnet.hathor.network/v1a +NEXT_PUBLIC_HATHOR_NODE_URL_MAINNET=https://node1.mainnet.hathor.network/v1a + +# Contract IDs +# Add your deployed contract IDs as a JSON array +# Example: ["0abc123...", "def456..."] +NEXT_PUBLIC_CONTRACT_IDS=[] diff --git a/dapp/.eslintrc.json b/dapp/.eslintrc.json new file mode 100644 index 0000000..bffb357 --- /dev/null +++ b/dapp/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": "next/core-web-vitals" +} diff --git a/dapp/.github/actions/deploy-dapp/action.yml b/dapp/.github/actions/deploy-dapp/action.yml new file mode 100644 index 0000000..ee0cdee --- /dev/null +++ b/dapp/.github/actions/deploy-dapp/action.yml @@ -0,0 +1,48 @@ +name: Deploy Hathor dApp +description: Build and deploy the Hathor dApp to AWS S3/CloudFront + +inputs: + site: + description: The site name to build and deploy (staging, production) + required: true + aws-region: + description: The AWS region to deploy to + required: true + default: us-east-1 + aws-role: + description: The AWS IAM role to assume for deployment + required: true + +runs: + using: composite + steps: + - name: Configure AWS Credentials + # https://github.com/aws-actions/configure-aws-credentials/releases/tag/v5.1.1 + uses: aws-actions/configure-aws-credentials@61815dcd50bd041e203e49132bacad1fd04d2708 + with: + aws-region: ${{ inputs.aws-region }} + role-to-assume: ${{ inputs.aws-role }} + + - name: Set up Node.js 24.x + # https://github.com/actions/setup-node/releases/tag/v6.1.0 + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f + with: + node-version: 24.x + + - name: Download node modules + # https://github.com/actions/download-artifact/releases/tag/v6.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 + with: + name: node_modules + + - name: Build + shell: bash + run: | + tar -xf node_modules.tar + make build site=${{ inputs.site }} + + - name: Deploy + shell: bash + run: | + make sync site=${{ inputs.site }} + make clear_cloudfront_cache site=${{ inputs.site }} diff --git a/dapp/.github/workflows/deploy.yml b/dapp/.github/workflows/deploy.yml new file mode 100644 index 0000000..9105fca --- /dev/null +++ b/dapp/.github/workflows/deploy.yml @@ -0,0 +1,78 @@ +name: deploy + +on: + push: + branches: [release] + tags: ['v*'] + +permissions: + id-token: write + contents: read + +jobs: + dependencies: + runs-on: ubuntu-latest + steps: + # https://github.com/actions/checkout/releases/tag/v6.0.1 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 + + - name: Set up Node.js 24.x + # https://github.com/actions/setup-node/releases/tag/v6.1.0 + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f + with: + node-version: 24.x + + - name: Cache node modules + # https://github.com/actions/cache/releases/tag/v4.3.0 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 + env: + cache-name: cache-node-modules + with: + path: ${{ github.workspace }}/node_modules + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-build-${{ env.cache-name }}- + ${{ runner.os }}-build- + ${{ runner.os }}- + + - name: Install Dependencies + run: | + npm install + tar -cvf node_modules.tar ./node_modules + + - name: Upload node modules + # https://github.com/actions/upload-artifact/releases/tag/v5.0.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 + with: + name: node_modules + path: node_modules.tar + if-no-files-found: error + retention-days: 1 + + deploy-staging: + if: github.ref == 'refs/heads/release' + needs: dependencies + runs-on: ubuntu-latest + steps: + # https://github.com/actions/checkout/releases/tag/v6.0.1 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 + - uses: ./.github/actions/deploy-dapp + with: + site: staging + aws-region: us-east-1 + # TODO: Update with your AWS IAM role ARN + aws-role: arn:aws:iam::YOUR_ACCOUNT_ID:role/YourGitHubActionsRoleStaging + + deploy-production: + if: startsWith(github.ref, 'refs/tags/v') + needs: dependencies + runs-on: ubuntu-latest + steps: + # https://github.com/actions/checkout/releases/tag/v6.0.1 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 + - uses: ./.github/actions/deploy-dapp + with: + site: production + aws-region: us-east-1 + # TODO: Update with your AWS IAM role ARN + aws-role: arn:aws:iam::YOUR_ACCOUNT_ID:role/YourGitHubActionsRoleProduction diff --git a/dapp/.github/workflows/test.yml b/dapp/.github/workflows/test.yml new file mode 100644 index 0000000..d5f7c7d --- /dev/null +++ b/dapp/.github/workflows/test.yml @@ -0,0 +1,118 @@ +name: Tests + +on: + push: + branches: [main, master, develop] + pull_request: + branches: [main, master, develop] + +jobs: + unit-and-integration-tests: + name: Unit & Integration Tests + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Run unit and integration tests + run: npm run test:run + + - name: Generate coverage report + run: npm run test:coverage + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v4 + with: + files: ./coverage/lcov.info + flags: unittests + name: codecov-umbrella + fail_ci_if_error: false + + e2e-tests: + name: E2E Tests + runs-on: ubuntu-latest + needs: unit-and-integration-tests + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Install Playwright browsers + run: npx playwright install --with-deps + + - name: Run E2E tests + run: npm run test:e2e + env: + NEXT_PUBLIC_USE_MOCK_WALLET: 'true' + NEXT_PUBLIC_DEFAULT_NETWORK: 'testnet' + + - name: Upload Playwright report + uses: actions/upload-artifact@v4 + if: always() + with: + name: playwright-report + path: playwright-report/ + retention-days: 30 + + lint: + name: Lint + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Run linter + run: npm run lint + + build: + name: Build + runs-on: ubuntu-latest + needs: [unit-and-integration-tests, lint] + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Build application + run: npm run build + env: + NEXT_PUBLIC_USE_MOCK_WALLET: 'false' + NEXT_PUBLIC_DEFAULT_NETWORK: 'testnet' diff --git a/dapp/.gitignore b/dapp/.gitignore new file mode 100644 index 0000000..2ca33b2 --- /dev/null +++ b/dapp/.gitignore @@ -0,0 +1,14 @@ +node_modules +.next +out +dist +build +.DS_Store +*.log +.env*.local +.vercel +*.tsbuildinfo +next-env.d.ts +coverage/ +playwright-report/ +test-results/ diff --git a/dapp/AGENTS.md b/dapp/AGENTS.md new file mode 100644 index 0000000..3da84aa --- /dev/null +++ b/dapp/AGENTS.md @@ -0,0 +1,439 @@ +# AGENTS.md — LLM Instructions for Hathor dApp + +This document is the single source of truth for AI agents building dApps from this template. Follow it step by step. + +## Quick Reference + +| What | Where | +|------|-------| +| WalletConnect Project ID | `.env.local` → `NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID` | +| Contract IDs (testnet) | `.env.local` → `NEXT_PUBLIC_CONTRACT_IDS_TESTNET` | +| Contract IDs (mainnet) | `.env.local` → `NEXT_PUBLIC_CONTRACT_IDS_MAINNET` | +| App name & description | `.env.local` → `NEXT_PUBLIC_APP_NAME` / `NEXT_PUBLIC_APP_DESCRIPTION` | +| Default network | `.env.local` → `NEXT_PUBLIC_DEFAULT_NETWORK` | +| Mock mode (no wallet) | `.env.local` → `NEXT_PUBLIC_USE_MOCK_WALLET=true` | +| Main page | `app/page.tsx` | +| Add new pages | `app/your-page/page.tsx` | +| Add components | `components/` | +| Contract state types | `types/hathor.ts` → `ContractState` | +| Contract state fields | `lib/hathorCoreAPI.ts` → `getContractState()` | +| Page title & metadata | `app/layout.tsx` → `metadata` | +| Header app name | `app/page.tsx` → `
` | +| WalletConnect metadata | `lib/walletConnectConfig.ts` | +| App icon | `public/images/icon.png` | +| Favicon | `public/favicon.png` | + +## Step 1: Configure Environment + +The `.env.local` file controls all runtime configuration. Edit it directly — do not modify `lib/config.ts` unless adding new env vars. + +```env +# REQUIRED: Get from https://cloud.walletconnect.com/ +# Create a project → copy the Project ID +NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=your_project_id_here + +# Network: 'testnet' or 'mainnet' +NEXT_PUBLIC_DEFAULT_NETWORK=testnet + +# Set to true during development to skip real wallet connection +NEXT_PUBLIC_USE_MOCK_WALLET=true + +# Your deployed nano contract IDs (JSON array) +NEXT_PUBLIC_CONTRACT_IDS_TESTNET=["000001a2b3c4d5e6..."] +NEXT_PUBLIC_CONTRACT_IDS_MAINNET=[] + +# App metadata shown in WalletConnect modal +NEXT_PUBLIC_APP_NAME=My dApp Name +NEXT_PUBLIC_APP_DESCRIPTION=Description of my dApp + +# Custom node URLs (optional — defaults work for most cases) +# NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET=https://node1.testnet.hathor.network/v1a +# NEXT_PUBLIC_HATHOR_NODE_URL_MAINNET=https://node1.mainnet.hathor.network/v1a +``` + +**Important**: Mock mode (`NEXT_PUBLIC_USE_MOCK_WALLET=true`) lets you develop and test the UI without a real wallet. It simulates connections, balances, and transactions. Set to `false` when ready for real wallet testing. + +## Step 2: Set App Identity + +Update these files to brand the dApp: + +**`app/layout.tsx`** — Page title and SEO: +```typescript +export const metadata: Metadata = { + title: 'Your App Name', + description: 'Your app description', +}; +``` + +**`app/page.tsx`** — Header display name: +```tsx +
+``` + +**`public/images/icon.png`** — Replace with your app icon (used in WalletConnect modal). + +**`public/favicon.png`** — Replace with your favicon. + +## Step 3: Build Your UI + +### Architecture Overview + +``` +app/layout.tsx ← Provider tree (do NOT reorder providers) + └─ ToastProvider + └─ WalletConnectProvider + └─ MetaMaskProvider + └─ UnifiedWalletProvider + └─ WalletProvider + └─ HathorProvider + └─ {children} ← Your pages render here +``` + +All pages automatically have access to wallet and contract state through React contexts. + +### The Main Page (`app/page.tsx`) + +This is the template's example page. **Replace its contents entirely** with your dApp UI. Keep the imports and hooks pattern: + +```tsx +'use client'; + +import { useWallet } from '@/contexts/WalletContext'; +import { useHathor } from '@/contexts/HathorContext'; +import Header from '@/components/Header'; + +export default function Home() { + const { balance, address, refreshBalance, sendNanoContractTx } = useWallet(); + const { network, isConnected, getContractStateForToken, getContractIdForToken } = useHathor(); + + return ( +
+
{}} /> +
+ {/* Your UI here */} +
+
+ ); +} +``` + +### Adding New Pages + +Create files in `app/` following Next.js App Router conventions: + +``` +app/ +├── page.tsx ← / (home) +├── dashboard/page.tsx ← /dashboard +├── history/page.tsx ← /history +└── settings/page.tsx ← /settings +``` + +Every page must be `'use client'` if it uses wallet hooks. All contexts are available automatically — no extra wrapping needed. + +### Creating Components + +Place new components in `components/`. Use existing UI primitives from `components/ui/`: + +- `Button` — `components/ui/button.tsx` +- `Card` / `CardHeader` / `CardContent` — `components/ui/card.tsx` +- `Dialog` — `components/ui/dialog.tsx` +- `Select` — `components/ui/select.tsx` + +### Styling + +This project uses **Tailwind CSS**. The color scheme is based on `slate` tones with an orange accent (`rgb(255, 166, 0)` to `rgb(255, 115, 0)` gradient). Global styles are in `app/globals.css`. + +## Step 4: Interact with Nano Contracts + +### Available Hooks + +**`useHathor()`** — Network, connection, and contract state: +```typescript +const { + isConnected, // boolean — is a wallet connected? + address, // string | null — connected wallet address + network, // 'testnet' | 'mainnet' + contractStates, // Record — keyed by token symbol + getContractStateForToken, // (token: string) => ContractState | null + getContractIdForToken, // (token: string) => string | null + coreAPI, // HathorCoreAPI instance for direct node queries + connectWallet, // () => Promise + disconnectWallet, // () => Promise + switchNetwork, // (network: Network) => Promise + refreshContractStates,// () => Promise + allTransactions, // ContractTransaction[] — history from all contracts + isLoadingHistory, // boolean + refreshHistory, // () => Promise +} = useHathor(); +``` + +**`useWallet()`** — Balance and transactions: +```typescript +const { + balance, // bigint — balance in cents (100 = 1.00 token) + address, // string | null + balanceVerified, // boolean — has balance been fetched? + isLoadingBalance, // boolean + refreshBalance, // (tokenUid?: string, network?: Network) => Promise + sendNanoContractTx, // (params) => Promise — send a transaction + setBalance, // React.Dispatch — for resetting balance on token switch +} = useWallet(); +``` + +**`useUnifiedWallet()`** — Low-level wallet adapter info: +```typescript +const { walletType, adapter } = useUnifiedWallet(); +// walletType: 'walletconnect' | 'metamask' | null +``` + +### Sending a Transaction + +```typescript +const { sendNanoContractTx } = useWallet(); +const { network, getContractIdForToken, getContractStateForToken } = useHathor(); + +const handleAction = async () => { + const contractId = getContractIdForToken('HTR'); + const contractState = getContractStateForToken('HTR'); + const tokenUid = contractState?.token_uid || '00'; + + const result = await sendNanoContractTx({ + network, + nc_id: contractId, + method: 'your_method', // The nano contract method name + args: [arg1, arg2], // Method arguments + actions: [ + { + type: 'deposit', // 'deposit' or 'withdrawal' + amount: '1000', // Amount in cents (1000 = 10.00 tokens) + token: tokenUid, // Token UID ('00' for HTR) + }, + ], + push_tx: true, + }); + + console.log('TX Hash:', result.response?.hash); +}; +``` + +### Reading Contract State + +Contract state is automatically fetched and cached in `HathorContext`. Access it via hooks: + +```typescript +const { getContractStateForToken } = useHathor(); +const state = getContractStateForToken('HTR'); +// state.token_uid, state.available_tokens (bigint), state.total_liquidity_provided (bigint) +``` + +For direct API calls (not cached): +```typescript +const { coreAPI } = useHathor(); + +// Fetch state with specific fields +const state = await coreAPI.getContractState(contractId, ['field1', 'field2']); + +// Fetch transaction history +const history = await coreAPI.getContractHistory(contractId, 100); + +// Call a view function (read-only, no wallet needed) +const result = await coreAPI.callViewFunction(contractId, 'method_name', [args]); + +// Get blueprint info +const blueprint = await coreAPI.getBlueprintInfo(blueprintId); +``` + +### Adding Custom Contract State Fields + +If your nano contract has custom state fields beyond the defaults (`token_uid`, `available_tokens`, `total_liquidity_provided`): + +1. **Update the type** in `types/hathor.ts`: +```typescript +export interface ContractState { + token_uid: string; + available_tokens: bigint; + total_liquidity_provided: bigint; + // Add your fields: + your_custom_field: number; + another_field: string; + [key: string]: any; +} +``` + +2. **Update the field list** in `lib/hathorCoreAPI.ts` → `getContractState()`: +```typescript +async getContractState( + contractId: string, + fields: string[] = ['token_uid', 'available_tokens', 'total_liquidity_provided', 'your_custom_field', 'another_field'] +): Promise { +``` + +3. **Use in components**: +```typescript +const state = getContractStateForToken('HTR'); +console.log(state?.your_custom_field); +``` + +### Toast Notifications + +```typescript +import { toast } from '@/lib/toast'; + +toast.success('Transaction confirmed!'); +toast.error('Something went wrong'); +toast.info('Please confirm in your wallet...'); +``` + +## Step 5: Adding Env Vars + +If you need new environment variables: + +1. Add to `.env.local` with `NEXT_PUBLIC_` prefix (for client-side access) +2. Add to `.env.example` with documentation +3. Read in `lib/config.ts`: +```typescript +export const config = { + // ... existing config + yourNewVar: process.env.NEXT_PUBLIC_YOUR_VAR || 'default', +}; +``` + +**Important**: Next.js requires `NEXT_PUBLIC_` env vars to be referenced as literal strings (not via dynamic key access) because they are replaced at build time. + +## Project Structure + +``` +├── app/ # Next.js App Router pages +│ ├── layout.tsx # Root layout — provider tree (DO NOT reorder) +│ ├── page.tsx # Home page — REPLACE WITH YOUR UI +│ └── globals.css # Global styles (Tailwind) +├── components/ # React components +│ ├── Header.tsx # App header with wallet connect button +│ ├── BalanceCard.tsx # Wallet balance display +│ ├── ContractInfoPanel.tsx # Contract state display +│ ├── NetworkSelector.tsx # Testnet/Mainnet dropdown +│ ├── TokenSelector.tsx # Token picker (when multiple contracts) +│ ├── WalletConnectionModal.tsx # Wallet connection dialog +│ ├── HelpIcon.tsx # Tooltip help icon +│ └── ui/ # Base UI primitives (button, card, dialog, select) +├── contexts/ # React Context providers +│ ├── HathorContext.tsx # Main context: network, contracts, connection +│ ├── WalletContext.tsx # Balance management, sendNanoContractTx +│ ├── UnifiedWalletContext.tsx # Unified adapter over MetaMask/WalletConnect +│ ├── MetaMaskContext.tsx # MetaMask Snaps integration +│ └── WalletConnectContext.tsx # WalletConnect/Reown integration +├── lib/ # Core utilities +│ ├── config.ts # Env var parsing — ADD NEW VARS HERE +│ ├── hathorRPC.ts # RPC service (wallet communication) +│ ├── hathorCoreAPI.ts # Blockchain node API (read contract state) +│ ├── walletConnectConfig.ts # WalletConnect metadata +│ ├── walletConnectClient.ts # WalletConnect client singleton +│ ├── utils.ts # Formatting helpers +│ ├── toast.tsx # Toast notification system +│ └── version.ts # App version constant +├── types/ # TypeScript definitions +│ ├── hathor.ts # ContractState, BlueprintInfo, RPC types +│ ├── wallet.ts # WalletAdapter interface +│ ├── index.ts # Re-exports +│ └── metamask.d.ts # MetaMask window types +├── __tests__/ # Tests +│ ├── unit/ # Unit tests (vitest) +│ └── integration/ # Integration tests (vitest) +├── __mocks__/ # Test mocks +├── e2e/ # E2E tests (Playwright) +├── public/ # Static assets +│ ├── favicon.png # Favicon — REPLACE +│ └── images/icon.png # App icon — REPLACE +├── .env.example # Full env var documentation +├── .env.local.example # Quick-start env (mock mode enabled) +├── .env.local # Your actual config (gitignored) +└── scripts/deploy.sh # Deployment script +``` + +## Development Commands + +```bash +npm run dev # Start dev server at http://localhost:3000 +npm run build # Production build +npm run lint # ESLint +npm run test # Unit tests (watch mode) +npm run test:run # Unit tests (single run) +npm run test:coverage # Tests with coverage report +npm run test:e2e # Playwright E2E tests +``` + +## Testing + +- Unit tests: `__tests__/unit/` — test utilities, API clients, RPC service +- Integration tests: `__tests__/integration/` — test context providers with mocked wallets +- E2E tests: `e2e/` — test full page flows with Playwright +- Mocks: `__mocks__/` — mock implementations for wallet APIs +- Coverage thresholds: 80% lines/statements/functions, 70% branches + +When adding features, add corresponding tests. Use mocks from `__mocks__/` for wallet interactions. + +## Key Concepts + +### Wallet Connection Flow + +1. User clicks "Connect Wallet" → `WalletConnectionModal` opens +2. User picks MetaMask Snaps or Reown (WalletConnect) +3. Provider's `connect()` is called → `UnifiedWalletContext` wraps it in a unified `WalletAdapter` +4. `HathorContext` detects connection → syncs address and network from wallet +5. `WalletContext` begins balance fetching via `HathorRPCService` + +### How Contract IDs Map to Tokens + +Each contract ID in `NEXT_PUBLIC_CONTRACT_IDS_TESTNET` is fetched for its state. The `token_uid` field in the state determines which token symbol it maps to (looked up via the node API). This means: +- One contract per token +- Token symbol is resolved automatically +- Access state by token symbol: `getContractStateForToken('HTR')` + +### Network Switching + +- Stored in localStorage (`hathor_selected_network`) +- Changing network **disconnects** the wallet (Hathor wallets require this) +- Contract states are re-fetched for the new network +- `HathorCoreAPI` automatically uses the correct node URL + +### Mock Mode + +When `NEXT_PUBLIC_USE_MOCK_WALLET=true`: +- `HathorRPCService` returns simulated responses +- Wallet connects instantly with a fake address +- Balance returns 1250.50 HTR +- Transactions return mock hashes +- Contract states use hardcoded defaults + +Use mock mode for UI development, then switch to `false` for real wallet integration testing. + +## Files You Should NOT Modify (Unless Necessary) + +These files contain core infrastructure. Modifying them incorrectly will break wallet connectivity: + +- `contexts/WalletConnectContext.tsx` — WalletConnect session management +- `contexts/MetaMaskContext.tsx` — MetaMask Snaps integration +- `contexts/UnifiedWalletContext.tsx` — Wallet adapter unification +- `lib/hathorRPC.ts` — RPC protocol implementation +- `lib/walletConnectClient.ts` — WalletConnect client singleton +- `app/layout.tsx` — Provider ordering (changing order breaks context dependencies) + +## Files You SHOULD Modify + +- `app/page.tsx` — **Replace entirely** with your dApp UI +- `app/` — Add new pages +- `components/` — Add new components +- `.env.local` — Configure WalletConnect ID, contract IDs, app name +- `types/hathor.ts` — Add custom contract state fields +- `lib/hathorCoreAPI.ts` — Add custom state fields to `getContractState()` defaults +- `lib/config.ts` — Add new env vars +- `public/` — Replace icon and favicon + +## Resources + +- [Hathor Documentation](https://docs.hathor.network) +- [Nano Contracts Guide](https://docs.hathor.network/guides/nano-contracts/) +- [Hathor Wallet API](https://docs.hathor.network/guides/headless-wallet/http-api/) +- [WalletConnect Cloud](https://cloud.walletconnect.com/) — Get your Project ID +- [Hathor Discord](https://discord.gg/hathor) diff --git a/dapp/Dockerfile b/dapp/Dockerfile new file mode 100644 index 0000000..644a83e --- /dev/null +++ b/dapp/Dockerfile @@ -0,0 +1,76 @@ +# Frontend Dockerfile - Multi-stage build for Next.js SSR +FROM node:18-alpine AS builder + +# Set working directory +WORKDIR /app + +# Copy package files +COPY package.json package-lock.json* ./ + +# Install dependencies +RUN npm ci + +# Copy source code +COPY . . + +# Build arguments for configurable API URL +ARG NEXT_PUBLIC_API_URL +ENV NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL:-/} + +# Set environment for building +ENV NEXT_PUBLIC_USE_MOCK_WALLET=false +ENV NEXT_PUBLIC_DEFAULT_NETWORK=testnet +ENV NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET=https://node1.india.testnet.hathor.network/v1a +ENV NEXT_PUBLIC_HATHOR_NODE_URL_MAINNET=https://node1.mainnet.hathor.network/v1a +ENV NEXT_PUBLIC_CONTRACT_IDS='["0000000079862340c1f7822b81f58668e2a62c5f1b69d8d2e3b8fdf1855196c1"]' +ENV NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=8264fff563181da658ce64ee80e80458 + +# Set environment for production build +ENV NEXT_TELEMETRY_DISABLED=1 + +# Build the application +RUN npm run build + +# Production stage +FROM node:18-alpine AS runner + +# Install curl for health checks and other utilities +RUN apk add --no-cache curl + +# Set working directory +WORKDIR /app + +# Build arguments for runtime configuration +ARG NEXT_PUBLIC_API_URL + +# Set environment +ENV NODE_ENV=production +ENV NEXT_TELEMETRY_DISABLED=1 +ENV NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL:-/} + +# Copy built application +COPY --from=builder /app/.next/standalone ./ +COPY --from=builder /app/.next/static ./.next/static +# Copy public directory (includes hathor-modules.json.gz) +COPY --from=builder /app/public ./public + +# Create non-root user +RUN addgroup -g 1001 -S nodejs && \ + adduser -S nextjs -G nodejs && \ + chown -R nextjs:nodejs /app + +# Switch to non-root user +USER nextjs + +# Expose port +EXPOSE 3000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ + CMD curl -f http://localhost:3000/ || exit 1 + +# Set hostname to 0.0.0.0 to accept connections from outside the container +ENV HOSTNAME=0.0.0.0 + +# Start Next.js +CMD ["node", "server.js"] diff --git a/dapp/Makefile b/dapp/Makefile new file mode 100644 index 0000000..6fa851f --- /dev/null +++ b/dapp/Makefile @@ -0,0 +1,14 @@ +.PHONY: build +build: + ./scripts/deploy.sh $(site) build $(aws_profile) + +.PHONY: sync +sync: + ./scripts/deploy.sh $(site) sync $(aws_profile) + +.PHONY: deploy +deploy: build sync clear_cloudfront_cache + +.PHONY: clear_cloudfront_cache +clear_cloudfront_cache: + ./scripts/deploy.sh $(site) clear_cache $(aws_profile) diff --git a/dapp/QUICKSTART.md b/dapp/QUICKSTART.md new file mode 100644 index 0000000..6eba9cf --- /dev/null +++ b/dapp/QUICKSTART.md @@ -0,0 +1,103 @@ +# Quick Start Guide + +## Getting Started + +### 1. Install Dependencies +```bash +npm install +``` + +### 2. Configure Environment +```bash +cp .env.local.example .env.local +``` + +The default configuration uses mock wallet mode, so you can test immediately without a real wallet. + +### 3. Run Development Server +```bash +npm run dev +``` + +### 4. Open in Browser +Navigate to [http://localhost:3000](http://localhost:3000) + +## Testing with Mock Wallet + +With `NEXT_PUBLIC_USE_MOCK_WALLET=true` (default), you can: + +1. **Connect Wallet**: Click "Connect Wallet" and choose any option +2. **View Mock Balance**: See simulated HTR balance +3. **View Contract Info**: See mock contract state + +All actions are simulated and no real transactions occur. + +## Connecting a Real Wallet + +### Prerequisites +- Hathor Wallet extension or MetaMask with Hathor Snap +- HTR tokens on India Testnet +- Deployed nano contract + +### Steps + +1. **Update Environment**: +```env +NEXT_PUBLIC_USE_MOCK_WALLET=false +NEXT_PUBLIC_CONTRACT_IDS_TESTNET=["your_contract_id_here"] +``` + +2. **Restart Server**: +```bash +npm run dev +``` + +3. **Connect Wallet**: + - Click "Connect Wallet" + - Choose Reown or MetaMask Snaps + - Approve connection in wallet + +4. **Interact with Contract**: + - Use the provided hooks and utilities + - Send transactions via `sendNanoContractTx` + - Confirm transactions in your wallet + +## Network Selection + +Use the network selector in the top-right to switch between: +- **India Testnet** (active) +- **Mainnet** (coming soon) + +## Troubleshooting + +### "Wallet not connected" error +- Ensure wallet extension is installed and unlocked +- Try refreshing the page +- Check that you're on the correct network + +### "Contract state not loaded" +- Verify `NEXT_PUBLIC_CONTRACT_IDS_TESTNET` is set correctly +- Check that the contract exists on the selected network +- Ensure node URL is accessible + +### Build errors +- Run `npm install` to ensure all dependencies are installed +- Delete `.next` folder and rebuild: `rm -rf .next && npm run dev` +- Check that Node.js version is 18 or higher + +## Next Steps + +1. **Deploy Contract**: Deploy your nano contract to India Testnet +2. **Update Config**: Add contract ID to `.env.local` +3. **Build Your dApp**: Modify the template to add your features + +## Development Tips + +- Use mock mode for rapid UI development +- Monitor browser console for errors +- Use React DevTools to inspect component state + +## Support + +- Check [README.md](./README.md) for detailed documentation +- Open an issue on GitHub for bugs or questions diff --git a/dapp/README.md b/dapp/README.md new file mode 100644 index 0000000..3a42c16 --- /dev/null +++ b/dapp/README.md @@ -0,0 +1,330 @@ +# create-hathor-dapp + +A template for building decentralized applications on the Hathor Network using Nano Contracts. This template provides wallet integration with MetaMask Snaps and Reown (WalletConnect), network switching, and all the infrastructure you need to build your dApp. + +## Features + +- **Wallet Integration**: Connect via Reown (WalletConnect) or MetaMask Snaps +- **Network Support**: Testnet and Mainnet support with easy switching +- **Nano Contract Support**: Ready-to-use infrastructure for interacting with nano contracts +- **Contract State Viewing**: Display and refresh contract state data +- **Balance Management**: View wallet balances with authorization +- **Mock Mode**: Test the UI without connecting a real wallet +- **Modern Stack**: Next.js 14, React 18, TypeScript, Tailwind CSS +- **Testing**: Unit tests with Vitest, E2E tests with Playwright + +## Quick Start + +### Prerequisites + +- Node.js 18+ and npm +- A Hathor wallet (Hathor Wallet or MetaMask with Hathor Snap) + +### Installation + +1. Clone the repository: +```bash +git clone +cd create-hathor-dapp +``` + +2. Install dependencies: +```bash +npm install +``` + +3. Configure environment: +```bash +cp .env.example .env.local +``` + +4. Edit `.env.local` with your configuration: + - Get a WalletConnect Project ID from https://cloud.walletconnect.com/ + - Add your nano contract IDs + - Set your preferred default network + +5. Run development server: +```bash +npm run dev +``` + +6. Open [http://localhost:3000](http://localhost:3000) + +## Environment Configuration + +```env +# WalletConnect Project ID (Required) +NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=your_project_id_here + +# Network Configuration +NEXT_PUBLIC_DEFAULT_NETWORK=testnet +NEXT_PUBLIC_USE_MOCK_WALLET=false + +# Contract IDs (JSON array format) +NEXT_PUBLIC_CONTRACT_IDS_TESTNET=["your_contract_id"] +NEXT_PUBLIC_CONTRACT_IDS_MAINNET=[] + +# App Metadata +NEXT_PUBLIC_APP_NAME=Your dApp Name +NEXT_PUBLIC_APP_DESCRIPTION=Your dApp description +``` + +## Architecture + +### Core Infrastructure + +1. **Hathor RPC Service** (`lib/hathorRPC.ts`) + - Implements the Hathor wallet-to-DApp RPC API + - Supports mock mode, MetaMask Snaps, and WalletConnect + - Methods: `htr_getConnectedNetwork`, `htr_getBalance`, `htr_getAddress`, `htr_sendNanoContractTx` + +2. **Hathor Core API** (`lib/hathorCoreAPI.ts`) + - Fetches blockchain data from Hathor nodes + - Methods: `getBlueprintInfo`, `getContractState`, `getContractHistory`, `getTransaction`, `callViewFunction` + +3. **Context Providers** + - `MetaMaskContext`: MetaMask Snaps integration + - `WalletConnectContext`: Reown/WalletConnect integration + - `UnifiedWalletContext`: Unified wallet adapter pattern + - `WalletContext`: Balance and transaction management + - `HathorContext`: Contract state and network management + +### Project Structure + +``` +create-hathor-dapp/ +├── app/ +│ ├── layout.tsx # Root layout with providers +│ ├── page.tsx # Main page +│ └── globals.css # Global styles +├── components/ +│ ├── Header.tsx # Header with wallet connection +│ ├── BalanceCard.tsx # Balance display +│ ├── ContractInfoPanel.tsx # Contract state display +│ ├── NetworkSelector.tsx # Network switching +│ ├── TokenSelector.tsx # Token selection +│ ├── WalletConnectionModal.tsx # Wallet connection +│ └── ui/ # Reusable UI components +├── contexts/ +│ ├── HathorContext.tsx # Hathor network & contract state +│ ├── WalletContext.tsx # Wallet state management +│ ├── MetaMaskContext.tsx # MetaMask Snaps integration +│ ├── WalletConnectContext.tsx # WalletConnect integration +│ └── UnifiedWalletContext.tsx # Unified wallet adapter +├── lib/ +│ ├── config.ts # Environment configuration +│ ├── hathorRPC.ts # RPC service +│ ├── hathorCoreAPI.ts # Core API service +│ ├── utils.ts # Utility functions +│ ├── toast.tsx # Toast notifications +│ └── walletConnectConfig.ts # WalletConnect setup +├── types/ +│ ├── hathor.ts # Hathor types +│ ├── wallet.ts # Wallet adapter types +│ └── index.ts # Common types +├── __tests__/ # Unit and integration tests +├── e2e/ # End-to-end tests +└── __mocks__/ # Test mocks +``` + +## Using the Template + +### Sending Nano Contract Transactions + +```typescript +import { useWallet } from '@/contexts/WalletContext'; +import { useHathor } from '@/contexts/HathorContext'; + +function YourComponent() { + const { sendNanoContractTx } = useWallet(); + const { network, getContractIdForToken, getContractStateForToken } = useHathor(); + + const handleTransaction = async () => { + const contractId = getContractIdForToken('HTR'); + const contractState = getContractStateForToken('HTR'); + const tokenUid = contractState?.token_uid || '00'; + + const result = await sendNanoContractTx({ + network, + nc_id: contractId, + method: 'your_method_name', + args: [arg1, arg2], + actions: [ + { + type: 'deposit', + amount: '1000', // in cents + token: tokenUid, + }, + ], + push_tx: true, + }); + + console.log('Transaction hash:', result.response.hash); + }; + + return ; +} +``` + +### Reading Contract State + +```typescript +import { useHathor } from '@/contexts/HathorContext'; + +function ContractStateDisplay() { + const { getContractStateForToken, coreAPI } = useHathor(); + + const contractState = getContractStateForToken('HTR'); + + // Or fetch directly from API + const fetchState = async () => { + const state = await coreAPI.getContractState('your-contract-id'); + console.log(state); + }; + + return ( +
+

Available Tokens: {contractState?.available_tokens.toString()}

+
+ ); +} +``` + +### Adding New Pages + +Create new pages in the `app/` directory following Next.js App Router conventions: + +```typescript +// app/your-page/page.tsx +'use client'; + +import { useHathor } from '@/contexts/HathorContext'; +import Header from '@/components/Header'; + +export default function YourPage() { + const { isConnected } = useHathor(); + + return ( +
+
{}} /> +
+ {/* Your page content */} +
+
+ ); +} +``` + +## Development + +### Mock Mode + +For testing without a wallet: +```env +NEXT_PUBLIC_USE_MOCK_WALLET=true +``` + +Mock mode simulates: +- Wallet connection +- Balance queries +- Transaction submissions +- Network information + +### Running Tests + +```bash +# Unit tests +npm test + +# Unit tests with UI +npm run test:ui + +# Unit tests with coverage +npm run test:coverage + +# E2E tests +npm run test:e2e + +# E2E tests with UI +npm run test:e2e:ui +``` + +### Building for Production + +```bash +npm run build +npm start +``` + +### Linting + +```bash +npm run lint +``` + +## API Reference + +### Hathor RPC Methods + +| Method | Description | +|--------|-------------| +| `htr_getConnectedNetwork()` | Get the network the wallet is connected to | +| `htr_getBalance(params)` | Get balance for specified tokens | +| `htr_getAddress(params)` | Get wallet address | +| `htr_sendNanoContractTx(params)` | Send a nano contract transaction | + +### Hathor Core API Methods + +| Method | Description | +|--------|-------------| +| `getBlueprintInfo(blueprintId)` | Fetch blueprint information | +| `getContractState(contractId)` | Fetch current contract state | +| `getContractHistory(contractId, limit)` | Fetch contract transaction history | +| `getTransaction(txId)` | Fetch transaction details | +| `callViewFunction(contractId, method, args)` | Call a view function | +| `getClaimableBalance(contractId, address)` | Get claimable balance for an address | + +## Troubleshooting + +### Wallet Not Connecting + +1. Ensure you're on the correct network (testnet/mainnet) +2. Check that your wallet extension is installed and unlocked +3. Try refreshing the page +4. Check browser console for errors + +### Contract State Not Loading + +1. Check network configuration in `.env.local` +2. Verify contract ID is correct +3. Ensure node URL is accessible +4. Check browser console for API errors + +### Transaction Failing + +1. Verify sufficient balance +2. Check transaction parameters +3. Ensure contract has sufficient liquidity +4. Verify network connection + +## Resources + +- [Hathor Documentation](https://docs.hathor.network) +- [Wallet API Reference](https://docs.hathor.network/guides/headless-wallet/http-api/) +- [Nano Contracts Guide](https://docs.hathor.network/guides/nano-contracts/) +- [Hathor Discord](https://discord.gg/hathor) + +## Contributing + +1. Fork the repository +2. Create a feature branch +3. Make your changes +4. Submit a pull request + +## License + +MIT License - see LICENSE file for details + +--- + +Built with Hathor Network diff --git a/dapp/__mocks__/hathorCoreAPI.ts b/dapp/__mocks__/hathorCoreAPI.ts new file mode 100644 index 0000000..a5c9ac9 --- /dev/null +++ b/dapp/__mocks__/hathorCoreAPI.ts @@ -0,0 +1,181 @@ +import { vi } from 'vitest' +import { ContractState, BlueprintInfo, ContractHistory } from '@/types/hathor' +import { Network } from '@/lib/config' + +export const mockBlueprintInfo: BlueprintInfo = { + id: 'test-blueprint-id', + name: 'TestContract', + attributes: { + public_methods: ['deposit', 'withdraw', 'get_balance'], + }, +} + +export const mockContractStates: Record = { + 'contract-htr': { + token_uid: '00', + available_tokens: 100000000n, + total_liquidity_provided: 100000000n, + }, + 'contract-usdc': { + token_uid: '01', + available_tokens: 50000000n, + total_liquidity_provided: 50000000n, + }, +} + +export const mockTransactions = [ + { + tx_id: '0000000000000001', + timestamp: Date.now() - 60000, + nc_method: 'deposit', + nc_caller: 'WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp', + first_block: '0000000000000abc', + is_voided: false, + nc_args_decoded: { + amount: 1000, + }, + nc_events: [ + { + type: 'Deposit', + data: '{"user":"WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp","amount":1000}', + }, + ], + }, + { + tx_id: '0000000000000002', + timestamp: Date.now() - 120000, + nc_method: 'withdraw', + nc_caller: 'WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp', + first_block: '0000000000000abd', + is_voided: false, + nc_args_decoded: { + amount: 500, + }, + nc_events: [ + { + type: 'Withdrawal', + data: '{"user":"WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp","amount":500}', + }, + ], + }, +] + +export const mockContractHistory: ContractHistory = { + transactions: mockTransactions, + total: mockTransactions.length, + hasMore: false, +} + +export class MockHathorCoreAPI { + private baseUrl: string + public network: Network + + constructor(network: Network) { + this.network = network + this.baseUrl = `https://mock-${network}.hathor.network/v1a` + } + + async getBlueprintInfo(blueprintId: string): Promise { + return mockBlueprintInfo + } + + async getContractState(contractId: string): Promise { + return mockContractStates[contractId] || mockContractStates['contract-htr'] + } + + async getContractHistory( + contractId: string, + limit: number = 50, + after?: string + ): Promise { + // Simulate pagination + const allTransactions = mockTransactions + const startIndex = after ? allTransactions.findIndex(tx => tx.tx_id === after) + 1 : 0 + const transactions = allTransactions.slice(startIndex, startIndex + limit) + + return { + transactions, + total: transactions.length, + hasMore: startIndex + limit < allTransactions.length, + } + } + + async getTransaction(txId: string): Promise { + const tx = mockTransactions.find(t => t.tx_id === txId) + if (!tx) { + throw new Error(`Transaction not found: ${txId}`) + } + return tx + } + + async callViewFunction( + contractId: string, + method: string, + args: any[] = [], + callerAddress?: string + ): Promise { + const callKey = `${method}(${args.map(arg => JSON.stringify(arg)).join(', ')})` + + // Mock different view function responses + if (method === 'get_address_balance') { + return { + calls: { + [callKey]: { + value: 5000, + }, + }, + } + } + + if (method === 'get_balance') { + return { + calls: { + [callKey]: { + value: 10000, + }, + }, + } + } + + return { + calls: { + [callKey]: { + value: 0, + }, + }, + } + } + + async getClaimableBalance(contractId: string, callerAddress: string): Promise { + const result = await this.callViewFunction(contractId, 'get_address_balance', [callerAddress], callerAddress) + const callKey = Object.keys(result.calls)[0] + if (callKey && result.calls[callKey]?.value !== undefined) { + return BigInt(result.calls[callKey].value) + } + return 0n + } +} + +// Create mock instance +export const createMockHathorCoreAPI = (network: Network = 'testnet') => { + return new MockHathorCoreAPI(network) +} + +// Vitest mock factory +export const mockHathorCoreAPIFactory = () => { + const mockInstance = createMockHathorCoreAPI() + + return { + HathorCoreAPI: vi.fn().mockImplementation((network: Network) => { + const instance = createMockHathorCoreAPI(network) + return { + getBlueprintInfo: vi.fn().mockImplementation(instance.getBlueprintInfo.bind(instance)), + getContractState: vi.fn().mockImplementation(instance.getContractState.bind(instance)), + getContractHistory: vi.fn().mockImplementation(instance.getContractHistory.bind(instance)), + getTransaction: vi.fn().mockImplementation(instance.getTransaction.bind(instance)), + callViewFunction: vi.fn().mockImplementation(instance.callViewFunction.bind(instance)), + getClaimableBalance: vi.fn().mockImplementation(instance.getClaimableBalance.bind(instance)), + } + }), + } +} diff --git a/dapp/__mocks__/metamask.ts b/dapp/__mocks__/metamask.ts new file mode 100644 index 0000000..d78983a --- /dev/null +++ b/dapp/__mocks__/metamask.ts @@ -0,0 +1,179 @@ +import { vi } from 'vitest' + +export const mockAddress = 'WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp' +export const SNAP_ID = 'npm:@hathor/snap' + +// Mock balance response +export const mockBalanceResponse = { + response: [ + { + token: { id: '00', name: 'Hathor', symbol: 'HTR' }, + balance: { unlocked: 1250.5, locked: 0 }, + transactions: 42, + }, + { + token: { id: '01', name: 'USD Coin', symbol: 'USDC' }, + balance: { unlocked: 500.0, locked: 0 }, + transactions: 15, + }, + ], +} + +// Mock network response +export const mockNetworkResponse = { + network: 'testnet', + genesisHash: '000000000000000000000000000000000000000000000000000000000000test', +} + +// Mock wallet information response +export const mockWalletInfoResponse = { + address0: mockAddress, + network: 'testnet', +} + +// Mock transaction response +export const mockTxResponse = { + hash: '0000000000000000' + Math.random().toString(36).substring(2, 15), + success: true, +} + +// Create mock Ethereum provider (window.ethereum) +export const createMockEthereum = () => { + const eventHandlers: Record void>> = {} + + return { + isMetaMask: true, + request: vi.fn(async ({ method, params }: { method: string; params?: any }) => { + switch (method) { + case 'wallet_requestSnaps': + return { + [SNAP_ID]: { + id: SNAP_ID, + version: '1.0.0', + enabled: true, + }, + } + + case 'wallet_getSnaps': + return { + [SNAP_ID]: { + id: SNAP_ID, + version: '1.0.0', + enabled: true, + }, + } + + case 'wallet_invokeSnap': + const snapMethod = params?.request?.method + const snapParams = params?.request?.params + + switch (snapMethod) { + case 'htr_getAddress': + return { address: mockAddress, index: snapParams?.index || 0 } + + case 'htr_getBalance': + return mockBalanceResponse + + case 'htr_getConnectedNetwork': + return mockNetworkResponse + + case 'htr_getWalletInformation': + return mockWalletInfoResponse + + case 'htr_sendNanoContractTx': + return mockTxResponse + + case 'htr_changeNetwork': + return { + network: snapParams?.newNetwork || 'testnet', + success: true, + } + + default: + return { success: false, error: `Unknown snap method: ${snapMethod}` } + } + + default: + return { success: false, error: `Unknown Ethereum method: ${method}` } + } + }), + on: vi.fn((event: string, handler: (...args: any[]) => void) => { + if (!eventHandlers[event]) { + eventHandlers[event] = [] + } + eventHandlers[event].push(handler) + }), + removeListener: vi.fn((event: string, handler: (...args: any[]) => void) => { + if (eventHandlers[event]) { + eventHandlers[event] = eventHandlers[event].filter(h => h !== handler) + } + }), + emit: vi.fn((event: string, ...args: any[]) => { + if (eventHandlers[event]) { + eventHandlers[event].forEach(handler => handler(...args)) + } + }), + } +} + +// Setup MetaMask global mock +export const setupMetaMaskMock = () => { + const mockEthereum = createMockEthereum() + + Object.defineProperty(window, 'ethereum', { + writable: true, + configurable: true, + value: mockEthereum, + }) + + return mockEthereum +} + +// Remove MetaMask mock +export const cleanupMetaMaskMock = () => { + delete (window as any).ethereum +} + +// Mock MetaMask context value for testing +export const createMockMetaMaskContext = (overrides?: Partial) => ({ + address: mockAddress, + walletNetwork: 'testnet', + isConnected: true, + isInstalled: true, + connect: vi.fn(), + disconnect: vi.fn(), + request: vi.fn(async (method: string, params?: any) => { + const mockEthereum = createMockEthereum() + return mockEthereum.request({ + method: 'wallet_invokeSnap', + params: { + snapId: SNAP_ID, + request: { method, params }, + }, + }) + }), + ...overrides, +}) + +// Helper to test snap not installed scenario +export const createMockEthereumWithoutSnap = () => { + const mockEthereum = createMockEthereum() + + mockEthereum.request = vi.fn(async ({ method }: { method: string; params?: any }) => { + if (method === 'wallet_requestSnaps') { + throw new Error('User rejected snap installation') + } + throw new Error('Snap not installed') + }) + + return mockEthereum +} + +// Helper to test MetaMask not installed scenario +export const createMockWindowWithoutMetaMask = () => { + Object.defineProperty(window, 'ethereum', { + writable: true, + configurable: true, + value: undefined, + }) +} diff --git a/dapp/__mocks__/testUtils.tsx b/dapp/__mocks__/testUtils.tsx new file mode 100644 index 0000000..b4d2667 --- /dev/null +++ b/dapp/__mocks__/testUtils.tsx @@ -0,0 +1,118 @@ +import React, { ReactElement } from 'react' +import { render, RenderOptions } from '@testing-library/react' +import { vi } from 'vitest' + +// Mock fetch globally +export const mockFetch = vi.fn() +global.fetch = mockFetch + +// Helper to create mock fetch responses +export const createMockResponse = (data: any, status: number = 200) => { + return Promise.resolve({ + ok: status >= 200 && status < 300, + status, + statusText: status === 200 ? 'OK' : 'Error', + json: async () => data, + text: async () => JSON.stringify(data), + } as Response) +} + +// Helper to mock fetch with specific responses +export const setupMockFetch = (responses: Record) => { + mockFetch.mockImplementation(async (url: string) => { + const urlStr = url.toString() + + // Check for blueprint endpoint + if (urlStr.includes('/nc_blueprint/')) { + return createMockResponse(responses.blueprint || {}) + } + + // Check for contract state endpoint + if (urlStr.includes('/nano_contract/state')) { + if (urlStr.includes('calls[]=')) { + return createMockResponse(responses.viewFunction || { calls: {} }) + } + return createMockResponse(responses.contractState || { fields: {} }) + } + + // Check for contract history endpoint + if (urlStr.includes('/nano_contract/history')) { + return createMockResponse(responses.contractHistory || { history: [], has_more: false }) + } + + // Check for transaction endpoint + if (urlStr.includes('/transaction')) { + return createMockResponse(responses.transaction || {}) + } + + // Default response + return createMockResponse({}) + }) +} + +// Helper to reset fetch mock +export const resetMockFetch = () => { + mockFetch.mockReset() +} + +// Test wrapper with all providers +interface AllTheProvidersProps { + children: React.ReactNode +} + +export const AllTheProviders: React.FC = ({ children }) => { + return <>{children} +} + +// Custom render function that includes providers +export const renderWithProviders = ( + ui: ReactElement, + options?: Omit +) => { + return render(ui, { wrapper: AllTheProviders, ...options }) +} + +// Helper to wait for async operations +export const waitForAsync = () => new Promise(resolve => setTimeout(resolve, 0)) + +// Helper to create mock timers +export const setupMockTimers = () => { + vi.useFakeTimers() + return { + advanceTime: (ms: number) => vi.advanceTimersByTime(ms), + runAll: () => vi.runAllTimers(), + cleanup: () => vi.useRealTimers(), + } +} + +// Helper to mock console methods +export const mockConsole = () => { + const originalConsole = { ...console } + + const mocks = { + log: vi.spyOn(console, 'log').mockImplementation(() => {}), + error: vi.spyOn(console, 'error').mockImplementation(() => {}), + warn: vi.spyOn(console, 'warn').mockImplementation(() => {}), + } + + return { + ...mocks, + restore: () => { + Object.assign(console, originalConsole) + }, + } +} + +// Helper to create test addresses +export const createTestAddress = (suffix: string = '') => { + return `WYBwT3xLpDnHNtYZiU52oanupVeDKhAvN${suffix || 'p'}` +} + +// Helper to create test transaction hash +export const createTestTxHash = () => { + return '00000000' + Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15) +} + +// Re-export everything from React Testing Library +export * from '@testing-library/react' +export { default as userEvent } from '@testing-library/user-event' diff --git a/dapp/__mocks__/walletConnect.ts b/dapp/__mocks__/walletConnect.ts new file mode 100644 index 0000000..94444ea --- /dev/null +++ b/dapp/__mocks__/walletConnect.ts @@ -0,0 +1,140 @@ +import { vi } from 'vitest' +import { SessionTypes, PairingTypes } from '@walletconnect/types' + +export const mockAddress = 'WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp' + +export const mockSession: SessionTypes.Struct = { + topic: 'mock-session-topic', + relay: { protocol: 'irn' }, + expiry: Math.floor(Date.now() / 1000) + 86400, + acknowledged: true, + controller: 'mock-controller', + namespaces: { + hathor: { + accounts: [`hathor:testnet:${mockAddress}`], + methods: [ + 'htr_getAddress', + 'htr_getBalance', + 'htr_getUtxos', + 'htr_signWithAddress', + 'htr_sendNanoContractTx', + ], + events: [], + }, + }, + requiredNamespaces: {}, + optionalNamespaces: {}, + pairingTopic: 'mock-pairing-topic', + self: { + publicKey: 'mock-public-key', + metadata: { + name: 'Mock dApp', + description: 'Mock dApp', + url: 'http://localhost:3000', + icons: [], + }, + }, + peer: { + publicKey: 'mock-peer-public-key', + metadata: { + name: 'Mock Wallet', + description: 'Mock Wallet', + url: 'http://localhost', + icons: [], + }, + }, +} + +export const mockPairing: PairingTypes.Struct = { + topic: 'mock-pairing-topic', + relay: { protocol: 'irn' }, + peerMetadata: { + name: 'Mock Wallet', + description: 'Mock Wallet', + url: 'http://localhost', + icons: [], + }, + expiry: Math.floor(Date.now() / 1000) + 86400, + active: true, +} + +export const createMockSignClient = () => { + const eventHandlers: Record void>> = {} + + return { + on: vi.fn((event: string, handler: (...args: any[]) => void) => { + if (!eventHandlers[event]) { + eventHandlers[event] = [] + } + eventHandlers[event].push(handler) + }), + connect: vi.fn(async () => ({ + uri: 'wc:mock-uri', + approval: async () => mockSession, + })), + disconnect: vi.fn(async () => {}), + request: vi.fn(), + pairing: { + getAll: vi.fn(() => [mockPairing]), + }, + session: { + length: 1, + keys: ['mock-session-topic'], + get: vi.fn(() => mockSession), + }, + emit: vi.fn((event: string, ...args: any[]) => { + if (eventHandlers[event]) { + eventHandlers[event].forEach(handler => handler(...args)) + } + }), + } +} + +export const createMockWeb3Modal = () => ({ + openModal: vi.fn(), + closeModal: vi.fn(), + subscribeModal: vi.fn((callback: (state: { open: boolean }) => void) => { + return vi.fn() + }), +}) + +// Mock the @walletconnect/sign-client module +export const mockWalletConnectSignClient = { + default: vi.fn().mockImplementation(() => createMockSignClient()), +} + +// Mock the @web3modal/standalone module +export const mockWeb3ModalStandalone = { + Web3Modal: vi.fn().mockImplementation(() => createMockWeb3Modal()), +} + +// Mock the @walletconnect/utils module +export const mockWalletConnectUtils = { + getSdkError: vi.fn((errorKey: string) => ({ + code: 1000, + message: errorKey, + })), +} + +// Helper to setup WalletConnect mocks in tests +export const setupWalletConnectMocks = () => { + vi.mock('@walletconnect/sign-client', () => mockWalletConnectSignClient) + vi.mock('@web3modal/standalone', () => mockWeb3ModalStandalone) + vi.mock('@walletconnect/utils', () => mockWalletConnectUtils) +} + +// Mock WalletConnect context value for testing +export const createMockWalletConnectContext = (overrides?: Partial) => ({ + client: createMockSignClient(), + session: mockSession, + connect: vi.fn(), + disconnect: vi.fn(), + chains: ['hathor:testnet'], + pairings: [mockPairing], + accounts: [`hathor:testnet:${mockAddress}`], + setChains: vi.fn(), + getFirstAddress: vi.fn(() => mockAddress), + isConnected: true, + isInitializing: false, + ...overrides, +}) diff --git a/dapp/__tests__/integration/MetaMaskContext.test.tsx b/dapp/__tests__/integration/MetaMaskContext.test.tsx new file mode 100644 index 0000000..dec4787 --- /dev/null +++ b/dapp/__tests__/integration/MetaMaskContext.test.tsx @@ -0,0 +1,303 @@ +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' +import { renderHook, waitFor } from '@testing-library/react' +import { ReactNode } from 'react' +import { MetaMaskProvider, useMetaMask } from '@/contexts/MetaMaskContext' +import { + setupMetaMaskMock, + cleanupMetaMaskMock, + mockAddress, + SNAP_ID, +} from '@/__mocks__/metamask' + +describe('MetaMaskContext', () => { + beforeEach(() => { + setupMetaMaskMock() + localStorage.clear() + }) + + afterEach(() => { + cleanupMetaMaskMock() + vi.clearAllMocks() + }) + + const wrapper = ({ children }: { children: ReactNode }) => ( + {children} + ) + + describe('Initialization', () => { + it('should initialize with correct default values', () => { + const { result } = renderHook(() => useMetaMask(), { wrapper }) + + expect(result.current.address).toBeNull() + expect(result.current.isConnected).toBe(false) + expect(result.current.isInstalled).toBe(true) // MetaMask mock is installed + }) + + it('should detect MetaMask installation', () => { + const { result } = renderHook(() => useMetaMask(), { wrapper }) + + expect(result.current.isInstalled).toBe(true) + }) + + it('should detect when MetaMask is not installed', () => { + cleanupMetaMaskMock() + + const { result } = renderHook(() => useMetaMask(), { wrapper }) + + expect(result.current.isInstalled).toBe(false) + }) + }) + + describe('Connection', () => { + it('should connect to MetaMask Snap successfully', async () => { + const { result } = renderHook(() => useMetaMask(), { wrapper }) + + await waitFor(async () => { + await result.current.connect() + }) + + await waitFor(() => { + expect(result.current.isConnected).toBe(true) + expect(result.current.address).toBe(mockAddress) + }) + }) + + it('should store wallet type and address in localStorage', async () => { + const { result } = renderHook(() => useMetaMask(), { wrapper }) + + await waitFor(async () => { + await result.current.connect() + }) + + await waitFor(() => { + expect(localStorage.getItem('wallet_type')).toBe('metamask') + expect(localStorage.getItem('address')).toBe(mockAddress) + }) + }) + + it('should throw error when MetaMask is not installed', async () => { + cleanupMetaMaskMock() + + const { result } = renderHook(() => useMetaMask(), { wrapper }) + + await waitFor(async () => { + await expect(result.current.connect()).rejects.toThrow('MetaMask is not installed') + }) + }) + + it('should request snap connection with correct parameters', async () => { + const mockEthereum = window.ethereum + const requestSpy = vi.spyOn(mockEthereum!, 'request') + + const { result } = renderHook(() => useMetaMask(), { wrapper }) + + await waitFor(async () => { + await result.current.connect() + }) + + await waitFor(() => { + expect(requestSpy).toHaveBeenCalledWith({ + method: 'wallet_requestSnaps', + params: { + [SNAP_ID]: { + version: '*', + }, + }, + }) + }) + }) + }) + + describe('Disconnection', () => { + it('should disconnect and clear state', async () => { + const { result } = renderHook(() => useMetaMask(), { wrapper }) + + // Connect first + await waitFor(async () => { + await result.current.connect() + }) + + await waitFor(() => { + expect(result.current.isConnected).toBe(true) + }) + + // Then disconnect + await waitFor(async () => { + await result.current.disconnect() + }) + + await waitFor(() => { + expect(result.current.address).toBeNull() + expect(result.current.isConnected).toBe(false) + }) + }) + + it('should remove localStorage items on disconnect', async () => { + const { result } = renderHook(() => useMetaMask(), { wrapper }) + + // Connect + await waitFor(async () => { + await result.current.connect() + }) + + await waitFor(() => { + expect(localStorage.getItem('wallet_type')).toBe('metamask') + }) + + // Disconnect + await waitFor(async () => { + await result.current.disconnect() + }) + + await waitFor(() => { + expect(localStorage.getItem('wallet_type')).toBeNull() + expect(localStorage.getItem('address')).toBeNull() + }) + }) + }) + + describe('Persisted Connection', () => { + it('should restore connection from localStorage', async () => { + // Setup persisted connection + localStorage.setItem('wallet_type', 'metamask') + localStorage.setItem('address', mockAddress) + + // Mock wallet_getSnaps to simulate already connected snap + const mockEthereum = window.ethereum + const originalRequest = mockEthereum!.request + mockEthereum!.request = vi.fn(async ({ method, params }: any) => { + if (method === 'wallet_getSnaps') { + return { + [SNAP_ID]: { + id: SNAP_ID, + version: '1.0.0', + enabled: true, + }, + } + } + return originalRequest.call(mockEthereum, { method, params }) + }) + + const { result } = renderHook(() => useMetaMask(), { wrapper }) + + await waitFor( + () => { + expect(result.current.isConnected).toBe(true) + expect(result.current.address).toBe(mockAddress) + }, + { timeout: 3000 } + ) + }) + + it('should not restore connection if wallet type is not metamask', async () => { + localStorage.setItem('wallet_type', 'walletconnect') + localStorage.setItem('address', mockAddress) + + const { result } = renderHook(() => useMetaMask(), { wrapper }) + + // Wait a bit to ensure effect has run + await new Promise(resolve => setTimeout(resolve, 100)) + + expect(result.current.isConnected).toBe(false) + expect(result.current.address).toBeNull() + }) + }) + + describe('RPC Requests', () => { + it('should make RPC requests when connected', async () => { + const { result } = renderHook(() => useMetaMask(), { wrapper }) + + // Connect first + await waitFor(async () => { + await result.current.connect() + }) + + await waitFor(() => { + expect(result.current.isConnected).toBe(true) + }) + + // Make a request + const networkResult = await result.current.request('htr_getConnectedNetwork') + + expect(networkResult).toBeDefined() + expect(networkResult).toHaveProperty('network') + }) + + it('should throw error when making request without connection', async () => { + const { result } = renderHook(() => useMetaMask(), { wrapper }) + + await expect(result.current.request('htr_getConnectedNetwork')).rejects.toThrow( + 'MetaMask Snap is not connected' + ) + }) + + it('should invoke snap with correct parameters', async () => { + const mockEthereum = window.ethereum + const requestSpy = vi.spyOn(mockEthereum!, 'request') + + const { result } = renderHook(() => useMetaMask(), { wrapper }) + + // Connect first + await waitFor(async () => { + await result.current.connect() + }) + + await waitFor(() => { + expect(result.current.isConnected).toBe(true) + }) + + // Clear previous calls + requestSpy.mockClear() + + // Make a request + await result.current.request('htr_getBalance', { index: 0 }) + + expect(requestSpy).toHaveBeenCalledWith({ + method: 'wallet_invokeSnap', + params: { + snapId: SNAP_ID, + request: { + method: 'htr_getBalance', + params: { index: 0 }, + }, + }, + }) + }) + }) + + describe('Hook Error Handling', () => { + it.skip('should throw error when used outside provider', () => { + // Note: This test is skipped because renderHook in React 18 doesn't throw synchronously + // The error handling works correctly in runtime, just difficult to test with current tooling + }) + }) + + describe('Network Switching', () => { + it('should handle wallet information checking during connection', async () => { + const mockEthereum = window.ethereum + const requestSpy = vi.spyOn(mockEthereum!, 'request') + + const { result } = renderHook(() => useMetaMask(), { wrapper }) + + await waitFor(async () => { + await result.current.connect() + }) + + await waitFor(() => { + expect(result.current.isConnected).toBe(true) + }) + + // Should have called getWalletInformation during connection + expect(requestSpy).toHaveBeenCalledWith( + expect.objectContaining({ + method: 'wallet_invokeSnap', + params: expect.objectContaining({ + request: expect.objectContaining({ + method: 'htr_getWalletInformation', + }), + }), + }) + ) + }) + }) +}) diff --git a/dapp/__tests__/unit/hathorCoreAPI.test.ts b/dapp/__tests__/unit/hathorCoreAPI.test.ts new file mode 100644 index 0000000..afbc2c0 --- /dev/null +++ b/dapp/__tests__/unit/hathorCoreAPI.test.ts @@ -0,0 +1,412 @@ +import { describe, it, expect, beforeEach, vi } from 'vitest' +import { HathorCoreAPI } from '@/lib/hathorCoreAPI' +import { mockFetch, createMockResponse, resetMockFetch } from '@/__mocks__/testUtils' + +describe('HathorCoreAPI', () => { + let api: HathorCoreAPI + + beforeEach(() => { + resetMockFetch() + api = new HathorCoreAPI('testnet') + }) + + describe('constructor', () => { + it('should initialize with testnet URL', () => { + const testnetApi = new HathorCoreAPI('testnet') + expect(testnetApi).toBeInstanceOf(HathorCoreAPI) + }) + + it('should initialize with mainnet URL', () => { + const mainnetApi = new HathorCoreAPI('mainnet') + expect(mainnetApi).toBeInstanceOf(HathorCoreAPI) + }) + }) + + describe('getBlueprintInfo', () => { + it('should fetch blueprint info successfully', async () => { + const mockBlueprint = { + id: 'test-blueprint-id', + name: 'TestContract', + attributes: { + public_methods: ['deposit', 'withdraw'], + }, + } + + mockFetch.mockResolvedValueOnce(createMockResponse(mockBlueprint)) + + const result = await api.getBlueprintInfo('test-blueprint-id') + + expect(mockFetch).toHaveBeenCalledWith( + expect.stringContaining('/nc_blueprint/test-blueprint-id') + ) + expect(result).toEqual(mockBlueprint) + }) + + it('should throw error on failed request', async () => { + mockFetch.mockResolvedValueOnce(createMockResponse({}, 404)) + + await expect(api.getBlueprintInfo('invalid-id')).rejects.toThrow( + 'Failed to fetch blueprint info' + ) + }) + + it('should handle network errors', async () => { + mockFetch.mockRejectedValueOnce(new Error('Network error')) + + await expect(api.getBlueprintInfo('test-id')).rejects.toThrow('Network error') + }) + }) + + describe('getContractState', () => { + it('should fetch and parse contract state successfully', async () => { + const mockResponse = { + fields: { + token_uid: { value: '00' }, + available_tokens: { value: 100000000n }, + total_liquidity_provided: { value: 100000000n }, + }, + } + + mockFetch.mockResolvedValueOnce(createMockResponse(mockResponse)) + + const result = await api.getContractState('contract-id') + + expect(mockFetch).toHaveBeenCalledWith( + expect.stringContaining('/nano_contract/state?id=contract-id') + ) + expect(result.token_uid).toBe('00') + expect(result.available_tokens).toBe(100000000n) + expect(result.total_liquidity_provided).toBe(100000000n) + }) + + it('should use default values when fields are missing', async () => { + const mockResponse = { + fields: {}, + } + + mockFetch.mockResolvedValueOnce(createMockResponse(mockResponse)) + + const result = await api.getContractState('contract-id') + + expect(result.token_uid).toBe('00') + expect(result.available_tokens).toBe(0n) + expect(result.total_liquidity_provided).toBe(0n) + }) + + it('should fetch custom fields when provided', async () => { + const mockResponse = { + fields: { + token_uid: { value: '00' }, + custom_field: { value: 42 }, + }, + } + + mockFetch.mockResolvedValueOnce(createMockResponse(mockResponse)) + + const result = await api.getContractState('contract-id', ['token_uid', 'custom_field']) + + expect(mockFetch).toHaveBeenCalledWith( + expect.stringContaining('fields[]=token_uid') + ) + expect(mockFetch).toHaveBeenCalledWith( + expect.stringContaining('fields[]=custom_field') + ) + expect(result.custom_field).toBe(42) + }) + + it('should throw error on failed request', async () => { + mockFetch.mockResolvedValueOnce(createMockResponse({}, 500)) + + await expect(api.getContractState('contract-id')).rejects.toThrow( + 'Failed to fetch contract state' + ) + }) + }) + + describe('getContractHistory', () => { + it('should fetch contract history successfully', async () => { + const mockResponse = { + history: [ + { + hash: '0000000000000001', + timestamp: Date.now() - 60000, + nc_method: 'deposit', + nc_address: 'WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp', + first_block: '0000000000000abc', + is_voided: false, + nc_args_decoded: { amount: 1000 }, + nc_events: [ + { + type: 'Deposit', + data: '{"user":"WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp","amount":1000}', + }, + ], + }, + ], + has_more: false, + } + + mockFetch.mockResolvedValueOnce(createMockResponse(mockResponse)) + + const result = await api.getContractHistory('contract-id', 50) + + expect(mockFetch).toHaveBeenCalledWith( + expect.stringContaining('/nano_contract/history?id=contract-id&count=50') + ) + expect(result.transactions).toHaveLength(1) + expect(result.transactions[0].tx_id).toBe('0000000000000001') + expect(result.transactions[0].nc_method).toBe('deposit') + expect(result.hasMore).toBe(false) + }) + + it('should include pagination parameter when provided', async () => { + const mockResponse = { + history: [], + has_more: true, + } + + mockFetch.mockResolvedValueOnce(createMockResponse(mockResponse)) + + await api.getContractHistory('contract-id', 50, 'after-tx-id') + + expect(mockFetch).toHaveBeenCalledWith( + expect.stringContaining('after=after-tx-id') + ) + }) + + it('should handle empty history', async () => { + const mockResponse = { + history: [], + has_more: false, + } + + mockFetch.mockResolvedValueOnce(createMockResponse(mockResponse)) + + const result = await api.getContractHistory('contract-id') + + expect(result.transactions).toHaveLength(0) + expect(result.total).toBe(0) + expect(result.hasMore).toBe(false) + }) + + it('should throw error on failed request', async () => { + mockFetch.mockResolvedValueOnce(createMockResponse({}, 404)) + + await expect(api.getContractHistory('invalid-id')).rejects.toThrow( + 'Failed to fetch contract history' + ) + }) + }) + + describe('getTransaction', () => { + it('should fetch transaction successfully', async () => { + const mockTx = { + hash: '0000000000000001', + timestamp: Date.now(), + inputs: [], + outputs: [], + } + + mockFetch.mockResolvedValueOnce(createMockResponse(mockTx)) + + const result = await api.getTransaction('0000000000000001') + + expect(mockFetch).toHaveBeenCalledWith( + expect.stringContaining('/transaction?id=0000000000000001') + ) + expect(result.hash).toBe('0000000000000001') + }) + + it('should throw error on failed request', async () => { + mockFetch.mockResolvedValueOnce(createMockResponse({}, 404)) + + await expect(api.getTransaction('invalid-tx-id')).rejects.toThrow( + 'Failed to fetch transaction' + ) + }) + }) + + describe('callViewFunction', () => { + it('should call view function without caller address', async () => { + const mockResponse = { + calls: { + 'get_balance()': { + value: 1000, + }, + }, + } + + mockFetch.mockResolvedValueOnce(createMockResponse(mockResponse)) + + const result = await api.callViewFunction('contract-id', 'get_balance', []) + + const callUrl = mockFetch.mock.calls[0][0] as string + expect(callUrl).toContain('/nano_contract/state?') + expect(callUrl).toContain('id=contract-id') + expect(callUrl).toContain('get_balance') + expect(result).toEqual(mockResponse) + }) + + it('should call view function with arguments', async () => { + const mockResponse = { + calls: { + 'get_address_balance("WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp")': { + value: 5000, + }, + }, + } + + mockFetch.mockResolvedValueOnce(createMockResponse(mockResponse)) + + const result = await api.callViewFunction( + 'contract-id', + 'get_address_balance', + ['WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp'] + ) + + const callUrl = mockFetch.mock.calls[0][0] as string + expect(callUrl).toContain('get_address_balance') + expect(callUrl).toContain('WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp') + expect(result).toEqual(mockResponse) + }) + + it('should call view function with caller address', async () => { + const mockResponse = { + calls: { + 'calculate_max()': { + value: 10000, + }, + }, + } + + mockFetch.mockResolvedValueOnce(createMockResponse(mockResponse)) + + await api.callViewFunction( + 'contract-id', + 'calculate_max', + [], + 'WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp' + ) + + expect(mockFetch).toHaveBeenCalled() + }) + + it('should throw error on failed request', async () => { + mockFetch.mockResolvedValueOnce(createMockResponse({}, 500)) + + await expect( + api.callViewFunction('contract-id', 'invalid_method', []) + ).rejects.toThrow('Failed to call view function') + }) + }) + + describe('getMaximumLiquidityRemoval', () => { + it('should get maximum liquidity removal amount', async () => { + const mockResponse = { + calls: { + 'calculate_address_maximum_liquidity_removal("WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp")': { + value: 10000, + }, + }, + } + + mockFetch.mockResolvedValueOnce(createMockResponse(mockResponse)) + + const result = await api.getMaximumLiquidityRemoval( + 'contract-id', + 'WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp' + ) + + expect(result).toBe(10000n) + }) + + it('should return 0n when no result is available', async () => { + const mockResponse = { + calls: {}, + } + + mockFetch.mockResolvedValueOnce(createMockResponse(mockResponse)) + + const result = await api.getMaximumLiquidityRemoval( + 'contract-id', + 'WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp' + ) + + expect(result).toBe(0n) + }) + + it('should handle undefined value', async () => { + const mockResponse = { + calls: { + 'calculate_address_maximum_liquidity_removal("WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp")': { + value: undefined, + }, + }, + } + + mockFetch.mockResolvedValueOnce(createMockResponse(mockResponse)) + + const result = await api.getMaximumLiquidityRemoval( + 'contract-id', + 'WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp' + ) + + expect(result).toBe(0n) + }) + }) + + describe('getClaimableBalance', () => { + it('should get claimable balance', async () => { + const mockResponse = { + calls: { + 'get_address_balance("WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp")': { + value: 5000, + }, + }, + } + + mockFetch.mockResolvedValueOnce(createMockResponse(mockResponse)) + + const result = await api.getClaimableBalance( + 'contract-id', + 'WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp' + ) + + expect(result).toBe(5000n) + }) + + it('should return 0n when no balance is available', async () => { + const mockResponse = { + calls: {}, + } + + mockFetch.mockResolvedValueOnce(createMockResponse(mockResponse)) + + const result = await api.getClaimableBalance( + 'contract-id', + 'WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp' + ) + + expect(result).toBe(0n) + }) + + it('should handle string value conversion to bigint', async () => { + const mockResponse = { + calls: { + 'get_address_balance("WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp")': { + value: '999999999999', + }, + }, + } + + mockFetch.mockResolvedValueOnce(createMockResponse(mockResponse)) + + const result = await api.getClaimableBalance( + 'contract-id', + 'WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp' + ) + + expect(result).toBe(999999999999n) + }) + }) +}) diff --git a/dapp/__tests__/unit/hathorRPC.test.ts b/dapp/__tests__/unit/hathorRPC.test.ts new file mode 100644 index 0000000..157a53f --- /dev/null +++ b/dapp/__tests__/unit/hathorRPC.test.ts @@ -0,0 +1,320 @@ +import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest' +import { HathorRPCService } from '@/lib/hathorRPC' +import { createMockSignClient, mockSession } from '@/__mocks__/walletConnect' + +describe('HathorRPCService', () => { + describe('Mock Mode', () => { + let rpcService: HathorRPCService + + beforeEach(() => { + rpcService = new HathorRPCService(true) + vi.useFakeTimers() + }) + + afterEach(() => { + vi.useRealTimers() + }) + + it('should return mock network data', async () => { + const networkPromise = rpcService.getConnectedNetwork() + vi.advanceTimersByTime(500) + const result = await networkPromise + + expect(result).toEqual({ + network: 'testnet', + genesisHash: '0x123...', + }) + }) + + it('should return mock balance data', async () => { + const balancePromise = rpcService.getBalance({ index: 0 }) + vi.advanceTimersByTime(500) + const result = await balancePromise + + expect(result.response).toHaveLength(1) + expect(result.response[0].token.symbol).toBe('HTR') + expect(result.response[0].balance.unlocked).toBe(1250.5) + }) + + it('should return mock address', async () => { + const addressPromise = rpcService.getAddress({ index: 0 }) + vi.advanceTimersByTime(500) + const result = await addressPromise + + expect(result.address).toBe('WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp') + expect(result.index).toBe(0) + }) + + it('should return mock transaction response', async () => { + const txPromise = rpcService.sendNanoContractTx({ + address: 'WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp', + nc_id: 'contract-id', + nc_blueprint_id: 'blueprint-id', + nc_method: 'deposit', + nc_args: ['32768'], + nc_actions: [] + }) + vi.advanceTimersByTime(500) + const result = await txPromise + + expect(result.hash).toMatch(/^00000000[a-z0-9]+/) + expect(result.success).toBe(true) + expect(result.timestamp).toBeDefined() + }) + + it('should throw error for unimplemented mock method', async () => { + const unknownPromise = rpcService.request('htr_unknownMethod') + vi.advanceTimersByTime(500) + + await expect(unknownPromise).rejects.toThrow('Mock not implemented for method') + }) + + it('should simulate network delay', async () => { + const addressPromise = rpcService.getAddress({ index: 0 }) + + // Advance time to simulate delay + vi.advanceTimersByTime(500) + const result = await addressPromise + + expect(result.address).toBe('WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp') + }) + }) + + describe('WalletConnect Mode', () => { + let rpcService: HathorRPCService + let mockClient: any + + beforeEach(() => { + mockClient = createMockSignClient() + // Pass 'testnet' as the network parameter + rpcService = new HathorRPCService(false, mockClient, mockSession, undefined, 'testnet') + }) + + afterEach(() => { + vi.restoreAllMocks() + }) + + it('should make request through WalletConnect client', async () => { + mockClient.request.mockResolvedValueOnce({ + network: 'testnet', + genesisHash: '0xreal', + }) + + const result = await rpcService.getConnectedNetwork() + + expect(mockClient.request).toHaveBeenCalledWith({ + chainId: 'hathor:testnet', + topic: mockSession.topic, + request: { + method: 'htr_getConnectedNetwork', + params: undefined, + }, + }) + expect(result.network).toBe('testnet') + }) + + it('should pass parameters to WalletConnect request', async () => { + mockClient.request.mockResolvedValueOnce({ + address: 'WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp', + index: 0, + addressPath: "m/44'/280'/0'/0/0", + }) + + await rpcService.getAddress({ index: 0 }) + + expect(mockClient.request).toHaveBeenCalledWith( + expect.objectContaining({ + request: expect.objectContaining({ + method: 'htr_getAddress', + params: { index: 0 }, + }), + }) + ) + }) + + it('should throw error when wallet not connected', async () => { + const disconnectedRpcService = new HathorRPCService(false) + + await expect(disconnectedRpcService.getConnectedNetwork()).rejects.toThrow( + 'Wallet not connected' + ) + }) + + it('should handle WalletConnect request errors', async () => { + mockClient.request.mockRejectedValueOnce(new Error('User rejected')) + + await expect(rpcService.getConnectedNetwork()).rejects.toThrow('User rejected') + }) + + it('should update client and session', () => { + const newMockClient = createMockSignClient() + const newMockSession = { ...mockSession, topic: 'new-topic' } + + rpcService.updateClientAndSession(newMockClient, newMockSession) + + expect(rpcService['client']).toBe(newMockClient) + expect(rpcService['session']).toBe(newMockSession) + }) + }) + + describe('Custom Request Function Mode (MetaMask)', () => { + let rpcService: HathorRPCService + let customRequest: any + + beforeEach(() => { + customRequest = vi.fn() + rpcService = new HathorRPCService(false, undefined, undefined, customRequest) + }) + + it('should use custom request function when provided', async () => { + customRequest.mockResolvedValueOnce({ + address: 'WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp', + index: 0, + }) + + const result = await rpcService.getAddress({ index: 0 }) + + expect(customRequest).toHaveBeenCalledWith('htr_getAddress', { index: 0 }) + expect(result.address).toBe('WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp') + }) + + it('should handle custom request function errors', async () => { + customRequest.mockRejectedValueOnce(new Error('MetaMask error')) + + await expect(rpcService.getBalance({ index: 0 })).rejects.toThrow('MetaMask error') + }) + + it('should prefer custom request over WalletConnect', async () => { + const mockClient = createMockSignClient() + rpcService = new HathorRPCService(false, mockClient, mockSession, customRequest) + + customRequest.mockResolvedValueOnce({ network: 'mainnet' }) + + await rpcService.getConnectedNetwork() + + expect(customRequest).toHaveBeenCalled() + expect(mockClient.request).not.toHaveBeenCalled() + }) + + it('should update custom request function', () => { + const newCustomRequest = vi.fn() + + rpcService.updateClientAndSession(undefined, undefined, newCustomRequest) + + expect(rpcService['customRequest']).toBe(newCustomRequest) + }) + }) + + describe('sendNanoContractTx', () => { + it('should send nano contract transaction with all parameters', async () => { + const mockClient = createMockSignClient() + // Pass 'testnet' as the network parameter + const rpcService = new HathorRPCService(false, mockClient, mockSession, undefined, 'testnet') + + mockClient.request.mockResolvedValueOnce({ + hash: '0000000000000001', + success: true, + }) + + const txParams = { + address: 'WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp', + nc_id: 'contract-id', + nc_blueprint_id: 'blueprint-id', + nc_method: 'deposit', + nc_args: ['32768'], + nc_actions: [ + { + type: 'deposit', + token: '00', + amount: '1000', + }, + ], + } + + const result = await rpcService.sendNanoContractTx(txParams) + + expect(mockClient.request).toHaveBeenCalledWith({ + chainId: 'hathor:testnet', + topic: mockSession.topic, + request: { + method: 'htr_sendNanoContractTx', + params: txParams, + }, + }) + expect(result.success).toBe(true) + }) + }) + + describe('Mode switching', () => { + it('should respect useMock flag throughout lifecycle', async () => { + const mockClient = createMockSignClient() + const mockRpcService = new HathorRPCService(true, mockClient, mockSession) + + vi.useFakeTimers() + const resultPromise = mockRpcService.getConnectedNetwork() + vi.advanceTimersByTime(500) + const result = await resultPromise + vi.useRealTimers() + + expect(result.genesisHash).toBe('0x123...') // Mock value + expect(mockClient.request).not.toHaveBeenCalled() + }) + + it('should switch from mock to real mode', async () => { + const mockClient = createMockSignClient() + mockClient.request.mockResolvedValueOnce({ + network: 'testnet', + genesisHash: '0xreal', + }) + + const rpcService = new HathorRPCService(false, mockClient, mockSession, undefined, 'testnet') + const result = await rpcService.getConnectedNetwork() + + expect(result.genesisHash).toBe('0xreal') + expect(mockClient.request).toHaveBeenCalled() + }) + }) + + describe('Error handling', () => { + let mockClient: any + let rpcService: HathorRPCService + + beforeEach(() => { + mockClient = createMockSignClient() + rpcService = new HathorRPCService(false, mockClient, mockSession, undefined, 'testnet') + }) + + afterEach(() => { + vi.restoreAllMocks() + }) + + it('should handle errors with messages', async () => { + mockClient.request.mockRejectedValueOnce({ + message: 'Specific error message', + }) + + await expect(rpcService.getConnectedNetwork()).rejects.toThrow( + 'Specific error message' + ) + }) + + it('should handle errors without messages', async () => { + mockClient.request.mockRejectedValueOnce({}) + + await expect(rpcService.getConnectedNetwork()).rejects.toThrow( + 'RPC request failed' + ) + }) + + it('should handle custom request errors with messages', async () => { + const customRequest = vi.fn() + const rpcService = new HathorRPCService(false, undefined, undefined, customRequest) + + customRequest.mockRejectedValueOnce({ + message: 'Custom error', + }) + + await expect(rpcService.getConnectedNetwork()).rejects.toThrow('Custom error') + }) + }) +}) diff --git a/dapp/__tests__/unit/utils.test.ts b/dapp/__tests__/unit/utils.test.ts new file mode 100644 index 0000000..ebc2860 --- /dev/null +++ b/dapp/__tests__/unit/utils.test.ts @@ -0,0 +1,172 @@ +import { describe, it, expect } from 'vitest' +import { + cn, + formatAddress, + formatNumber, + formatTokenAmount, + formatBalance, + formatBalanceWithCommas, +} from '@/lib/utils' + +describe('utils', () => { + describe('cn - className utility', () => { + it('should join valid class names', () => { + expect(cn('class1', 'class2', 'class3')).toBe('class1 class2 class3') + }) + + it('should filter out falsy values', () => { + expect(cn('class1', undefined, 'class2', null, false, 'class3')).toBe('class1 class2 class3') + }) + + it('should return empty string for all falsy inputs', () => { + expect(cn(undefined, null, false)).toBe('') + }) + + it('should handle empty input', () => { + expect(cn()).toBe('') + }) + }) + + describe('formatAddress', () => { + it('should format a standard Hathor address', () => { + const address = 'WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp' + const formatted = formatAddress(address) + expect(formatted).toBe('WYBwT3...AvNp') + }) + + it('should handle shorter addresses', () => { + const address = 'WYBwT3xLp' + const formatted = formatAddress(address) + expect(formatted).toBe('WYBwT3...3xLp') + }) + + it('should handle empty string', () => { + expect(formatAddress('')).toBe('') + }) + + it('should preserve format for very short addresses', () => { + const address = 'ABCD' + const formatted = formatAddress(address) + expect(formatted).toBe('ABCD...ABCD') + }) + }) + + describe('formatNumber', () => { + it('should format number with default 2 decimals', () => { + expect(formatNumber(123.456)).toBe('123.46') + }) + + it('should format number with custom decimals', () => { + expect(formatNumber(123.456, 3)).toBe('123.456') + expect(formatNumber(123.456, 1)).toBe('123.5') + expect(formatNumber(123.456, 0)).toBe('123') + }) + + it('should handle integers', () => { + expect(formatNumber(123)).toBe('123.00') + }) + + it('should handle zero', () => { + expect(formatNumber(0)).toBe('0.00') + }) + + it('should handle negative numbers', () => { + expect(formatNumber(-123.456)).toBe('-123.46') + }) + }) + + describe('formatTokenAmount', () => { + it('should format bigint amount correctly (100 = 1.00)', () => { + expect(formatTokenAmount(100n)).toBe('1.00') + }) + + it('should format bigint amount with large value', () => { + expect(formatTokenAmount(123456n)).toBe('1234.56') + }) + + it('should format bigint amount with small value', () => { + expect(formatTokenAmount(50n)).toBe('0.50') + }) + + it('should format bigint amount with very small value', () => { + expect(formatTokenAmount(5n)).toBe('0.05') + }) + + it('should format bigint amount with 1 unit', () => { + expect(formatTokenAmount(1n)).toBe('0.01') + }) + + it('should format bigint zero', () => { + expect(formatTokenAmount(0n)).toBe('0.00') + }) + + it('should format number amount correctly', () => { + expect(formatTokenAmount(100)).toBe('1.00') + expect(formatTokenAmount(12345)).toBe('123.45') + }) + + it('should handle large bigint amounts', () => { + expect(formatTokenAmount(100000000n)).toBe('1000000.00') + }) + + it('should pad with zeros for amounts less than 100', () => { + expect(formatTokenAmount(99n)).toBe('0.99') + expect(formatTokenAmount(10n)).toBe('0.10') + expect(formatTokenAmount(1n)).toBe('0.01') + }) + }) + + describe('formatBalance', () => { + it('should format bigint balance correctly (100 = 1.00)', () => { + expect(formatBalance(100n)).toBe('1.00') + }) + + it('should format bigint balance with large value', () => { + expect(formatBalance(125050n)).toBe('1250.50') + }) + + it('should format bigint balance with small value', () => { + expect(formatBalance(50n)).toBe('0.50') + }) + + it('should format bigint zero balance', () => { + expect(formatBalance(0n)).toBe('0.00') + }) + + it('should format number balance correctly', () => { + expect(formatBalance(100)).toBe('1.00') + expect(formatBalance(125050)).toBe('1250.50') + }) + + it('should handle large balances', () => { + expect(formatBalance(10000000000n)).toBe('100000000.00') + }) + + it('should pad with zeros for small amounts', () => { + expect(formatBalance(5n)).toBe('0.05') + expect(formatBalance(1n)).toBe('0.01') + }) + }) + + describe('formatBalanceWithCommas', () => { + it('should format balance with thousand separators', () => { + expect(formatBalanceWithCommas(123456789n)).toBe('1,234,567.89') + }) + + it('should format small balance without commas', () => { + expect(formatBalanceWithCommas(12345n)).toBe('123.45') + }) + + it('should format large balance with multiple commas', () => { + expect(formatBalanceWithCommas(123456789012n)).toBe('1,234,567,890.12') + }) + + it('should handle zero', () => { + expect(formatBalanceWithCommas(0n)).toBe('0.00') + }) + + it('should handle numbers', () => { + expect(formatBalanceWithCommas(123456789)).toBe('1,234,567.89') + }) + }) +}) diff --git a/dapp/app/escrow/[id]/page.tsx b/dapp/app/escrow/[id]/page.tsx new file mode 100644 index 0000000..91f7239 --- /dev/null +++ b/dapp/app/escrow/[id]/page.tsx @@ -0,0 +1,76 @@ +'use client'; + +import { useState, useEffect, use } from 'react'; +import Link from 'next/link'; +import { useHathor } from '@/contexts/HathorContext'; +import { EscrowDetail } from '@/components/EscrowDetail'; +import { EscrowState } from '@/types/hathor'; +import Header from '@/components/Header'; + +export default function EscrowPage({ params }: { params: Promise<{ id: string }> }) { + const { id } = use(params); + const { fetchEscrowState, escrows } = useHathor(); + const [escrow, setEscrow] = useState(null); + const [isLoading, setIsLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + // Try from cache first + if (escrows[id]) { + setEscrow(escrows[id]); + setIsLoading(false); + return; + } + + // Fetch from fullnode + fetchEscrowState(id) + .then(state => { + if (state) { + setEscrow(state); + } else { + setError('Escrow not found'); + } + }) + .catch(err => setError(err.message)) + .finally(() => setIsLoading(false)); + }, [id, fetchEscrowState, escrows]); + + const handleRefresh = async () => { + setIsLoading(true); + const state = await fetchEscrowState(id); + if (state) setEscrow(state); + setIsLoading(false); + }; + + return ( +
+
{}} /> + +
+
+ + ← Back to Dashboard + + +
+ + {isLoading && ( +
+

Loading escrow...

+
+ )} + + {error && ( +
+

{error}

+

{id}

+
+ )} + + {escrow && } +
+
+ ); +} diff --git a/dapp/app/globals.css b/dapp/app/globals.css new file mode 100644 index 0000000..3251ce5 --- /dev/null +++ b/dapp/app/globals.css @@ -0,0 +1,62 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +:root { + --background: #0f172a; + --foreground: #f1f5f9; +} + +body { + color: var(--foreground); + background: var(--background); + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; +} + +@keyframes bounce-once { + 0%, 100% { + transform: scale(1) translateY(0); + } + 25% { + transform: scale(1.1) translateY(-20px); + } + 50% { + transform: scale(0.95) translateY(0); + } + 75% { + transform: scale(1.05) translateY(-10px); + } +} + +@keyframes spin-slow { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +@keyframes confetti { + 0% { + transform: translateY(-10vh) rotate(0deg); + opacity: 1; + } + 100% { + transform: translateY(100vh) rotate(720deg); + opacity: 0; + } +} + +.animate-bounce-once { + animation: bounce-once 0.8s ease-out; +} + +.animate-spin-slow { + animation: spin-slow 3s linear infinite; +} + +.animate-confetti { + animation: confetti 3s ease-in forwards; + font-size: 2rem; +} diff --git a/dapp/app/layout.tsx b/dapp/app/layout.tsx new file mode 100644 index 0000000..f368bcf --- /dev/null +++ b/dapp/app/layout.tsx @@ -0,0 +1,43 @@ +import type { Metadata } from 'next'; +import { WalletProvider } from '@/contexts/WalletContext'; +import { HathorProvider } from '@/contexts/HathorContext'; +import { WalletConnectProvider } from '@/contexts/WalletConnectContext'; +import { MetaMaskProvider } from '@/contexts/MetaMaskContext'; +import { UnifiedWalletProvider } from '@/contexts/UnifiedWalletContext'; +import { ToastProvider, Toaster } from '@/lib/toast'; +import './globals.css'; + +export const metadata: Metadata = { + title: 'x402 Escrow Manager', + description: 'Manage x402 payment escrows on Hathor Network', + icons: { + icon: '/images/icon.png', + }, +}; + +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + + + + + + + + {children} + + + + + + + + + + ); +} diff --git a/dapp/app/page.tsx b/dapp/app/page.tsx new file mode 100644 index 0000000..ba14303 --- /dev/null +++ b/dapp/app/page.tsx @@ -0,0 +1,90 @@ +'use client'; + +import { useState } from 'react'; +import { useWallet } from '@/contexts/WalletContext'; +import { useHathor } from '@/contexts/HathorContext'; +import Header from '@/components/Header'; +import BalanceCard from '@/components/BalanceCard'; +import { WalletConnectionModal } from '@/components/WalletConnectionModal'; +import { X402Fetch } from '@/components/X402Fetch'; +import { formatAddress } from '@/lib/utils'; + +export default function Home() { + const { address } = useWallet(); + const { network, isConnected } = useHathor(); + const [showWalletModal, setShowWalletModal] = useState(false); + + return ( +
+
{}} /> + +
+ {/* Hero */} +
+

x402 Payment Client

+

+ Access paid HTTP APIs on Hathor Network. Enter a URL, pay with your wallet, get the data. +

+
+ + {/* Wallet bar */} +
+ {isConnected ? ( + <> +
+
+
+ Connected: + {formatAddress(address || '')} + ({network}) +
+
+ + + ) : ( + <> +
+
+ Wallet not connected +
+ + + )} +
+ + {/* x402 Fetch Flow */} + + + {/* How it works */} +
+

How x402 Works

+
+ {[ + { step: '1', title: 'Fetch', desc: 'Request a paid API endpoint' }, + { step: '2', title: '402', desc: 'Server responds with payment requirements' }, + { step: '3', title: 'Pay', desc: 'Deposit funds into an escrow contract' }, + { step: '4', title: 'Access', desc: 'Retry with proof — get the data' }, + ].map(({ step, title, desc }) => ( +
+
{step}
+

{title}

+

{desc}

+
+ ))} +
+
+
+ + +
+ ); +} diff --git a/dapp/components/BalanceCard.tsx b/dapp/components/BalanceCard.tsx new file mode 100644 index 0000000..5532134 --- /dev/null +++ b/dapp/components/BalanceCard.tsx @@ -0,0 +1,66 @@ +'use client'; + +import { useWallet } from '@/contexts/WalletContext'; +import { useHathor } from '@/contexts/HathorContext'; +import { useUnifiedWallet } from '@/contexts/UnifiedWalletContext'; +import { formatBalanceWithCommas } from '@/lib/utils'; +import { toast } from '@/lib/toast'; + +interface BalanceCardProps { + selectedToken: string; +} + +export default function BalanceCard({ selectedToken }: BalanceCardProps) { + const { balance, walletBalance, balanceVerified, isLoadingBalance, refreshBalance } = useWallet(); + const { isConnected, getContractStateForToken, network } = useHathor(); + const { walletType } = useUnifiedWallet(); + + const handleLoadBalance = () => { + // Only show confirmation toast for WalletConnect (not MetaMask Snap) + if (walletType !== 'metamask') { + toast.info('Please confirm the operation in your wallet...'); + } + const tokenUid = getContractStateForToken(selectedToken)?.token_uid || '00'; + refreshBalance(tokenUid, network); + }; + + if (!isConnected) { + return ( +
+
+ YOUR BALANCE +
+

Connect your wallet to view balance

+
+ ); + } + + return ( +
+
+ YOUR BALANCE +
+ +
+
+ Wallet Balance: + {balanceVerified && balance > 0n ? ( + + {formatBalanceWithCommas(balance)} {selectedToken} + + ) : isLoadingBalance ? ( + Loading... + ) : ( + + )} +
+
+
+ ); +} diff --git a/dapp/components/ContractInfoPanel.tsx b/dapp/components/ContractInfoPanel.tsx new file mode 100644 index 0000000..e6271b9 --- /dev/null +++ b/dapp/components/ContractInfoPanel.tsx @@ -0,0 +1,77 @@ +'use client'; + +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; +import { ContractState } from '@/types/hathor'; +import { formatTokenAmount, formatNumber } from '@/lib/utils'; + +interface ContractInfoPanelProps { + contractState: ContractState | null; + loading?: boolean; + token?: string; + title?: string; + description?: string; +} + +export function ContractInfoPanel({ + contractState, + loading, + token = 'HTR', + title = 'Contract Information', + description = 'Current state of the nano contract' +}: ContractInfoPanelProps) { + if (loading) { + return ( + + + + ℹ️ + {title} + + Loading contract state... + + + ); + } + + if (!contractState) { + return ( + + + + ℹ️ + {title} + + No contract data available. Configure contract IDs in your environment variables. + + + ); + } + + return ( + + + + ℹ️ + {title} + + {description} + + +
+
+

Available Tokens

+

{formatTokenAmount(contractState.available_tokens)} {token}

+
+
+

Total Liquidity

+

{formatTokenAmount(contractState.total_liquidity_provided)} {token}

+
+
+

Token UID

+

{contractState.token_uid}

+
+
+
+
+ ); +} diff --git a/dapp/components/CreateEscrowForm.tsx b/dapp/components/CreateEscrowForm.tsx new file mode 100644 index 0000000..c3f8035 --- /dev/null +++ b/dapp/components/CreateEscrowForm.tsx @@ -0,0 +1,173 @@ +'use client'; + +import { useState } from 'react'; +import { useWallet } from '@/contexts/WalletContext'; +import { useHathor } from '@/contexts/HathorContext'; +import { config } from '@/lib/config'; +import { toast } from '@/lib/toast'; + +interface CreateEscrowFormProps { + onCreated?: (ncId: string) => void; +} + +export function CreateEscrowForm({ onCreated }: CreateEscrowFormProps) { + const { sendNanoContractTx, address } = useWallet(); + const { network, addEscrow, isConnected } = useHathor(); + + const [sellerAddress, setSellerAddress] = useState(config.sellerAddress); + const [amount, setAmount] = useState('100'); + const [resourceUrl, setResourceUrl] = useState('http://localhost:3000/weather'); + const [deadlineMinutes, setDeadlineMinutes] = useState('5'); + const [isSubmitting, setIsSubmitting] = useState(false); + const [showForm, setShowForm] = useState(false); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + if (!isConnected || !address) { + toast.error('Connect your wallet first'); + return; + } + + if (!config.blueprintId) { + toast.error('Blueprint ID not configured'); + return; + } + + setIsSubmitting(true); + const deadline = Math.floor(Date.now() / 1000) + parseInt(deadlineMinutes) * 60; + const amountCents = parseInt(amount); + + try { + toast.info('Please confirm the transaction in your wallet...'); + + const result = await sendNanoContractTx({ + network, + blueprint_id: config.blueprintId, + method: 'initialize', + args: [ + sellerAddress, + config.facilitatorAddress, + '00', // HTR token + deadline, + resourceUrl, + 'dapp-escrow', + ], + actions: [{ + type: 'deposit', + amount: String(amountCents), + token: '00', + }], + push_tx: true, + }); + + // Extract ncId from response (varies by wallet type) + const ncId = result?.response?.hash || result?.hash || result?.response?.response?.hash; + if (ncId) { + await addEscrow(ncId); + toast.success(`Escrow created! ID: ${ncId.slice(0, 12)}...`); + setShowForm(false); + onCreated?.(ncId); + } else { + toast.success('Transaction sent! Refresh to see the escrow.'); + console.log('Full result:', result); + } + } catch (error: any) { + toast.error(error.message || 'Failed to create escrow'); + } finally { + setIsSubmitting(false); + } + }; + + if (!showForm) { + return ( + + ); + } + + return ( +
+
+

Create Escrow

+ +
+ +
+
+ + setSellerAddress(e.target.value)} + className="w-full bg-slate-700 border border-slate-600 rounded-lg px-3 py-2 text-white text-sm font-mono" + required + /> +
+ +
+
+ + setAmount(e.target.value)} + min="1" + className="w-full bg-slate-700 border border-slate-600 rounded-lg px-3 py-2 text-white text-sm" + required + /> +

{(parseInt(amount || '0') / 100).toFixed(2)} HTR

+
+ +
+ + +
+
+ +
+ + setResourceUrl(e.target.value)} + className="w-full bg-slate-700 border border-slate-600 rounded-lg px-3 py-2 text-white text-sm" + required + /> +
+ +
+ +
+
+
+ ); +} diff --git a/dapp/components/EscrowDetail.tsx b/dapp/components/EscrowDetail.tsx new file mode 100644 index 0000000..30e5a43 --- /dev/null +++ b/dapp/components/EscrowDetail.tsx @@ -0,0 +1,121 @@ +'use client'; + +import { useState } from 'react'; +import { EscrowState } from '@/types/hathor'; +import { EscrowStatusBadge } from './EscrowStatusBadge'; +import { useWallet } from '@/contexts/WalletContext'; +import { useHathor } from '@/contexts/HathorContext'; +import { formatAddress } from '@/lib/utils'; +import { toast } from '@/lib/toast'; + +interface EscrowDetailProps { + escrow: EscrowState; + onRefund?: () => void; +} + +export function EscrowDetail({ escrow, onRefund }: EscrowDetailProps) { + const { sendNanoContractTx, address } = useWallet(); + const { network, isConnected, refreshEscrows } = useHathor(); + const [isRefunding, setIsRefunding] = useState(false); + + const deadlineDate = new Date(escrow.deadline * 1000); + const isExpired = escrow.deadline < Math.floor(Date.now() / 1000); + const canRefund = escrow.phase === 'LOCKED' && isConnected; + const amountDisplay = (escrow.amount / 100).toFixed(2); + const tokenLabel = escrow.token_uid === '00' ? 'HTR' : escrow.token_uid.slice(0, 8) + '...'; + + const handleRefund = async () => { + if (!canRefund) return; + setIsRefunding(true); + + try { + toast.info('Please confirm the refund in your wallet...'); + + await sendNanoContractTx({ + network, + nc_id: escrow.ncId, + method: 'refund', + args: [], + actions: [{ + type: 'withdrawal', + amount: String(escrow.amount), + token: escrow.token_uid, + address: escrow.buyer, + }], + push_tx: true, + }); + + toast.success('Refund successful! Funds returned.'); + await refreshEscrows(); + onRefund?.(); + } catch (error: any) { + toast.error(error.message || 'Refund failed'); + } finally { + setIsRefunding(false); + } + }; + + const fields = [ + { label: 'Contract ID', value: escrow.ncId, mono: true }, + { label: 'Phase', value: escrow.phase, badge: true }, + { label: 'Amount', value: `${amountDisplay} ${tokenLabel}` }, + { label: 'Buyer', value: escrow.buyer, mono: true }, + { label: 'Seller', value: escrow.seller, mono: true }, + { label: 'Facilitator', value: escrow.facilitator, mono: true }, + { label: 'Token UID', value: escrow.token_uid, mono: true }, + { label: 'Deadline', value: `${deadlineDate.toLocaleString()}${isExpired ? ' (EXPIRED)' : ''}` }, + { label: 'Resource URL', value: escrow.resource_url }, + { label: 'Request Hash', value: escrow.request_hash, mono: true }, + ]; + + return ( +
+
+

Escrow Details

+ +
+ +
+ {fields.map(({ label, value, mono, badge }) => ( +
+ {label} + {badge ? ( + + ) : ( + + {value} + + )} +
+ ))} +
+ + {canRefund && ( +
+ + {isExpired && ( +

Deadline expired — anyone can trigger this refund.

+ )} +
+ )} + + {escrow.phase === 'RELEASED' && ( +
+

Funds have been released to the seller.

+
+ )} + + {escrow.phase === 'REFUNDED' && ( +
+

Funds have been refunded to the buyer.

+
+ )} +
+ ); +} diff --git a/dapp/components/EscrowList.tsx b/dapp/components/EscrowList.tsx new file mode 100644 index 0000000..a4945f3 --- /dev/null +++ b/dapp/components/EscrowList.tsx @@ -0,0 +1,81 @@ +'use client'; + +import Link from 'next/link'; +import { useHathor } from '@/contexts/HathorContext'; +import { EscrowStatusBadge } from './EscrowStatusBadge'; +import { formatAddress } from '@/lib/utils'; + +export function EscrowList() { + const { escrows, isLoadingEscrows, refreshEscrows } = useHathor(); + + const escrowList = Object.values(escrows); + + if (isLoadingEscrows && escrowList.length === 0) { + return ( +
+

Loading escrows...

+
+ ); + } + + if (escrowList.length === 0) { + return ( +
+

No escrows yet

+

Create your first escrow to get started

+
+ ); + } + + return ( +
+
+

Your Escrows

+ +
+ + {escrowList.map((escrow) => { + const isExpired = escrow.deadline < Math.floor(Date.now() / 1000); + const deadlineDate = new Date(escrow.deadline * 1000); + const amountDisplay = (escrow.amount / 100).toFixed(2); + const tokenLabel = escrow.token_uid === '00' ? 'HTR' : escrow.token_uid.slice(0, 8) + '...'; + + return ( + +
+
+ + {formatAddress(escrow.ncId)} +
+ {amountDisplay} {tokenLabel} +
+ +
+ Seller: {formatAddress(escrow.seller)} + + {escrow.phase === 'LOCKED' ? ( + isExpired ? ( + Expired + ) : ( + `Deadline: ${deadlineDate.toLocaleString()}` + ) + ) : ( + escrow.phase === 'RELEASED' ? 'Funds released to seller' : 'Funds refunded' + )} + +
+ + ); + })} +
+ ); +} diff --git a/dapp/components/EscrowStatusBadge.tsx b/dapp/components/EscrowStatusBadge.tsx new file mode 100644 index 0000000..b21e32a --- /dev/null +++ b/dapp/components/EscrowStatusBadge.tsx @@ -0,0 +1,16 @@ +'use client'; + +const STATUS_STYLES: Record = { + LOCKED: 'bg-amber-500/20 text-amber-400 border-amber-500/30', + RELEASED: 'bg-green-500/20 text-green-400 border-green-500/30', + REFUNDED: 'bg-slate-500/20 text-slate-400 border-slate-500/30', +}; + +export function EscrowStatusBadge({ phase }: { phase: string }) { + const style = STATUS_STYLES[phase] || STATUS_STYLES.LOCKED; + return ( + + {phase} + + ); +} diff --git a/dapp/components/Header.tsx b/dapp/components/Header.tsx new file mode 100644 index 0000000..5c6a42c --- /dev/null +++ b/dapp/components/Header.tsx @@ -0,0 +1,92 @@ +'use client'; + +import { useState } from 'react'; +import { useHathor } from '@/contexts/HathorContext'; +import { formatAddress } from '@/lib/utils'; +import { WalletConnectionModal } from './WalletConnectionModal'; +import { NetworkSelector } from './NetworkSelector'; +import TokenSelector from './TokenSelector'; + +interface HeaderProps { + selectedToken: string; + onTokenChange: (token: string) => void; + appName?: string; +} + +export default function Header({ selectedToken, onTokenChange, appName = 'Hathor dApp' }: HeaderProps) { + const { isConnected, address, disconnectWallet, network, switchNetwork } = useHathor(); + const [showModal, setShowModal] = useState(false); + const [showDisconnectMenu, setShowDisconnectMenu] = useState(false); + + const handleConnect = async () => { + setShowModal(true); + }; + + // Handle network change - disconnect wallet first if connected + const handleNetworkChange = (newNetwork: typeof network) => { + if (isConnected) { + disconnectWallet(); + } + switchNetwork(newNetwork); + }; + + return ( + <> +
+
+

{appName}

+
+ +
+ + {isConnected ? ( + <> + +
+ + {showDisconnectMenu && ( + <> +
setShowDisconnectMenu(false)} /> +
+ +
+ + )} +
+ + ) : ( + + )} +
+
+ + + + ); +} diff --git a/dapp/components/HelpIcon.tsx b/dapp/components/HelpIcon.tsx new file mode 100644 index 0000000..c8e44fd --- /dev/null +++ b/dapp/components/HelpIcon.tsx @@ -0,0 +1,46 @@ +'use client'; + +import { useState } from 'react'; + +interface HelpIconProps { + text: string; + className?: string; +} + +export default function HelpIcon({ text, className = '' }: HelpIconProps) { + const [isVisible, setIsVisible] = useState(false); + + return ( +
+ setIsVisible(true)} + onMouseLeave={() => setIsVisible(false)} + onClick={(e) => { + e.stopPropagation(); + setIsVisible(!isVisible); + }} + className="inline-flex items-center justify-center w-4 h-4 text-xs text-slate-400 hover:text-slate-300 cursor-help transition-colors" + > + + + + + + {isVisible && ( +
+
+

{text}

+
+ )} +
+ ); +} diff --git a/dapp/components/NetworkSelector.tsx b/dapp/components/NetworkSelector.tsx new file mode 100644 index 0000000..e2ae365 --- /dev/null +++ b/dapp/components/NetworkSelector.tsx @@ -0,0 +1,34 @@ +'use client'; + +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; +import { Network } from '@/lib/config'; + +interface NetworkSelectorProps { + value: Network; + onChange: (network: Network) => void; +} + +export function NetworkSelector({ value, onChange }: NetworkSelectorProps) { + const handleChange = (value: string) => { + onChange(value as Network); + }; + + const networkLabels: Record = { + privatenet: 'Privatenet', + testnet: 'Testnet', + mainnet: 'Mainnet', + }; + + return ( + + ); +} diff --git a/dapp/components/TokenSelector.tsx b/dapp/components/TokenSelector.tsx new file mode 100644 index 0000000..bfb3b7b --- /dev/null +++ b/dapp/components/TokenSelector.tsx @@ -0,0 +1,32 @@ +'use client'; + +import { useHathor } from '@/contexts/HathorContext'; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; + +interface TokenSelectorProps { + selectedToken: string; + onTokenChange: (token: string) => void; +} + +export default function TokenSelector({ selectedToken, onTokenChange }: TokenSelectorProps) { + const { contractStates } = useHathor(); + + // Get available tokens from contract states + const availableTokens = Object.keys(contractStates); + const isDisabled = availableTokens.length === 0; + + return ( + + ); +} diff --git a/dapp/components/WalletConnectionModal.tsx b/dapp/components/WalletConnectionModal.tsx new file mode 100644 index 0000000..b48312a --- /dev/null +++ b/dapp/components/WalletConnectionModal.tsx @@ -0,0 +1,125 @@ +'use client'; + +import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog'; +import { Button } from '@/components/ui/button'; +import { useWalletConnect } from '@/contexts/WalletConnectContext'; +import { useMetaMask } from '@/contexts/MetaMaskContext'; +import { useHathor } from '@/contexts/HathorContext'; +import { useState, useEffect } from 'react'; + +interface WalletConnectionModalProps { + open: boolean; + onOpenChange: (open: boolean) => void; +} + +export function WalletConnectionModal({ open, onOpenChange }: WalletConnectionModalProps) { + const { connect: connectWalletConnect, isInitializing } = useWalletConnect(); + const { connect: connectMetaMask, isInstalled: isMetaMaskInstalled } = useMetaMask(); + const { network } = useHathor(); + const [isConnecting, setIsConnecting] = useState(false); + const [connectingWallet, setConnectingWallet] = useState<'reown' | 'metamask' | null>(null); + const [error, setError] = useState(null); + + useEffect(() => { + if (!open) { + setIsConnecting(false); + setConnectingWallet(null); + setError(null); + } + }, [open]); + + const handleReownConnect = async () => { + try { + setIsConnecting(true); + setConnectingWallet('reown'); + setError(null); + await connectWalletConnect(network); + onOpenChange(false); + } catch (error: any) { + console.error('Failed to connect via Reown:', error); + if (error?.message?.includes('not initialized yet')) { + setError('Wallet is initializing. Please wait a moment and try again.'); + } else if (error?.message?.includes('User closed the modal')) { + setError(null); // User intentionally closed, don't show error + } else if (error?.message?.includes('Network mismatch')) { + setError(error.message); // Show the full network mismatch error + } else { + setError('Failed to connect. Please try again.'); + } + } finally { + setIsConnecting(false); + setConnectingWallet(null); + } + }; + + const handleMetamaskConnect = async () => { + if (!isMetaMaskInstalled) { + setError('MetaMask is not installed. Please install MetaMask extension first.'); + return; + } + + try { + setIsConnecting(true); + setConnectingWallet('metamask'); + setError(null); + await connectMetaMask(network); + onOpenChange(false); + } catch (error: any) { + console.error('Failed to connect via MetaMask:', error); + if (error?.message?.includes('not installed')) { + setError('MetaMask is not installed. Please install MetaMask extension first.'); + } else if (error?.message?.includes('User rejected')) { + setError(null); // User intentionally rejected, don't show error + } else { + setError(error?.message || 'Failed to connect to MetaMask. Please try again.'); + } + } finally { + setIsConnecting(false); + setConnectingWallet(null); + } + }; + + const isReownButtonDisabled = isConnecting || isInitializing; + const isMetaMaskButtonDisabled = isConnecting || !isMetaMaskInstalled; + + return ( + + + + Connect Wallet + + Choose your preferred wallet connection method + + +
+ {error && ( +
+ {error} +
+ )} + {isInitializing && ( +
+ Initializing wallet connection... +
+ )} + + +
+
+
+ ); +} diff --git a/dapp/components/X402Fetch.tsx b/dapp/components/X402Fetch.tsx new file mode 100644 index 0000000..eddc919 --- /dev/null +++ b/dapp/components/X402Fetch.tsx @@ -0,0 +1,426 @@ +'use client'; + +import { useState } from 'react'; +import { useWallet } from '@/contexts/WalletContext'; +import { useHathor } from '@/contexts/HathorContext'; +import { config } from '@/lib/config'; +import { toast } from '@/lib/toast'; +import { EscrowStatusBadge } from './EscrowStatusBadge'; +import { formatAddress } from '@/lib/utils'; + +interface PaymentOption { + scheme: string; + network: string; + asset: string; + amount: string; + description: string; + resource: string; + payTo: string; + maxTimeoutSeconds: number; + extra: { + facilitatorUrl: string; + facilitatorAddress: string; + blueprintId: string; + deadlineSeconds: number; + }; +} + +interface PaymentHistory { + id: string; + url: string; + ncId: string; + amount: string; + asset: string; + timestamp: Date; + resourceData: any; + status: 'paid' | 'failed'; +} + +type Step = 'idle' | 'fetching' | 'got402' | 'creating_escrow' | 'waiting_confirmation' | 'retrying' | 'done' | 'error'; + +export function X402Fetch() { + const { sendNanoContractTx, address, refreshBalance } = useWallet(); + const { network, isConnected, addEscrow } = useHathor(); + + const [url, setUrl] = useState('http://localhost:3001/weather'); + const [step, setStep] = useState('idle'); + const [paymentOptions, setPaymentOptions] = useState([]); + const [selectedOption, setSelectedOption] = useState(null); + const [resourceData, setResourceData] = useState(null); + const [error, setError] = useState(null); + const [ncId, setNcId] = useState(null); + const [history, setHistory] = useState([]); + + const reset = () => { + setStep('idle'); + setPaymentOptions([]); + setSelectedOption(null); + setResourceData(null); + setError(null); + setNcId(null); + }; + + // Step 1: Fetch the URL, expect 402 + const handleFetch = async () => { + reset(); + setStep('fetching'); + + try { + const resp = await fetch(url, { mode: 'cors' }); + + if (resp.ok) { + const data = await resp.json(); + setResourceData(data); + setStep('done'); + toast.success('Resource is free — no payment needed!'); + return; + } + + if (resp.status !== 402) { + throw new Error(`Unexpected status: ${resp.status}`); + } + + const body = await resp.json(); + if (!body.accepts || body.accepts.length === 0) { + throw new Error('402 response has no payment options'); + } + + setPaymentOptions(body.accepts); + setSelectedOption(body.accepts[0]); + setStep('got402'); + } catch (err: any) { + console.error('X402 fetch error:', err); + setError(err.message || 'Failed to fetch'); + setStep('error'); + } + }; + + // Step 2: Create escrow and pay + const handlePay = async () => { + if (!selectedOption || !isConnected || !address) return; + + const opt = selectedOption; + setStep('creating_escrow'); + + try { + const deadline = Math.floor(Date.now() / 1000) + opt.extra.deadlineSeconds; + const amount = parseInt(opt.amount); + + toast.info('Confirm the escrow deposit in your wallet...'); + + const result = await sendNanoContractTx({ + network, + blueprint_id: opt.extra.blueprintId, + method: 'initialize', + args: [ + opt.payTo, + opt.extra.facilitatorAddress, + opt.asset, + deadline, + opt.resource, + 'dapp-x402-fetch', + ], + actions: [{ + type: 'deposit', + amount: String(amount), + token: opt.asset, + }], + push_tx: true, + }); + + const escrowId = result?.response?.hash || result?.hash || result?.response?.response?.hash; + if (!escrowId) { + throw new Error('No transaction hash in response'); + } + + setNcId(escrowId); + await addEscrow(escrowId); + toast.success(`Escrow created: ${escrowId.slice(0, 12)}...`); + + // Step 3: Wait for confirmation + setStep('waiting_confirmation'); + await waitForConfirmation(escrowId); + + // Step 4: Retry with payment proof + setStep('retrying'); + const paymentPayload = { + scheme: 'hathor-escrow', + network: `hathor:${network}`, + payload: { + ncId: escrowId, + depositTxId: escrowId, + buyerAddress: address, + }, + }; + + const paidResp = await fetch(url, { + headers: { 'X-Payment': JSON.stringify(paymentPayload) }, + }); + + if (paidResp.status !== 200) { + const errBody = await paidResp.json().catch(() => ({})); + throw new Error(errBody.reason || errBody.error || `Payment rejected: ${paidResp.status}`); + } + + const data = await paidResp.json(); + setResourceData(data); + setStep('done'); + toast.success('Resource received!'); + + // Add to history + setHistory(prev => [{ + id: escrowId, + url, + ncId: escrowId, + amount: opt.amount, + asset: opt.asset, + timestamp: new Date(), + resourceData: data, + status: 'paid', + }, ...prev]); + + refreshBalance('00', network); + } catch (err: any) { + setError(err.message); + setStep('error'); + toast.error(err.message); + } + }; + + const waitForConfirmation = async (txId: string) => { + const nodeUrl = config.hathorNodeUrls[network]; + for (let i = 0; i < 60; i++) { + try { + const resp = await fetch(`${nodeUrl}/transaction?id=${txId}`); + const data = await resp.json(); + if (data.success && data.meta?.first_block) return; + } catch { /* retry */ } + await new Promise(r => setTimeout(r, 1000)); + } + throw new Error('Transaction confirmation timeout (60s)'); + }; + + const amountDisplay = selectedOption + ? `${(parseInt(selectedOption.amount) / 100).toFixed(2)} ${selectedOption.asset === '00' ? 'HTR' : 'tokens'}` + : ''; + + return ( +
+ {/* URL Input */} +
+

Access a Paid Resource

+

+ Enter the URL of an x402-enabled API. The dApp will handle the payment flow automatically. +

+ +
+ setUrl(e.target.value)} + placeholder="https://api.example.com/data" + className="flex-1 bg-slate-700 border border-slate-600 rounded-lg px-4 py-3 text-white font-mono text-sm" + disabled={step !== 'idle' && step !== 'error' && step !== 'done'} + /> + +
+
+ + {/* Step: Fetching */} + {step === 'fetching' && ( +
+
Fetching resource...
+

Requesting {url}

+
+ )} + + {/* Step: Got 402 — show payment options */} + {step === 'got402' && selectedOption && ( +
+
+ 💰 +
+

402 — Payment Required

+

This resource requires payment to access

+
+
+ +
+
+ Resource + {selectedOption.resource} +
+
+ Amount + {amountDisplay} +
+
+ Pay to (seller) + {formatAddress(selectedOption.payTo)} +
+
+ Facilitator + {formatAddress(selectedOption.extra.facilitatorAddress)} +
+
+ Deadline + {selectedOption.extra.deadlineSeconds}s +
+ {selectedOption.description && ( +
+ Description + {selectedOption.description} +
+ )} +
+ + {paymentOptions.length > 1 && ( +
+ +
+ {paymentOptions.map((opt, i) => ( + + ))} +
+
+ )} + +
+ + +
+
+ )} + + {/* Step: Creating escrow */} + {step === 'creating_escrow' && ( +
+
Creating escrow...
+

Confirm the deposit in your wallet

+
+ )} + + {/* Step: Waiting confirmation */} + {step === 'waiting_confirmation' && ( +
+
Waiting for on-chain confirmation...
+

+ Escrow ID: {ncId?.slice(0, 16)}... +

+

This usually takes 8-16 seconds

+
+ )} + + {/* Step: Retrying */} + {step === 'retrying' && ( +
+
Payment verified! Fetching resource...
+

Retrying request with payment proof

+
+ )} + + {/* Step: Done — show resource */} + {step === 'done' && resourceData && ( +
+
+ +
+

Resource Received

+ {ncId &&

Paid via escrow {formatAddress(ncId)}

} +
+
+ +
+            {JSON.stringify(resourceData.data || resourceData, null, 2)}
+          
+ + +
+ )} + + {/* Step: Error */} + {step === 'error' && ( +
+
+ +

Error

+
+

{error}

+ +
+ )} + + {/* Payment History */} + {history.length > 0 && ( +
+

Payment History

+
+ {history.map((entry) => ( +
+
+

{entry.url}

+

+ {entry.timestamp.toLocaleTimeString()} — Escrow: {formatAddress(entry.ncId)} +

+
+
+

+ {(parseInt(entry.amount) / 100).toFixed(2)} {entry.asset === '00' ? 'HTR' : 'tokens'} +

+ +
+
+ ))} +
+
+ )} +
+ ); +} diff --git a/dapp/components/ui/button.tsx b/dapp/components/ui/button.tsx new file mode 100644 index 0000000..801d09b --- /dev/null +++ b/dapp/components/ui/button.tsx @@ -0,0 +1,44 @@ +import * as React from "react" +import { cn } from "@/lib/utils" + +export interface ButtonProps + extends React.ButtonHTMLAttributes { + variant?: 'default' | 'outline' | 'ghost' | 'destructive' + size?: 'default' | 'sm' | 'lg' | 'icon' +} + +const Button = React.forwardRef( + ({ className, variant = 'default', size = 'default', ...props }, ref) => { + const baseStyles = "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none" + + const variants = { + default: "bg-blue-600 text-white hover:bg-blue-700", + outline: "border border-slate-700 bg-transparent hover:bg-slate-700 text-white", + ghost: "hover:bg-slate-700 text-white", + destructive: "bg-red-600 text-white hover:bg-red-700" + } + + const sizes = { + default: "h-10 py-2 px-4", + sm: "h-9 px-3 rounded-md", + lg: "h-11 px-8 rounded-md", + icon: "h-10 w-10" + } + + return ( + + ) +}) +SelectTrigger.displayName = "SelectTrigger" + +const SelectValue = ({ placeholder, labels }: { placeholder?: string; labels?: Record }) => { + const context = React.useContext(SelectContext) + if (!context) throw new Error('SelectValue must be used within Select') + + const displayValue = labels?.[context.value] || context.value || placeholder + return {displayValue} +} + +const SelectContent = ({ children, className }: { children: React.ReactNode; className?: string }) => { + const context = React.useContext(SelectContext) + if (!context) throw new Error('SelectContent must be used within Select') + + if (!context.open) return null + + return ( + <> +
context.setOpen(false)} + /> +
+ {children} +
+ + ) +} + +interface SelectItemProps { + value: string + disabled?: boolean + className?: string + children: React.ReactNode +} + +const SelectItem = ({ value, disabled, className, children }: SelectItemProps) => { + const context = React.useContext(SelectContext) + if (!context) throw new Error('SelectItem must be used within Select') + + const handleClick = () => { + if (!disabled) { + context.onValueChange(value) + context.setOpen(false) + } + } + + return ( +
+ {children} +
+ ) +} + +export { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } diff --git a/dapp/contexts/HathorContext.tsx b/dapp/contexts/HathorContext.tsx new file mode 100644 index 0000000..c4abd14 --- /dev/null +++ b/dapp/contexts/HathorContext.tsx @@ -0,0 +1,216 @@ +'use client'; + +import React, { createContext, useContext, useState, useEffect, useCallback, ReactNode } from 'react'; +import { HathorCoreAPI } from '@/lib/hathorCoreAPI'; +import { EscrowState, ContractState } from '@/types/hathor'; +import { config, Network } from '@/lib/config'; +import { useWalletConnect } from './WalletConnectContext'; +import { useMetaMask } from './MetaMaskContext'; +import { useWallet } from './WalletContext'; +import { getEscrowIds, addEscrowId } from '@/lib/escrowStore'; + +const ESCROW_FIELDS = ['buyer', 'seller', 'facilitator', 'token_uid', 'amount', 'phase', 'deadline', 'resource_url', 'request_hash']; + +interface HathorContextType { + isConnected: boolean; + address: string | null; + network: Network; + coreAPI: HathorCoreAPI; + connectWallet: () => Promise; + disconnectWallet: () => Promise; + switchNetwork: (network: Network) => Promise; + // Compat with template components + contractStates: Record; + getContractStateForToken: (token: string) => ContractState | null; + getContractIdForToken: (token: string) => string | null; + // Escrow state + escrows: Record; + isLoadingEscrows: boolean; + refreshEscrows: () => Promise; + addEscrow: (ncId: string) => Promise; + fetchEscrowState: (ncId: string) => Promise; +} + +const HathorContext = createContext(undefined); + +const NETWORK_STORAGE_KEY = 'hathor_selected_network'; + +const getInitialNetwork = (): Network => { + if (typeof window !== 'undefined') { + const stored = localStorage.getItem(NETWORK_STORAGE_KEY); + if (stored === 'mainnet' || stored === 'testnet') return stored; + } + return config.defaultNetwork; +}; + +export function HathorProvider({ children }: { children: ReactNode }) { + const walletConnect = useWalletConnect(); + const metaMask = useMetaMask(); + const wallet = useWallet(); + const [address, setAddress] = useState(null); + const [network, setNetwork] = useState(getInitialNetwork); + const [coreAPI, setCoreAPI] = useState(() => new HathorCoreAPI(getInitialNetwork())); + const [escrows, setEscrows] = useState>({}); + const [isLoadingEscrows, setIsLoadingEscrows] = useState(false); + + const isConnected = walletConnect.isConnected || metaMask.isConnected; + + useEffect(() => { + setCoreAPI(new HathorCoreAPI(network)); + }, [network]); + + useEffect(() => { + if (isConnected) { + if (walletConnect.isConnected) { + const addr = walletConnect.getFirstAddress(); + setAddress(addr); + const walletNetwork = walletConnect.getConnectedNetwork(); + if (walletNetwork && walletNetwork !== network) { + setNetwork(walletNetwork); + localStorage.setItem(NETWORK_STORAGE_KEY, walletNetwork); + } + } else if (metaMask.isConnected) { + setAddress(metaMask.address); + if (metaMask.walletNetwork && metaMask.walletNetwork !== network) { + setNetwork(metaMask.walletNetwork); + localStorage.setItem(NETWORK_STORAGE_KEY, metaMask.walletNetwork); + } + } + } else { + setAddress(null); + wallet.setBalance(0n); + } + }, [isConnected, walletConnect.isConnected, metaMask.isConnected, walletConnect, metaMask]); + + const fetchEscrowState = useCallback(async (ncId: string): Promise => { + const api = new HathorCoreAPI(network); + let state; + try { + state = await api.getContractState(ncId, ESCROW_FIELDS); + } catch { + return null; + } + if (!state || !state.phase) return null; + return { + ncId, + buyer: state.buyer || '', + seller: state.seller || '', + facilitator: state.facilitator || '', + token_uid: state.token_uid || '00', + amount: typeof state.amount === 'bigint' ? Number(state.amount) : (state.amount || 0), + phase: state.phase as EscrowState['phase'], + deadline: state.deadline || 0, + resource_url: state.resource_url || '', + request_hash: state.request_hash || '', + }; + }, [network]); + + const refreshEscrows = useCallback(async () => { + setIsLoadingEscrows(true); + const ids = getEscrowIds(); + const results: Record = {}; + + // Mock mode + if (config.useMockWallet && ids.length === 0) { + setEscrows({}); + setIsLoadingEscrows(false); + return; + } + + for (const ncId of ids) { + if (config.useMockWallet) { + results[ncId] = { + ncId, + buyer: 'WMockBuyerAddress1234567890abcdef', + seller: config.sellerAddress || 'WMockSellerAddr', + facilitator: config.facilitatorAddress || 'WMockFacAddr', + token_uid: '00', + amount: 100, + phase: 'LOCKED', + deadline: Math.floor(Date.now() / 1000) + 300, + resource_url: 'http://localhost:3001/weather', + request_hash: 'mock-hash', + }; + continue; + } + + try { + const state = await fetchEscrowState(ncId); + if (state) results[ncId] = state; + } catch (err) { + // Remove stale escrow IDs that no longer exist on-chain + console.warn(`Escrow ${ncId} not found, removing from tracker`); + const { removeEscrowId } = await import('@/lib/escrowStore'); + removeEscrowId(ncId); + } + } + + setEscrows(results); + setIsLoadingEscrows(false); + }, [fetchEscrowState]); + + const addEscrowAndRefresh = useCallback(async (ncId: string) => { + addEscrowId(ncId); + const state = await fetchEscrowState(ncId); + if (state) { + setEscrows(prev => ({ [ncId]: state, ...prev })); + } + }, [fetchEscrowState]); + + // Load escrows on mount and periodically + useEffect(() => { + refreshEscrows(); + const interval = setInterval(refreshEscrows, 15000); + return () => clearInterval(interval); + }, [refreshEscrows]); + + const connectWallet = async () => { + await walletConnect.connect(network); + }; + + const disconnectWallet = async () => { + if (walletConnect.isConnected) await walletConnect.disconnect(); + if (metaMask.isConnected) await metaMask.disconnect(); + localStorage.removeItem('wallet_type'); + }; + + const switchNetwork = async (newNetwork: Network) => { + setNetwork(newNetwork); + localStorage.setItem(NETWORK_STORAGE_KEY, newNetwork); + if (typeof (walletConnect as any).switchNetwork === 'function') { + (walletConnect as any).switchNetwork(newNetwork).catch(() => {}); + } + }; + + return ( + token === 'HTR' ? { token_uid: '00', available_tokens: 0n, total_liquidity_provided: 0n } : null, + getContractIdForToken: () => null, + escrows, + isLoadingEscrows, + refreshEscrows, + addEscrow: addEscrowAndRefresh, + fetchEscrowState, + }} + > + {children} + + ); +} + +export function useHathor() { + const context = useContext(HathorContext); + if (context === undefined) { + throw new Error('useHathor must be used within a HathorProvider'); + } + return context; +} diff --git a/dapp/contexts/MetaMaskContext.tsx b/dapp/contexts/MetaMaskContext.tsx new file mode 100644 index 0000000..b2d3e5a --- /dev/null +++ b/dapp/contexts/MetaMaskContext.tsx @@ -0,0 +1,212 @@ +'use client'; + +import React, { createContext, ReactNode, useCallback, useContext, useEffect, useMemo, useState } from 'react'; +import { HathorRPCService } from '@/lib/hathorRPC'; +import { config, Network } from '@/lib/config'; + +interface IMetaMaskContext { + address: string | null; + walletNetwork: Network | null; + isConnected: boolean; + isInstalled: boolean; + connect: (targetNetwork?: Network) => Promise; + disconnect: () => Promise; + request: (method: string, params?: any) => Promise; +} + +const MetaMaskContext = createContext({} as IMetaMaskContext); + +const SNAP_ID = 'npm:@hathor/snap'; +const SNAP_VERSION = '*'; // Use latest version + +export function MetaMaskProvider({ children }: { children: ReactNode | ReactNode[] }) { + const [address, setAddress] = useState(null); + const [walletNetwork, setWalletNetwork] = useState(null); + const [isConnected, setIsConnected] = useState(false); + const [isInstalled, setIsInstalled] = useState(false); + + // Helper method to call MetaMask Snap and parse JSON response + const metamask_request = useCallback(async (method: string, params?: any): Promise => { + if (!window.ethereum) { + throw new Error('MetaMask is not installed'); + } + + // Build request object - only include params if defined (MetaMask requires params to be object/array, not undefined) + const request: { method: string; params?: any } = { method }; + if (params !== undefined) { + request.params = params; + } + + const resultStr = await window.ethereum.request({ + method: 'wallet_invokeSnap', + params: { + snapId: SNAP_ID, + request, + }, + }); + + return typeof resultStr === 'string' ? JSON.parse(resultStr) : resultStr; + }, []); + + // Create RPC service instance configured for MetaMask + const [rpcService] = useState(() => new HathorRPCService(config.useMockWallet, undefined, undefined, metamask_request)); + + // Check if MetaMask is installed + useEffect(() => { + const checkMetaMask = () => { + if (typeof window !== 'undefined' && window.ethereum) { + setIsInstalled(true); + } + }; + checkMetaMask(); + }, []); + + // Check persisted connection on mount + useEffect(() => { + const checkPersistedConnection = async () => { + if (typeof window === 'undefined' || !window.ethereum) return; + + try { + const walletType = localStorage.getItem('wallet_type'); + if (walletType !== 'metamask') return; + + // Check if snap is already connected + const snaps = await window.ethereum.request({ + method: 'wallet_getSnaps', + }); + + if (snaps?.[SNAP_ID]) { + // Get wallet information from snap (no user approval required) + const result = await rpcService.getWalletInformation(); + + // MetaMask Snap returns response in nested format + const walletInfo = (result as any)?.response || result; + if (walletInfo?.address0) { + setAddress(walletInfo.address0); + setIsConnected(true); + // Store the wallet's network + if (walletInfo.network) { + setWalletNetwork(walletInfo.network as Network); + } + } + } + } catch (error) { + console.error('Failed to check persisted MetaMask connection:', error); + } + }; + + checkPersistedConnection(); + }, [rpcService]); + + const connect = useCallback(async (targetNetwork?: Network) => { + if (!window.ethereum) { + throw new Error('MetaMask is not installed. Please install MetaMask extension.'); + } + + // Use provided network or default from config + const dappNetwork = targetNetwork || config.defaultNetwork; + + try { + // Request snap connection + const result = await window.ethereum.request({ + method: 'wallet_requestSnaps', + params: { + [SNAP_ID]: { + version: SNAP_VERSION, + }, + }, + }); + + if (!result?.[SNAP_ID]) { + throw new Error('Failed to connect to Hathor Snap'); + } + + // Get wallet information from snap (includes network) + const walletResult = await rpcService.getWalletInformation(); + + // MetaMask Snap returns response in nested format + const walletInfo = (walletResult as any)?.response || walletResult; + if (!walletInfo?.address0) { + throw new Error('Failed to get wallet information from snap'); + } + + // Check if wallet's network matches dapp's network + const walletNetwork = walletInfo.network; + let finalAddress = walletInfo.address0; + + if (walletNetwork !== dappNetwork) { + console.log(`Wallet is on ${walletNetwork}, switching to ${dappNetwork}...`); + try { + await metamask_request('htr_changeNetwork', { network: walletNetwork, newNetwork: dappNetwork }); + // After network change, get updated wallet info with new address + const updatedWalletResult = await rpcService.getWalletInformation(); + const updatedWalletInfo = (updatedWalletResult as any)?.response || updatedWalletResult; + if (updatedWalletInfo?.address0) { + finalAddress = updatedWalletInfo.address0; + console.log(`Network switched, new address: ${finalAddress}`); + } + } catch (error) { + console.warn('Failed to change network:', error); + // Continue anyway - user can manually switch later + } + } + + setAddress(finalAddress); + setIsConnected(true); + setWalletNetwork(dappNetwork); + localStorage.setItem('wallet_type', 'metamask'); + localStorage.setItem('address', finalAddress); + } catch (error: any) { + console.error('Failed to connect to MetaMask Snap:', error); + throw new Error(error?.message || 'Failed to connect to MetaMask Snap'); + } + }, [rpcService, metamask_request]); + + const disconnect = useCallback(async () => { + setAddress(null); + setWalletNetwork(null); + setIsConnected(false); + localStorage.removeItem('wallet_type'); + localStorage.removeItem('address'); + }, []); + + const request = useCallback( + async (method: string, params?: any): Promise => { + if (!isConnected) { + throw new Error('MetaMask Snap is not connected'); + } + + try { + const result = await metamask_request(method, params); + return result as T; + } catch (error: any) { + console.error('MetaMask Snap request failed:', error); + throw new Error(error?.message || 'MetaMask Snap request failed'); + } + }, + [isConnected, metamask_request] + ); + + const value = useMemo( + () => ({ + address, + walletNetwork, + isConnected, + isInstalled, + connect, + disconnect, + request, + }), + [address, walletNetwork, isConnected, isInstalled, connect, disconnect, request] + ); + + return {children}; +} + +export function useMetaMask() { + const context = useContext(MetaMaskContext); + if (context === undefined) { + throw new Error('useMetaMask must be used within a MetaMaskProvider'); + } + return context; +} diff --git a/dapp/contexts/UnifiedWalletContext.tsx b/dapp/contexts/UnifiedWalletContext.tsx new file mode 100644 index 0000000..4c882f3 --- /dev/null +++ b/dapp/contexts/UnifiedWalletContext.tsx @@ -0,0 +1,96 @@ +'use client'; + +import React, { createContext, useContext, useEffect, useState, ReactNode } from 'react'; +import { WalletAdapter, WalletType } from '@/types/wallet'; +import { useMetaMask } from './MetaMaskContext'; +import { useWalletConnect } from './WalletConnectContext'; + +interface UnifiedWalletContextType { + adapter: WalletAdapter | null; + walletType: WalletType; + setWalletType: (type: WalletType) => void; +} + +const UnifiedWalletContext = createContext(undefined); + +export function UnifiedWalletProvider({ children }: { children: ReactNode }) { + const metaMask = useMetaMask(); + const walletConnect = useWalletConnect(); + const [walletType, setWalletTypeState] = useState(null); + + // Load wallet type from localStorage on mount + useEffect(() => { + const storedWalletType = localStorage.getItem('wallet_type') as WalletType; + if (storedWalletType) { + setWalletTypeState(storedWalletType); + } + }, []); + + // Update wallet type when connections change + useEffect(() => { + if (metaMask.isConnected && walletType !== 'metamask') { + setWalletTypeState('metamask'); + } else if (walletConnect.isConnected && walletType !== 'walletconnect') { + setWalletTypeState('walletconnect'); + } else if (!metaMask.isConnected && !walletConnect.isConnected && walletType !== null) { + setWalletTypeState(null); + } + }, [metaMask.isConnected, walletConnect.isConnected, walletType]); + + // Determine which adapter to use based on wallet type + const adapter: WalletAdapter | null = (() => { + if (walletType === 'metamask' && metaMask.isConnected) { + return { + isConnected: metaMask.isConnected, + isInitializing: false, + address: metaMask.address, + connect: metaMask.connect, + disconnect: metaMask.disconnect, + request: metaMask.request, + }; + } else if (walletType === 'walletconnect' && walletConnect.isConnected) { + const connectedNetwork = walletConnect.getConnectedNetwork() || 'privatenet'; + return { + isConnected: walletConnect.isConnected, + isInitializing: walletConnect.isInitializing, + address: walletConnect.getFirstAddress(), + connect: () => walletConnect.connect(undefined), + disconnect: walletConnect.disconnect, + request: async (method: string, params?: any): Promise => { + if (!walletConnect.client || !walletConnect.session) { + throw new Error('WalletConnect not connected'); + } + return walletConnect.client.request({ + chainId: `hathor:${connectedNetwork}`, + topic: walletConnect.session.topic, + request: { method, params }, + }); + }, + }; + } + return null; + })(); + + const setWalletType = (type: WalletType) => { + setWalletTypeState(type); + if (type) { + localStorage.setItem('wallet_type', type); + } else { + localStorage.removeItem('wallet_type'); + } + }; + + return ( + + {children} + + ); +} + +export function useUnifiedWallet() { + const context = useContext(UnifiedWalletContext); + if (context === undefined) { + throw new Error('useUnifiedWallet must be used within a UnifiedWalletProvider'); + } + return context; +} diff --git a/dapp/contexts/WalletConnectContext.tsx b/dapp/contexts/WalletConnectContext.tsx new file mode 100644 index 0000000..98dd18f --- /dev/null +++ b/dapp/contexts/WalletConnectContext.tsx @@ -0,0 +1,298 @@ +'use client'; + +import React, { createContext, ReactNode, useCallback, useContext, useEffect, useMemo, useState, useRef } from 'react'; +import Client from '@walletconnect/sign-client'; +import { PairingTypes, SessionTypes } from '@walletconnect/types'; +import { Web3Modal } from '@web3modal/standalone'; +import { getSdkError } from '@walletconnect/utils'; +import { WALLETCONNECT_PROJECT_ID } from '@/lib/walletConnectConfig'; +import { initializeWalletConnectClient } from '@/lib/walletConnectClient'; +import { Network } from '@/lib/config'; + +interface IWalletConnectContext { + client: Client | undefined; + session: SessionTypes.Struct | undefined; + connect: (targetNetwork?: Network, pairing?: { topic: string }) => Promise; + disconnect: () => Promise; + chains: string[]; + pairings: PairingTypes.Struct[]; + accounts: string[]; + setChains: React.Dispatch>; + getFirstAddress: () => string; + getConnectedNetwork: () => Network | null; + isConnected: boolean; + isInitializing: boolean; +} + +const WalletConnectContext = createContext({} as IWalletConnectContext); + +const web3Modal = new Web3Modal({ + projectId: WALLETCONNECT_PROJECT_ID, + themeMode: 'dark', + walletConnectVersion: 2, +}); + +export function WalletConnectProvider({ children }: { children: ReactNode | ReactNode[] }) { + const [client, setClient] = useState(); + const [pairings, setPairings] = useState([]); + const [session, setSession] = useState(); + const [accounts, setAccounts] = useState([]); + const [chains, setChains] = useState([]); + const [clientInitialized, setClientInitialized] = useState(false); + const [isInitializing, setIsInitializing] = useState(false); + const initializationAttempted = useRef(false); + + const reset = () => { + setSession(undefined); + setAccounts([]); + setChains([]); + localStorage.removeItem('wallet_type'); + localStorage.removeItem('address'); + }; + + const onSessionConnected = useCallback(async (_session: SessionTypes.Struct) => { + const allNamespaceAccounts = Object.values(_session.namespaces) + .map((namespace) => namespace.accounts) + .flat(); + const allNamespaceChains = Object.keys(_session.namespaces); + + setSession(_session); + setChains(allNamespaceChains); + setAccounts(allNamespaceAccounts); + + // Store wallet type and address in localStorage + localStorage.setItem('wallet_type', 'walletconnect'); + if (_session.namespaces.hathor?.accounts?.[0]) { + const [, , address] = _session.namespaces.hathor.accounts[0].split(':'); + localStorage.setItem('address', address); + } + }, []); + + const getFirstAddress = useCallback(() => { + if (!session?.namespaces?.hathor?.accounts?.[0]) { + return ''; + } + const [, , addr] = session.namespaces.hathor.accounts[0].split(':'); + return addr; + }, [session]); + + const getConnectedNetwork = useCallback((): Network | null => { + if (!session?.namespaces?.hathor?.accounts?.[0]) { + return null; + } + const [, network] = session.namespaces.hathor.accounts[0].split(':'); + return network as Network; + }, [session]); + + const subscribeToEvents = useCallback( + async (_client: Client) => { + if (!_client) { + throw new Error('WalletConnect is not initialized'); + } + + _client.on('session_ping', (args) => { + console.log('EVENT', 'session_ping', args); + }); + + _client.on('session_event', (args) => { + console.log('EVENT', 'session_event', args); + }); + + _client.on('session_update', ({ topic, params }) => { + console.log('EVENT', 'session_update', { topic, params }); + const { namespaces } = params; + const _session = _client.session.get(topic); + const updatedSession = { ..._session, namespaces }; + onSessionConnected(updatedSession); + }); + + _client.on('session_delete', () => { + console.log('EVENT', 'session_delete'); + reset(); + }); + }, + [onSessionConnected] + ); + + const checkPersistedState = useCallback( + async (_client: Client) => { + if (!_client) { + throw new Error('WalletConnect is not initialized'); + } + setPairings(_client.pairing.getAll({ active: true })); + + if (session) return; + if (_client.session.length) { + const lastKeyIndex = _client.session.keys.length - 1; + const _session = _client.session.get(_client.session.keys[lastKeyIndex]); + await onSessionConnected(_session); + return _session; + } + }, + [session, onSessionConnected] + ); + + useEffect(() => { + if (client && !clientInitialized) { + (async () => { + try { + await subscribeToEvents(client); + await checkPersistedState(client); + setClientInitialized(true); + } catch (error) { + console.error('Failed to setup WalletConnect:', error); + } + })(); + } + }, [client, clientInitialized, subscribeToEvents, checkPersistedState]); + + useEffect(() => { + if (initializationAttempted.current || isInitializing || client) return; + + initializationAttempted.current = true; + setIsInitializing(true); + (async () => { + try { + const _client = await initializeWalletConnectClient(); + setClient(_client); + } catch (error) { + console.error('Failed to initialize WalletConnect on mount:', error); + initializationAttempted.current = false; + } finally { + setIsInitializing(false); + } + })(); + }, []); + + const connect = useCallback( + async (targetNetwork?: Network, pairing?: { topic: string }) => { + if (!client) { + throw new Error('WalletConnect client is not initialized yet. Please wait a moment and try again.'); + } + + if (session) { + return; + } + + // Default to testnet if no network specified + const dappNetwork = targetNetwork || 'privatenet'; + + let unsubscribe: (() => void) | undefined; + + try { + const requiredNamespaces = { + hathor: { + methods: [ + 'htr_getAddress', + 'htr_getBalance', + 'htr_getUtxos', + 'htr_signWithAddress', + 'htr_sendNanoContractTx', + ], + chains: [`hathor:${dappNetwork}`], + events: [], + }, + }; + + const { uri, approval } = await client.connect({ + pairingTopic: pairing?.topic, + requiredNamespaces, + }); + + if (uri) { + const standaloneChains = Object.values(requiredNamespaces) + .map((namespace) => namespace.chains) + .flat() as string[]; + + web3Modal.openModal({ uri, standaloneChains }); + } + + const modalClosedPromise = new Promise((_, reject) => { + unsubscribe = web3Modal.subscribeModal((state) => { + if (!state.open) { + reject(new Error('User closed the modal')); + } + }); + }); + + const newSession = await Promise.race([approval(), modalClosedPromise]); + + // Extract network from the connected session + const connectedAccount = newSession.namespaces?.hathor?.accounts?.[0]; + if (connectedAccount) { + const [, walletNetwork] = connectedAccount.split(':'); + + // Validate network matches + if (walletNetwork !== dappNetwork) { + // Disconnect the session since networks don't match + await client.disconnect({ + topic: newSession.topic, + reason: getSdkError('USER_DISCONNECTED'), + }); + throw new Error(`Network mismatch: wallet is on ${walletNetwork} but dapp requires ${dappNetwork}. Please switch your wallet to ${dappNetwork} and try again.`); + } + } + + await onSessionConnected(newSession); + setPairings(client.pairing.getAll({ active: true })); + } catch (e) { + console.error('Failed to connect:', e); + throw e; + } finally { + if (unsubscribe) { + unsubscribe(); + } + web3Modal.closeModal(); + } + }, + [client, session, onSessionConnected] + ); + + const disconnect = useCallback(async () => { + if (!client) { + throw new Error('WalletConnect is not initialized'); + } + if (!session) { + throw new Error('Session is not connected'); + } + + try { + await client.disconnect({ + topic: session.topic, + reason: getSdkError('USER_DISCONNECTED'), + }); + } catch (error) { + console.error('SignClient.disconnect failed:', error); + } finally { + reset(); + } + }, [client, session]); + + const value = useMemo( + () => ({ + pairings, + accounts, + chains, + client, + session, + connect, + disconnect, + getFirstAddress, + getConnectedNetwork, + setChains, + isConnected: !!session, + isInitializing, + }), + [pairings, accounts, chains, client, session, connect, disconnect, getFirstAddress, getConnectedNetwork, setChains, isInitializing] + ); + + return {children}; +} + +export function useWalletConnect() { + const context = useContext(WalletConnectContext); + if (context === undefined) { + throw new Error('useWalletConnect must be used within a WalletConnectProvider'); + } + return context; +} diff --git a/dapp/contexts/WalletContext.tsx b/dapp/contexts/WalletContext.tsx new file mode 100644 index 0000000..216e4dc --- /dev/null +++ b/dapp/contexts/WalletContext.tsx @@ -0,0 +1,241 @@ +'use client'; + +import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react'; +import { WalletState } from '@/types'; +import { HathorRPCService } from '@/lib/hathorRPC'; +import { useUnifiedWallet } from './UnifiedWalletContext'; +import { config, Network } from '@/lib/config'; + +interface WalletContextType { + connected: boolean; + address: string | null; + balance: bigint; + walletBalance: number; + balanceVerified: boolean; + isLoadingBalance: boolean; + connectWallet: () => void; + disconnectWallet: () => void; + setBalance: React.Dispatch>; + refreshBalance: (tokenUid?: string, network?: Network) => Promise; + sendNanoContractTx: (params: { + network: Network; + nc_id?: string; + blueprint_id?: string; + method: string; + args: any[]; + actions: Array<{ + type: 'deposit' | 'withdrawal'; + amount: string; + token: string; + address?: string; + }>; + push_tx: boolean; + }) => Promise; +} + +const WalletContext = createContext(undefined); + +const BALANCE_CACHE_KEY = 'hathor_balance_cache'; +const BALANCE_CACHE_DURATION = 15 * 60 * 1000; // 15 minutes in milliseconds + +interface BalanceCache { + balance: string; // Store as string since bigint can't be JSON serialized + timestamp: number; + address: string; +} + +export function WalletProvider({ children }: { children: ReactNode }) { + const { adapter } = useUnifiedWallet(); + const [connected, setConnected] = useState(false); + const [address, setAddress] = useState(null); + const [balance, setBalance] = useState(0n); + const [balanceVerified, setBalanceVerified] = useState(false); + const [isLoadingBalance, setIsLoadingBalance] = useState(false); + const [rpcService] = useState(() => new HathorRPCService(config.useMockWallet)); + + // Load cached balance from localStorage + const loadCachedBalance = (addr: string): bigint | null => { + try { + const cached = localStorage.getItem(BALANCE_CACHE_KEY); + if (!cached) return null; + + const cache: BalanceCache = JSON.parse(cached); + const now = Date.now(); + + // Check if cache is for the same address and is still valid (less than 15 minutes old) + if (cache.address === addr && (now - cache.timestamp) < BALANCE_CACHE_DURATION) { + return BigInt(cache.balance); + } + + return null; + } catch (error) { + console.error('Failed to load cached balance:', error); + return null; + } + }; + + // Save balance to cache + const saveCachedBalance = (addr: string, bal: bigint) => { + try { + const cache: BalanceCache = { + balance: bal.toString(), + timestamp: Date.now(), + address: addr, + }; + localStorage.setItem(BALANCE_CACHE_KEY, JSON.stringify(cache)); + } catch (error) { + console.error('Failed to save cached balance:', error); + } + }; + + // Define fetchBalance before it's used in useEffect + const fetchBalance = async (addr: string, forceRefresh: boolean = false, tokenUid: string = '00', network: Network = 'mainnet') => { + if (!addr) return; + + // Don't use cache - always fetch fresh balance to ensure authorization + if (config.useMockWallet) { + setBalance(100000n); + setBalanceVerified(true); + saveCachedBalance(addr, 100000n); + return; + } + + // Update RPC service network before making request + rpcService.setNetwork(network); + + setIsLoadingBalance(true); + setBalanceVerified(false); // Reset verified state while fetching new balance + try { + const balanceInfo = await rpcService.getBalance({ + network, + tokens: [tokenUid], + }); + + console.log('Balance response:', balanceInfo); + + // Handle both direct response and nested response format (MetaMask Snap wraps response) + const responseData = (balanceInfo as any)?.response?.response || balanceInfo?.response; + const balanceData = responseData?.[0]?.balance?.unlocked; + + // Convert to bigint - value is already in cents from API + const balanceValue = typeof balanceData === 'number' + ? BigInt(Math.floor(balanceData)) + : (typeof balanceData === 'bigint' ? balanceData : 0n); + + console.log('Parsed balance:', balanceValue.toString()); + + setBalance(balanceValue); + setBalanceVerified(true); + saveCachedBalance(addr, balanceValue); + } catch (error: any) { + console.log('Balance fetch was rejected or failed:', error); + setBalance(0n); + setBalanceVerified(false); + } finally { + setIsLoadingBalance(false); + } + }; + + // Update rpcService and fetch balance when wallet connects + useEffect(() => { + console.log('WalletContext useEffect - adapter state:', { + isConnected: adapter?.isConnected, + address: adapter?.address, + hasRequest: !!adapter?.request, + }); + + if (adapter?.isConnected && adapter.address) { + // Update rpcService with adapter's request function + console.log('Updating rpcService with adapter.request'); + rpcService.updateClientAndSession(undefined, undefined, adapter.request); + // Update address - balance fetch is handled by page.tsx with correct token + setAddress(adapter.address); + } else if (!adapter?.isConnected) { + setAddress(null); + setBalance(0n); + } + }, [adapter?.isConnected, adapter?.address, adapter?.request, rpcService]); + + // Convert balance from cents (bigint) to token units (number) for backwards compatibility + const walletBalance = typeof balance === 'bigint' ? Number(balance) / 100 : 0; + + const connectWallet = () => { + setConnected(true); + setAddress('0x7a3f...9b2c'); + setBalance(100000n); + }; + + const disconnectWallet = () => { + setConnected(false); + setAddress(null); + setBalance(0n); + setBalanceVerified(false); + setIsLoadingBalance(false); + }; + + // Generic method to send nano contract transactions + const sendNanoContractTx = async (params: { + network: Network; + nc_id?: string; + blueprint_id?: string; + method: string; + args: any[]; + actions: Array<{ + type: 'deposit' | 'withdrawal'; + amount: string; + token: string; + address?: string; + }>; + push_tx: boolean; + }) => { + if (!adapter?.isConnected || !address) { + throw new Error('Wallet not connected'); + } + + // Update RPC service network before making request + rpcService.setNetwork(params.network); + + console.log('Sending nano contract tx with params:', params); + + try { + const result = await rpcService.sendNanoContractTx(params); + console.log('Nano contract tx successful:', result); + return result; + } catch (error) { + console.error('Failed to send nano contract tx:', error); + throw error; + } + }; + + const refreshBalance = async (tokenUid: string = '00', network: Network = 'mainnet') => { + if (address) { + await fetchBalance(address, true, tokenUid, network); // Force refresh + } + }; + + return ( + + {children} + + ); +} + +export function useWallet() { + const context = useContext(WalletContext); + if (context === undefined) { + throw new Error('useWallet must be used within a WalletProvider'); + } + return context; +} diff --git a/dapp/e2e/homepage.spec.ts b/dapp/e2e/homepage.spec.ts new file mode 100644 index 0000000..f4fe8ce --- /dev/null +++ b/dapp/e2e/homepage.spec.ts @@ -0,0 +1,136 @@ +import { test, expect } from '@playwright/test' + +test.describe('Hathor dApp Homepage', () => { + test.beforeEach(async ({ page }) => { + // Navigate to homepage + await page.goto('/') + }) + + test('should load homepage successfully', async ({ page }) => { + // Check page title + await expect(page).toHaveTitle(/Hathor dApp/i) + + // Check main heading is visible + const heading = page.getByRole('heading', { level: 1 }) + await expect(heading).toBeVisible() + }) + + test('should display main template components', async ({ page }) => { + // Wait for page to be fully loaded + await page.waitForLoadState('networkidle') + + // Check that key UI elements are present + const pageContent = await page.textContent('body') + expect(pageContent).toBeTruthy() + + // The page should render without errors + const errors: Error[] = [] + page.on('pageerror', error => errors.push(error)) + await page.waitForTimeout(1000) + expect(errors).toHaveLength(0) + }) + + test('should display wallet connection button', async ({ page }) => { + // Look for wallet connect button + const connectButton = page.getByRole('button', { name: /connect/i }) + await expect(connectButton).toBeVisible() + }) + + test('should display getting started guide', async ({ page }) => { + // Check for getting started section + const gettingStarted = page.getByText('Getting Started') + await expect(gettingStarted).toBeVisible() + }) + + test('should display welcome message', async ({ page }) => { + // Check for welcome message + const welcomeText = page.getByText('Welcome to Your Hathor dApp') + await expect(welcomeText).toBeVisible() + }) + + test('should be responsive', async ({ page }) => { + // Test mobile viewport + await page.setViewportSize({ width: 375, height: 667 }) + await page.waitForLoadState('networkidle') + + const body = page.locator('body') + await expect(body).toBeVisible() + + // Test desktop viewport + await page.setViewportSize({ width: 1920, height: 1080 }) + await page.waitForLoadState('networkidle') + await expect(body).toBeVisible() + }) + + test('should not have console errors', async ({ page }) => { + const consoleErrors: string[] = [] + + page.on('console', msg => { + if (msg.type() === 'error') { + consoleErrors.push(msg.text()) + } + }) + + await page.goto('/') + await page.waitForLoadState('networkidle') + await page.waitForTimeout(2000) + + // Filter out expected errors (e.g., from mock wallet setup) + const unexpectedErrors = consoleErrors.filter(error => + !error.includes('WalletConnect') && + !error.includes('MetaMask') && + !error.includes('mock') + ) + + expect(unexpectedErrors).toHaveLength(0) + }) + + test('should have working navigation', async ({ page }) => { + await page.waitForLoadState('networkidle') + + // Check that the app is interactive + const body = page.locator('body') + const isInteractive = await body.isEnabled() + expect(isInteractive).toBe(true) + }) +}) + +test.describe('Mock Wallet Integration', () => { + test('should work with mock wallet enabled', async ({ page }) => { + // The app should be in mock mode based on environment variable + await page.goto('/') + await page.waitForLoadState('networkidle') + + // The page should render without crashing + const content = await page.textContent('body') + expect(content).toBeTruthy() + expect(content!.length).toBeGreaterThan(0) + }) + + test('should display balance section', async ({ page }) => { + await page.goto('/') + await page.waitForLoadState('networkidle') + + // Give time for any initial data loading + await page.waitForTimeout(2000) + + // Check if balance card is rendered + const balanceText = page.getByText('YOUR BALANCE') + await expect(balanceText).toBeVisible() + }) +}) + +test.describe('Resources Section', () => { + test('should display resource links', async ({ page }) => { + await page.goto('/') + await page.waitForLoadState('networkidle') + + // Check for resources section + const resources = page.getByText('Resources') + await expect(resources).toBeVisible() + + // Check for Hathor documentation link + const docsLink = page.getByRole('link', { name: /Hathor Documentation/i }) + await expect(docsLink).toBeVisible() + }) +}) diff --git a/dapp/lib/config.ts b/dapp/lib/config.ts new file mode 100644 index 0000000..2d00185 --- /dev/null +++ b/dapp/lib/config.ts @@ -0,0 +1,17 @@ +export type Network = 'mainnet' | 'testnet' | 'privatenet'; + +export const config = { + useMockWallet: process.env.NEXT_PUBLIC_USE_MOCK_WALLET === 'true', + defaultNetwork: (process.env.NEXT_PUBLIC_DEFAULT_NETWORK || 'privatenet') as Network, + hathorNodeUrls: { + 'privatenet': process.env.NEXT_PUBLIC_HATHOR_NODE_URL_PRIVATENET || 'http://127.0.0.1:49180/v1a', + 'testnet': process.env.NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET || 'https://node1.india.testnet.hathor.network/v1a', + 'mainnet': process.env.NEXT_PUBLIC_HATHOR_NODE_URL_MAINNET || 'https://node1.mainnet.hathor.network/v1a', + }, + + // x402 Escrow config + blueprintId: process.env.NEXT_PUBLIC_BLUEPRINT_ID || '', + facilitatorAddress: process.env.NEXT_PUBLIC_FACILITATOR_ADDRESS || '', + sellerAddress: process.env.NEXT_PUBLIC_SELLER_ADDRESS || '', + escrowDeadlineSeconds: parseInt(process.env.NEXT_PUBLIC_ESCROW_DEADLINE_SECONDS || '300'), +}; diff --git a/dapp/lib/escrowStore.ts b/dapp/lib/escrowStore.ts new file mode 100644 index 0000000..9979bb0 --- /dev/null +++ b/dapp/lib/escrowStore.ts @@ -0,0 +1,21 @@ +const STORAGE_KEY = 'x402_escrows'; + +export function getEscrowIds(): string[] { + if (typeof window === 'undefined') return []; + const raw = localStorage.getItem(STORAGE_KEY); + if (!raw) return []; + return JSON.parse(raw); +} + +export function addEscrowId(ncId: string): void { + const ids = getEscrowIds(); + if (!ids.includes(ncId)) { + ids.unshift(ncId); // newest first + localStorage.setItem(STORAGE_KEY, JSON.stringify(ids)); + } +} + +export function removeEscrowId(ncId: string): void { + const ids = getEscrowIds().filter(id => id !== ncId); + localStorage.setItem(STORAGE_KEY, JSON.stringify(ids)); +} diff --git a/dapp/lib/hathorCoreAPI.ts b/dapp/lib/hathorCoreAPI.ts new file mode 100644 index 0000000..269055e --- /dev/null +++ b/dapp/lib/hathorCoreAPI.ts @@ -0,0 +1,153 @@ +import { Network, config } from './config'; +import { ContractState, BlueprintInfo, ContractHistory } from '@/types/hathor'; + +export class HathorCoreAPI { + private baseUrl: string; + + constructor(network: Network) { + this.baseUrl = config.hathorNodeUrls[network]; + } + + async getBlueprintInfo(blueprintId: string): Promise { + const response = await fetch(`${this.baseUrl}/nc_blueprint/${blueprintId}`); + if (!response.ok) { + throw new Error(`Failed to fetch blueprint info: ${response.statusText}`); + } + return response.json(); + } + + async getContractState(contractId: string, fields: string[] = ['token_uid', 'available_tokens', 'total_liquidity_provided']): Promise { + const queryString = fields.map(field => `fields[]=${field}`).join('&'); + const response = await fetch(`${this.baseUrl}/nano_contract/state?id=${contractId}&${queryString}`); + if (!response.ok) { + throw new Error(`Failed to fetch contract state: ${response.statusText}`); + } + const data = await response.json(); + + // Build state object from all returned fields + const state: ContractState = { + token_uid: data.fields?.token_uid?.value || '00', + available_tokens: BigInt(data.fields?.available_tokens?.value || 0), + total_liquidity_provided: BigInt(data.fields?.total_liquidity_provided?.value || 0), + }; + + // Add any additional fields that were returned + if (data.fields) { + for (const [key, fieldData] of Object.entries(data.fields)) { + if (!(key in state) && fieldData && typeof fieldData === 'object' && 'value' in fieldData) { + state[key] = (fieldData as any).value; + } + } + } + + return state; + } + + async getContractHistory(contractId: string, limit: number = 50, after?: string): Promise { + let url = `${this.baseUrl}/nano_contract/history?id=${contractId}&count=${limit}&include_nc_events=true`; + if (after) { + url += `&after=${after}`; + } + const response = await fetch(url); + if (!response.ok) { + throw new Error(`Failed to fetch contract history: ${response.statusText}`); + } + const data = await response.json(); + return { + transactions: data.history?.map((tx: any) => ({ + tx_id: tx.hash, + timestamp: tx.timestamp, + nc_method: tx.nc_method, + nc_caller: tx.nc_address, + first_block: tx.first_block, + is_voided: tx.is_voided, + nc_args_decoded: tx.nc_args_decoded, + nc_events: tx.nc_events, + })) || [], + total: data.history?.length || 0, + hasMore: data.has_more || false, + }; + } + + async getTransaction(txId: string): Promise { + const response = await fetch(`${this.baseUrl}/transaction?id=${txId}`); + if (!response.ok) { + throw new Error(`Failed to fetch transaction: ${response.statusText}`); + } + return response.json(); + } + + async callViewFunction(contractId: string, method: string, args: any[] = [], callerAddress?: string): Promise { + const body: any = { + id: contractId, + method, + args, + }; + + if (callerAddress) { + body.caller = callerAddress; + } + + // Construct query parameters properly + const params = new URLSearchParams(); + params.append('id', contractId); + params.append('calls[]', `${method}(${args.map(arg => JSON.stringify(arg)).join(', ')})`); + + const response = await fetch(`${this.baseUrl}/nano_contract/state?${params.toString()}`); + + if (!response.ok) { + throw new Error(`Failed to call view function: ${response.statusText}`); + } + + const data = await response.json(); + return data; + } + + async getMaximumLiquidityRemoval(contractId: string, callerAddress: string): Promise { + const result = await this.callViewFunction(contractId, 'calculate_address_maximum_liquidity_removal', [callerAddress], callerAddress); + // The result is in calls['calculate_address_maximum_liquidity_removal()'].value + if (result.calls) { + // Get the first (and should be only) call result + const callKey = Object.keys(result.calls)[0]; + if (callKey && result.calls[callKey]?.value !== undefined) { + return BigInt(result.calls[callKey].value); + } + } + return 0n; + } + + async getClaimableBalance(contractId: string, callerAddress: string): Promise { + const result = await this.callViewFunction(contractId, 'get_address_balance', [callerAddress], callerAddress); + // The result is in calls['get_address_balance("ADDRESS")'].value + if (result.calls) { + // Get the first (and should be only) call result + const callKey = Object.keys(result.calls)[0]; + if (callKey && result.calls[callKey]?.value !== undefined) { + return BigInt(result.calls[callKey].value); + } + } + return 0n; + } + + async getTokenInfo(tokenUid: string): Promise<{ symbol: string; name: string } | null> { + // HTR native token + if (tokenUid === '00' || /^0+$/.test(tokenUid)) { + return { symbol: 'HTR', name: 'Hathor' }; + } + + try { + const response = await fetch(`${this.baseUrl}/thin_wallet/token?id=${tokenUid}`); + if (!response.ok) { + return null; + } + const data = await response.json(); + return { + symbol: data.symbol || tokenUid.slice(0, 8), + name: data.name || 'Unknown Token', + }; + } catch (error) { + console.error('Failed to fetch token info:', error); + return null; + } + } +} diff --git a/dapp/lib/hathorRPC.ts b/dapp/lib/hathorRPC.ts new file mode 100644 index 0000000..ecbcab5 --- /dev/null +++ b/dapp/lib/hathorRPC.ts @@ -0,0 +1,130 @@ +import { HathorRPCRequest, HathorRPCResponse, GetBalanceParams, GetAddressParams, SendNanoContractTxParams } from '@/types/hathor'; +import Client from '@walletconnect/sign-client'; +import { SessionTypes } from '@walletconnect/types'; +import { Network } from '@/lib/config'; + +type RequestFunction = (method: string, params?: any) => Promise; + +export class HathorRPCService { + private useMock: boolean; + private client: Client | undefined; + private session: SessionTypes.Struct | undefined; + private customRequest: RequestFunction | undefined; + private network: Network; + + constructor(useMock: boolean = false, client?: Client, session?: SessionTypes.Struct, customRequest?: RequestFunction, network: Network = 'mainnet') { + this.useMock = useMock; + this.client = client; + this.session = session; + this.customRequest = customRequest; + this.network = network; + } + + updateClientAndSession(client?: Client, session?: SessionTypes.Struct, customRequest?: RequestFunction, network?: Network) { + this.client = client; + this.session = session; + this.customRequest = customRequest; + if (network) { + this.network = network; + } + } + + setNetwork(network: Network) { + this.network = network; + } + + async request(method: string, params?: any): Promise { + if (this.useMock) { + return this.mockRequest(method, params); + } + + // Use custom request function if provided (e.g., MetaMask) + if (this.customRequest) { + try { + const result = await this.customRequest(method, params); + return result; + } catch (error: any) { + console.error('RPC request failed:', error); + throw new Error(error?.message || 'RPC request failed'); + } + } + + // Fall back to WalletConnect + if (!this.client || !this.session) { + throw new Error('Wallet not connected. Please connect your wallet.'); + } + + try { + const result = await this.client.request({ + chainId: `hathor:${this.network}`, + topic: this.session.topic, + request: { + method, + params, + }, + }); + + return result; + } catch (error: any) { + console.error('RPC request failed:', error); + throw new Error(error?.message || 'RPC request failed'); + } + } + + async getConnectedNetwork(): Promise<{ network: string; genesisHash: string }> { + return this.request('htr_getConnectedNetwork'); + } + + async getBalance(params: GetBalanceParams): Promise<{ response: any[] }> { + return this.request('htr_getBalance', params); + } + + async getAddress(params: GetAddressParams): Promise<{ address: string; index: number; addressPath: string }> { + return this.request('htr_getAddress', params); + } + + async getWalletInformation(): Promise<{ address0: string; network: string }> { + return this.request('htr_getWalletInformation'); + } + + async sendNanoContractTx(params: SendNanoContractTxParams): Promise { + return this.request('htr_sendNanoContractTx', params); + } + + private async mockRequest(method: string, params?: any): Promise { + await new Promise(resolve => setTimeout(resolve, 500)); + + switch (method) { + case 'htr_getConnectedNetwork': + return { network: 'testnet', genesisHash: '0x123...' } as T; + + case 'htr_getBalance': + return { + response: [{ + token: { id: '00', name: 'Hathor', symbol: 'HTR' }, + balance: { unlocked: 1250.50, locked: 0 }, + tokenAuthorities: { unlocked: { mint: false, melt: false }, locked: { mint: false, melt: false } }, + transactions: 42, + lockExpires: null, + }] + } as T; + + case 'htr_getAddress': + return { address: 'WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp', index: 0, addressPath: "m/44'/280'/0'/0/0" } as T; + + case 'htr_getWalletInformation': + return { address0: 'WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp', network: 'testnet' } as T; + + case 'htr_sendNanoContractTx': + return { + hash: '00000000' + Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15), + success: true, + timestamp: Date.now(), + nonce: Math.floor(Math.random() * 1000000), + } as T; + + default: + throw new Error(`Mock not implemented for method: ${method}`); + } + } +} diff --git a/dapp/lib/toast.tsx b/dapp/lib/toast.tsx new file mode 100644 index 0000000..71205f0 --- /dev/null +++ b/dapp/lib/toast.tsx @@ -0,0 +1,162 @@ +'use client'; + +import { createContext, useContext, useState, useCallback, ReactNode, useEffect } from 'react'; +import { createPortal } from 'react-dom'; + +interface Toast { + id: string; + message: string; + type: 'success' | 'error' | 'info'; +} + +interface ToastContextType { + toasts: Toast[]; + addToast: (message: string, type: Toast['type']) => void; + removeToast: (id: string) => void; +} + +const ToastContext = createContext(undefined); + +export function ToastProvider({ children }: { children: ReactNode }) { + const [toasts, setToasts] = useState([]); + const [mounted, setMounted] = useState(false); + + useEffect(() => { + setMounted(true); + }, []); + + const addToast = useCallback((message: string, type: Toast['type']) => { + const id = Math.random().toString(36).substring(2, 11); + console.log('[ToastProvider] Adding toast:', { id, message, type }); + setToasts((prev) => { + const newToasts = [...prev, { id, message, type }]; + console.log('[ToastProvider] New toasts array:', newToasts); + return newToasts; + }); + setTimeout(() => { + setToasts((prev) => prev.filter((t) => t.id !== id)); + }, 5000); + }, []); + + const removeToast = useCallback((id: string) => { + setToasts((prev) => prev.filter((t) => t.id !== id)); + }, []); + + const toastContainer = mounted ? ( + createPortal( +
+ {toasts.map((toast) => ( +
+ + {toast.type === 'success' && '✓'} + {toast.type === 'error' && '✕'} + {toast.type === 'info' && 'ℹ'} + + {toast.message} + +
+ ))} +
, + document.body + ) + ) : null; + + return ( + + {children} + {toastContainer} + + ); +} + +export function useToast() { + const context = useContext(ToastContext); + if (!context) { + throw new Error('useToast must be used within ToastProvider'); + } + return context; +} + +export const toast = { + success: (message: string) => { + console.log('[Toast] Dispatching success:', message); + if (typeof window !== 'undefined') { + window.dispatchEvent(new CustomEvent('toast', { detail: { message, type: 'success' } })); + } + }, + error: (message: string) => { + console.log('[Toast] Dispatching error:', message); + if (typeof window !== 'undefined') { + window.dispatchEvent(new CustomEvent('toast', { detail: { message, type: 'error' } })); + } + }, + info: (message: string) => { + console.log('[Toast] Dispatching info:', message); + if (typeof window !== 'undefined') { + window.dispatchEvent(new CustomEvent('toast', { detail: { message, type: 'info' } })); + } + }, +}; + +export function Toaster() { + const { addToast } = useToast(); + + useEffect(() => { + console.log('[Toaster] Setting up event listener'); + const handleToast = (event: Event) => { + const customEvent = event as CustomEvent; + console.log('[Toaster] Received toast event:', customEvent.detail); + addToast(customEvent.detail.message, customEvent.detail.type); + }; + + window.addEventListener('toast', handleToast); + return () => { + console.log('[Toaster] Cleaning up event listener'); + window.removeEventListener('toast', handleToast); + }; + }, [addToast]); + + return null; +} diff --git a/dapp/lib/utils.ts b/dapp/lib/utils.ts new file mode 100644 index 0000000..d21931a --- /dev/null +++ b/dapp/lib/utils.ts @@ -0,0 +1,62 @@ +export function cn(...inputs: (string | undefined | null | false)[]) { + return inputs.filter(Boolean).join(' ') +} + +export const TOKENS = [ + { value: 'HTR', label: 'HTR' }, +]; + +export function formatAddress(address: string): string { + if (!address) return ''; + return `${address.slice(0, 6)}...${address.slice(-4)}`; +} + +export function formatNumber(num: number, decimals: number = 2): string { + return num.toFixed(decimals); +} + +export function formatTokenAmount(amount: bigint | number, decimals: number = 2): string { + if (typeof amount === 'bigint') { + // Convert BigInt to string to avoid precision loss with large numbers + const amountStr = amount.toString(); + + // Pad with zeros if needed (for values less than 100) + const paddedStr = amountStr.padStart(decimals + 1, '0'); + + // Insert decimal point + const decimalPosition = paddedStr.length - decimals; + const integerPart = paddedStr.slice(0, decimalPosition); + const decimalPart = paddedStr.slice(decimalPosition); + + return `${integerPart}.${decimalPart}`; + } + return (amount / 100).toFixed(decimals); +} + +export function formatBalance(balance: bigint | number, decimals: number = 2): string { + if (typeof balance === 'bigint') { + // Convert BigInt to string to avoid precision loss with large numbers + const balanceStr = balance.toString(); + + // Pad with zeros if needed (for values less than 100) + const paddedStr = balanceStr.padStart(decimals + 1, '0'); + + // Insert decimal point + const decimalPosition = paddedStr.length - decimals; + const integerPart = paddedStr.slice(0, decimalPosition); + const decimalPart = paddedStr.slice(decimalPosition); + + return `${integerPart}.${decimalPart}`; + } + return (balance / 100).toFixed(decimals); +} + +export function formatBalanceWithCommas(balance: bigint | number, decimals: number = 2): string { + const formatted = formatBalance(balance, decimals); + const [integerPart, decimalPart] = formatted.split('.'); + + // Add thousand separators + const withCommas = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, ','); + + return decimalPart ? `${withCommas}.${decimalPart}` : withCommas; +} diff --git a/dapp/lib/version.ts b/dapp/lib/version.ts new file mode 100644 index 0000000..1774e93 --- /dev/null +++ b/dapp/lib/version.ts @@ -0,0 +1 @@ +export const APP_VERSION = 'v0.2.0'; diff --git a/dapp/lib/walletConnectClient.ts b/dapp/lib/walletConnectClient.ts new file mode 100644 index 0000000..75c999f --- /dev/null +++ b/dapp/lib/walletConnectClient.ts @@ -0,0 +1,29 @@ +import Client from '@walletconnect/sign-client'; +import { WALLETCONNECT_PROJECT_ID, WALLETCONNECT_METADATA, RELAY_URL } from './walletConnectConfig'; + +let client: Client | null = null; + +export async function initializeWalletConnectClient(): Promise { + if (client) { + return client; + } + + try { + client = await Client.init({ + projectId: WALLETCONNECT_PROJECT_ID, + relayUrl: RELAY_URL, + metadata: WALLETCONNECT_METADATA, + }); + return client; + } catch (error) { + console.error('Failed to initialize WalletConnect client:', error); + throw error; + } +} + +export function getWalletConnectClient(): Client { + if (!client) { + throw new Error('WalletConnect client is not initialized'); + } + return client; +} diff --git a/dapp/lib/walletConnectConfig.ts b/dapp/lib/walletConnectConfig.ts new file mode 100644 index 0000000..0f1299f --- /dev/null +++ b/dapp/lib/walletConnectConfig.ts @@ -0,0 +1,11 @@ +export const WALLETCONNECT_PROJECT_ID = process.env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID || 'YOUR_PROJECT_ID'; + +// Customize these values for your dApp +export const WALLETCONNECT_METADATA = { + name: process.env.NEXT_PUBLIC_APP_NAME || 'Hathor dApp', + description: process.env.NEXT_PUBLIC_APP_DESCRIPTION || 'Decentralized application on Hathor Network', + url: typeof window !== 'undefined' ? window.location.origin : 'https://your-dapp.com', + icons: [typeof window !== 'undefined' ? `${window.location.origin}/images/icon.png` : 'https://your-dapp.com/images/icon.png'], +}; + +export const RELAY_URL = 'wss://relay.walletconnect.com'; diff --git a/dapp/next.config.js b/dapp/next.config.js new file mode 100644 index 0000000..5cd8cc3 --- /dev/null +++ b/dapp/next.config.js @@ -0,0 +1,6 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + output: 'standalone', +} + +module.exports = nextConfig diff --git a/dapp/next.config.production.js b/dapp/next.config.production.js new file mode 100644 index 0000000..1c8496a --- /dev/null +++ b/dapp/next.config.production.js @@ -0,0 +1,9 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + output: 'export', + images: { + unoptimized: true, + }, +} + +module.exports = nextConfig diff --git a/dapp/package-lock.json b/dapp/package-lock.json new file mode 100644 index 0000000..b475cd1 --- /dev/null +++ b/dapp/package-lock.json @@ -0,0 +1,11057 @@ +{ + "name": "dapp", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "dapp", + "version": "0.1.0", + "license": "MIT", + "dependencies": { + "@walletconnect/sign-client": "^2.23.0", + "@walletconnect/utils": "^2.23.0", + "@web3modal/standalone": "^2.4.3", + "framer-motion": "^12.23.24", + "next": "14.2.3", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "sonner": "^2.0.7" + }, + "devDependencies": { + "@playwright/test": "^1.56.1", + "@testing-library/jest-dom": "^6.9.1", + "@testing-library/react": "^16.3.0", + "@testing-library/user-event": "^14.6.1", + "@types/node": "^20", + "@types/react": "^18", + "@types/react-dom": "^18", + "@vitejs/plugin-react": "^5.1.1", + "@vitest/coverage-v8": "^4.0.12", + "@vitest/ui": "^4.0.12", + "autoprefixer": "^10.4.19", + "c8": "^10.1.3", + "eslint": "^8", + "eslint-config-next": "14.2.3", + "happy-dom": "^20.0.10", + "jsdom": "^27.2.0", + "postcss": "^8.4.38", + "tailwindcss": "^3.4.3", + "typescript": "^5", + "vitest": "^4.0.12" + } + }, + "node_modules/@acemir/cssom": { + "version": "0.9.31", + "resolved": "https://registry.npmjs.org/@acemir/cssom/-/cssom-0.9.31.tgz", + "integrity": "sha512-ZnR3GSaH+/vJ0YlHau21FjfLYjMpYVIzTD8M8vIEQvIGxeOXyXdzCI140rrCY862p/C/BbzWsjc1dgnM9mkoTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@adobe/css-tools": { + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.4.tgz", + "integrity": "sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@adraffy/ens-normalize": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.11.1.tgz", + "integrity": "sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ==", + "license": "MIT" + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@asamuzakjp/css-color": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-4.1.2.tgz", + "integrity": "sha512-NfBUvBaYgKIuq6E/RBLY1m0IohzNHAYyaJGuTK79Z23uNwmz2jl1mPsC5ZxCCxylinKhT1Amn5oNTlx1wN8cQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@csstools/css-calc": "^3.0.0", + "@csstools/css-color-parser": "^4.0.1", + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0", + "lru-cache": "^11.2.5" + } + }, + "node_modules/@asamuzakjp/css-color/node_modules/lru-cache": { + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", + "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@asamuzakjp/dom-selector": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-6.8.1.tgz", + "integrity": "sha512-MvRz1nCqW0fsy8Qz4dnLIvhOlMzqDVBabZx6lH+YywFDdjXhMY37SmpV1XFX3JzG5GWHn63j6HX6QPr3lZXHvQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/nwsapi": "^2.3.9", + "bidi-js": "^1.0.3", + "css-tree": "^3.1.0", + "is-potential-custom-element-name": "^1.0.1", + "lru-cache": "^11.2.6" + } + }, + "node_modules/@asamuzakjp/dom-selector/node_modules/lru-cache": { + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", + "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@asamuzakjp/nwsapi": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz", + "integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", + "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz", + "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", + "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@csstools/color-helpers": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.0.2.tgz", + "integrity": "sha512-LMGQLS9EuADloEFkcTBR3BwV/CGHV7zyDxVRtVDTwdI2Ca4it0CCVTT9wCkxSgokjE5Ho41hEPgb8OEUwoXr6Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=20.19.0" + } + }, + "node_modules/@csstools/css-calc": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.1.1.tgz", + "integrity": "sha512-HJ26Z/vmsZQqs/o3a6bgKslXGFAungXGbinULZO3eMsOyNJHeBBZfup5FiZInOghgoM4Hwnmw+OgbJCNg1wwUQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-color-parser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.0.2.tgz", + "integrity": "sha512-0GEfbBLmTFf0dJlpsNU7zwxRIH0/BGEMuXLTCvFYxuL1tNhqzTbtnFICyJLTNK4a+RechKP75e7w42ClXSnJQw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/color-helpers": "^6.0.2", + "@csstools/css-calc": "^3.1.1" + }, + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz", + "integrity": "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-syntax-patches-for-csstree": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.2.tgz", + "integrity": "sha512-5GkLzz4prTIpoyeUiIu3iV6CSG3Plo7xRVOFPKI7FVEJ3mZ0A8SwK0XU3Gl7xAkiQ+mDyam+NNp875/C5y+jSA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "peerDependencies": { + "css-tree": "^3.2.1" + }, + "peerDependenciesMeta": { + "css-tree": { + "optional": true + } + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz", + "integrity": "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + } + }, + "node_modules/@emnapi/core": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz", + "integrity": "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/core/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD", + "optional": true + }, + "node_modules/@emnapi/runtime": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz", + "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD", + "optional": true + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD", + "optional": true + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@lit-labs/ssr-dom-shim": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.5.1.tgz", + "integrity": "sha512-Aou5UdlSpr5whQe8AA/bZG0jMj96CoJIWbGfZ91qieWu5AWUMKw8VR/pAkQkJYvBNhmCcWnZlyyk5oze8JIqYA==", + "license": "BSD-3-Clause" + }, + "node_modules/@lit/reactive-element": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.6.3.tgz", + "integrity": "sha512-QuTgnG52Poic7uM1AN5yJ09QMe0O28e10XzSvWDz02TJiiKee4stsiownEIadWm8nYzyDAyT+gKzUoZmiWQtsQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.0.0" + } + }, + "node_modules/@motionone/animation": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.18.0.tgz", + "integrity": "sha512-9z2p5GFGCm0gBsZbi8rVMOAJCtw1WqBTIPw3ozk06gDvZInBPIsQcHgYogEJ4yuHJ+akuW8g1SEIOpTOvYs8hw==", + "license": "MIT", + "dependencies": { + "@motionone/easing": "^10.18.0", + "@motionone/types": "^10.17.1", + "@motionone/utils": "^10.18.0", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/animation/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@motionone/dom": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/dom/-/dom-10.18.0.tgz", + "integrity": "sha512-bKLP7E0eyO4B2UaHBBN55tnppwRnaE3KFfh3Ps9HhnAkar3Cb69kUCJY9as8LrccVYKgHA+JY5dOQqJLOPhF5A==", + "license": "MIT", + "dependencies": { + "@motionone/animation": "^10.18.0", + "@motionone/generators": "^10.18.0", + "@motionone/types": "^10.17.1", + "@motionone/utils": "^10.18.0", + "hey-listen": "^1.0.8", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/dom/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@motionone/easing": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/easing/-/easing-10.18.0.tgz", + "integrity": "sha512-VcjByo7XpdLS4o9T8t99JtgxkdMcNWD3yHU/n6CLEz3bkmKDRZyYQ/wmSf6daum8ZXqfUAgFeCZSpJZIMxaCzg==", + "license": "MIT", + "dependencies": { + "@motionone/utils": "^10.18.0", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/easing/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@motionone/generators": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/generators/-/generators-10.18.0.tgz", + "integrity": "sha512-+qfkC2DtkDj4tHPu+AFKVfR/C30O1vYdvsGYaR13W/1cczPrrcjdvYCj0VLFuRMN+lP1xvpNZHCRNM4fBzn1jg==", + "license": "MIT", + "dependencies": { + "@motionone/types": "^10.17.1", + "@motionone/utils": "^10.18.0", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/generators/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@motionone/svelte": { + "version": "10.16.4", + "resolved": "https://registry.npmjs.org/@motionone/svelte/-/svelte-10.16.4.tgz", + "integrity": "sha512-zRVqk20lD1xqe+yEDZhMYgftsuHc25+9JSo+r0a0OWUJFocjSV9D/+UGhX4xgJsuwB9acPzXLr20w40VnY2PQA==", + "license": "MIT", + "dependencies": { + "@motionone/dom": "^10.16.4", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/svelte/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@motionone/types": { + "version": "10.17.1", + "resolved": "https://registry.npmjs.org/@motionone/types/-/types-10.17.1.tgz", + "integrity": "sha512-KaC4kgiODDz8hswCrS0btrVrzyU2CSQKO7Ps90ibBVSQmjkrt2teqta6/sOG59v7+dPnKMAg13jyqtMKV2yJ7A==", + "license": "MIT" + }, + "node_modules/@motionone/utils": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/utils/-/utils-10.18.0.tgz", + "integrity": "sha512-3XVF7sgyTSI2KWvTf6uLlBJ5iAgRgmvp3bpuOiQJvInd4nZ19ET8lX5unn30SlmRH7hXbBbH+Gxd0m0klJ3Xtw==", + "license": "MIT", + "dependencies": { + "@motionone/types": "^10.17.1", + "hey-listen": "^1.0.8", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/utils/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@motionone/vue": { + "version": "10.16.4", + "resolved": "https://registry.npmjs.org/@motionone/vue/-/vue-10.16.4.tgz", + "integrity": "sha512-z10PF9JV6SbjFq+/rYabM+8CVlMokgl8RFGvieSGNTmrkQanfHn+15XBrhG3BgUfvmTeSeyShfOHpG0i9zEdcg==", + "deprecated": "Motion One for Vue is deprecated. Use Oku Motion instead https://oku-ui.com/motion", + "license": "MIT", + "dependencies": { + "@motionone/dom": "^10.16.4", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/vue/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@msgpack/msgpack": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-3.1.3.tgz", + "integrity": "sha512-47XIizs9XZXvuJgoaJUIE2lFoID8ugvc0jzSHP+Ptfk8nTbnR8g788wv48N03Kx0UkAv559HWRQ3yzOgzlRNUA==", + "license": "ISC", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" + } + }, + "node_modules/@next/env": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.3.tgz", + "integrity": "sha512-W7fd7IbkfmeeY2gXrzJYDx8D2lWKbVoTIj1o1ScPHNzvp30s1AuoEFSdr39bC5sjxJaxTtq3OTCZboNp0lNWHA==", + "license": "MIT" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.3.tgz", + "integrity": "sha512-L3oDricIIjgj1AVnRdRor21gI7mShlSwU/1ZGHmqM3LzHhXXhdkrfeNY5zif25Bi5Dd7fiJHsbhoZCHfXYvlAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob": "10.3.10" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.3.tgz", + "integrity": "sha512-3pEYo/RaGqPP0YzwnlmPN2puaF2WMLM3apt5jLW2fFdXD9+pqcoTzRk+iZsf8ta7+quAe4Q6Ms0nR0SFGFdS1A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.3.tgz", + "integrity": "sha512-6adp7waE6P1TYFSXpY366xwsOnEXM+y1kgRpjSRVI2CBDOcbRjsJ67Z6EgKIqWIue52d2q/Mx8g9MszARj8IEA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.3.tgz", + "integrity": "sha512-cuzCE/1G0ZSnTAHJPUT1rPgQx1w5tzSX7POXSLaS7w2nIUJUD+e25QoXD/hMfxbsT9rslEXugWypJMILBj/QsA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.3.tgz", + "integrity": "sha512-0D4/oMM2Y9Ta3nGuCcQN8jjJjmDPYpHX9OJzqk42NZGJocU2MqhBq5tWkJrUQOQY9N+In9xOdymzapM09GeiZw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.3.tgz", + "integrity": "sha512-ENPiNnBNDInBLyUU5ii8PMQh+4XLr4pG51tOp6aJ9xqFQ2iRI6IH0Ds2yJkAzNV1CfyagcyzPfROMViS2wOZ9w==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.3.tgz", + "integrity": "sha512-BTAbq0LnCbF5MtoM7I/9UeUu/8ZBY0i8SFjUMCbPDOLv+un67e2JgyN4pmgfXBwy/I+RHu8q+k+MCkDN6P9ViQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.3.tgz", + "integrity": "sha512-AEHIw/dhAMLNFJFJIJIyOFDzrzI5bAjI9J26gbO5xhAKHYTZ9Or04BesFPXiAYXDNdrwTP2dQceYA4dL1geu8A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.3.tgz", + "integrity": "sha512-vga40n1q6aYb0CLrM+eEmisfKCR45ixQYXuBXxOOmmoV8sYST9k7E3US32FsY+CkkF7NtzdcebiFT4CHuMSyZw==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.3.tgz", + "integrity": "sha512-Q1/zm43RWynxrO7lW4ehciQVj+5ePBhOK+/K2P7pLFX3JaJ/IZVC69SHidrmZSOkqz7ECIOhhy7XhAFG4JYyHA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@noble/ciphers": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.3.0.tgz", + "integrity": "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/curves": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.0.tgz", + "integrity": "sha512-j84kjAbzEnQHaSIhRPUmB3/eVXu2k3dKPl2LOrR8fSOIL+89U+7lV117EWHtq/GHM3ReGHM46iRBdZfpc4HRUQ==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.7.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.0.tgz", + "integrity": "sha512-HXydb0DgzTpDPwbVeDGCG1gIu7X6+AuU6Zl6av/E/KG8LMsvPntvq+w17CHRpKBmN6Ybdrt1eP3k4cj8DJa78w==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.4.0" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.122.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.122.0.tgz", + "integrity": "sha512-oLAl5kBpV4w69UtFZ9xqcmTi+GENWOcPF7FCrczTiBbmC0ibXxCwyvZGbO39rCVEuLGAZM84DH0pUIyyv/YJzA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@playwright/test": { + "version": "1.59.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.59.1.tgz", + "integrity": "sha512-PG6q63nQg5c9rIi4/Z5lR5IVF7yU5MqmKaPOe0HSc0O2cX1fPi96sUQu5j7eo4gKCkB2AnNGoWt7y4/Xx3Kcqg==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.59.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polka/url": { + "version": "1.0.0-next.29", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.12.tgz", + "integrity": "sha512-pv1y2Fv0JybcykuiiD3qBOBdz6RteYojRFY1d+b95WVuzx211CRh+ytI/+9iVyWQ6koTh5dawe4S/yRfOFjgaA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.12.tgz", + "integrity": "sha512-cFYr6zTG/3PXXF3pUO+umXxt1wkRK/0AYT8lDwuqvRC+LuKYWSAQAQZjCWDQpAH172ZV6ieYrNnFzVVcnSflAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.12.tgz", + "integrity": "sha512-ZCsYknnHzeXYps0lGBz8JrF37GpE9bFVefrlmDrAQhOEi4IOIlcoU1+FwHEtyXGx2VkYAvhu7dyBf75EJQffBw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.12.tgz", + "integrity": "sha512-dMLeprcVsyJsKolRXyoTH3NL6qtsT0Y2xeuEA8WQJquWFXkEC4bcu1rLZZSnZRMtAqwtrF/Ib9Ddtpa/Gkge9Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.12.tgz", + "integrity": "sha512-YqWjAgGC/9M1lz3GR1r1rP79nMgo3mQiiA+Hfo+pvKFK1fAJ1bCi0ZQVh8noOqNacuY1qIcfyVfP6HoyBRZ85Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.12.tgz", + "integrity": "sha512-/I5AS4cIroLpslsmzXfwbe5OmWvSsrFuEw3mwvbQ1kDxJ822hFHIx+vsN/TAzNVyepI/j/GSzrtCIwQPeKCLIg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.12.tgz", + "integrity": "sha512-V6/wZztnBqlx5hJQqNWwFdxIKN0m38p8Jas+VoSfgH54HSj9tKTt1dZvG6JRHcjh6D7TvrJPWFGaY9UBVOaWPw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.12.tgz", + "integrity": "sha512-AP3E9BpcUYliZCxa3w5Kwj9OtEVDYK6sVoUzy4vTOJsjPOgdaJZKFmN4oOlX0Wp0RPV2ETfmIra9x1xuayFB7g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.12.tgz", + "integrity": "sha512-nWwpvUSPkoFmZo0kQazZYOrT7J5DGOJ/+QHHzjvNlooDZED8oH82Yg67HvehPPLAg5fUff7TfWFHQS8IV1n3og==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.12.tgz", + "integrity": "sha512-RNrafz5bcwRy+O9e6P8Z/OCAJW/A+qtBczIqVYwTs14pf4iV1/+eKEjdOUta93q2TsT/FI0XYDP3TCky38LMAg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.12.tgz", + "integrity": "sha512-Jpw/0iwoKWx3LJ2rc1yjFrj+T7iHZn2JDg1Yny1ma0luviFS4mhAIcd1LFNxK3EYu3DHWCps0ydXQ5i/rrJ2ig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.12.tgz", + "integrity": "sha512-vRugONE4yMfVn0+7lUKdKvN4D5YusEiPilaoO2sgUWpCvrncvWgPMzK00ZFFJuiPgLwgFNP5eSiUlv2tfc+lpA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.12.tgz", + "integrity": "sha512-ykGiLr/6kkiHc0XnBfmFJuCjr5ZYKKofkx+chJWDjitX+KsJuAmrzWhwyOMSHzPhzOHOy7u9HlFoa5MoAOJ/Zg==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^1.1.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.2.tgz", + "integrity": "sha512-sNXv5oLJ7ob93xkZ1XnxisYhGYXfaG9f65/ZgYuAu3qt7b3NadcOEhLvx28hv31PgX8SZJRYrAIPQilQmFpLVw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.12.tgz", + "integrity": "sha512-5eOND4duWkwx1AzCxadcOrNeighiLwMInEADT0YM7xeEOOFcovWZCq8dadXgcRHSf3Ulh1kFo/qvzoFiCLOL1Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.12.tgz", + "integrity": "sha512-PyqoipaswDLAZtot351MLhrlrh6lcZPo2LSYE+VDxbVk24LVKAGOuE4hb8xZQmrPAuEtTZW8E6D2zc5EUZX4Lw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz", + "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.16.1.tgz", + "integrity": "sha512-TvZbIpeKqGQQ7X0zSCvPH9riMSFQFSggnfBjFZ1mEoILW+UuXCKwOoPcgjMwiUtRqFZ8jWhPJc4um14vC6I4ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@scure/base": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz", + "integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.7.0.tgz", + "integrity": "sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==", + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.9.0", + "@noble/hashes": "~1.8.0", + "@scure/base": "~1.2.5" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@noble/curves": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz", + "integrity": "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.6.0.tgz", + "integrity": "sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.8.0", + "@scure/base": "~1.2.5" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39/node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "license": "Apache-2.0" + }, + "node_modules/@swc/helpers": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", + "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3", + "tslib": "^2.4.0" + } + }, + "node_modules/@swc/helpers/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/@testing-library/dom": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz", + "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "picocolors": "1.1.1", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/jest-dom": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.9.1.tgz", + "integrity": "sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@adobe/css-tools": "^4.4.0", + "aria-query": "^5.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "picocolors": "^1.1.1", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@testing-library/react": { + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.2.tgz", + "integrity": "sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@testing-library/dom": "^10.0.0", + "@types/react": "^18.0.0 || ^19.0.0", + "@types/react-dom": "^18.0.0 || ^19.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@testing-library/user-event": { + "version": "14.6.1", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.6.1.tgz", + "integrity": "sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tybys/wasm-util/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD", + "optional": true + }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.19.37", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.37.tgz", + "integrity": "sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.28", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz", + "integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT" + }, + "node_modules/@types/whatwg-mimetype": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-mimetype/-/whatwg-mimetype-3.0.2.tgz", + "integrity": "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.2.0.tgz", + "integrity": "sha512-5FKsVcHTk6TafQKQbuIVkXq58Fnbkd2wDL4LB7AURN7RUOu1utVP+G8+6u3ZhEroW3DF6hyo3ZEXxgKgp4KeCg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "7.2.0", + "@typescript-eslint/types": "7.2.0", + "@typescript-eslint/typescript-estree": "7.2.0", + "@typescript-eslint/visitor-keys": "7.2.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.2.0.tgz", + "integrity": "sha512-Qh976RbQM/fYtjx9hs4XkayYujB/aPwglw2choHmf3zBjB4qOywWSdt9+KLRdHubGcoSwBnXUH2sR3hkyaERRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "7.2.0", + "@typescript-eslint/visitor-keys": "7.2.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.2.0.tgz", + "integrity": "sha512-XFtUHPI/abFhm4cbCDc5Ykc8npOKBSJePY3a3s+lwumt7XWJuzP5cZcfZ610MIPHjQjNsOLlYK8ASPaNG8UiyA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.2.0.tgz", + "integrity": "sha512-cyxS5WQQCoBwSakpMrvMXuMDEbhOo9bNHHrNcEWis6XHx6KF518tkF1wBvKIn/tpq5ZpUYK7Bdklu8qY0MsFIA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "7.2.0", + "@typescript-eslint/visitor-keys": "7.2.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.2.0.tgz", + "integrity": "sha512-c6EIQRHhcpl6+tO8EMR+kjkkV+ugUNXOmeASA1rlzkd8EPIriavpWoiEz1HR/VLhbVIdhqnV6E7JZm00cBDx2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "7.2.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", + "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", + "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", + "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", + "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", + "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", + "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", + "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", + "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", + "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", + "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", + "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", + "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", + "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", + "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", + "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", + "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.11" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", + "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", + "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", + "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@vitejs/plugin-react": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.2.0.tgz", + "integrity": "sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.29.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-rc.3", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.18.0" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@vitest/coverage-v8": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.2.tgz", + "integrity": "sha512-sPK//PHO+kAkScb8XITeB1bf7fsk85Km7+rt4eeuRR3VS1/crD47cmV5wicisJmjNdfeokTZwjMk4Mj2d58Mgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^1.0.2", + "@vitest/utils": "4.1.2", + "ast-v8-to-istanbul": "^1.0.0", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.2.0", + "magicast": "^0.5.2", + "obug": "^2.1.1", + "std-env": "^4.0.0-rc.1", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/browser": "4.1.2", + "vitest": "4.1.2" + }, + "peerDependenciesMeta": { + "@vitest/browser": { + "optional": true + } + } + }, + "node_modules/@vitest/expect": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.2.tgz", + "integrity": "sha512-gbu+7B0YgUJ2nkdsRJrFFW6X7NTP44WlhiclHniUhxADQJH5Szt9mZ9hWnJPJ8YwOK5zUOSSlSvyzRf0u1DSBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.2", + "@vitest/utils": "4.1.2", + "chai": "^6.2.2", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.2.tgz", + "integrity": "sha512-Ize4iQtEALHDttPRCmN+FKqOl2vxTiNUhzobQFFt/BM1lRUTG7zRCLOykG/6Vo4E4hnUdfVLo5/eqKPukcWW7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "4.1.2", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.2.tgz", + "integrity": "sha512-dwQga8aejqeuB+TvXCMzSQemvV9hNEtDDpgUKDzOmNQayl2OG241PSWeJwKRH3CiC+sESrmoFd49rfnq7T4RnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.2.tgz", + "integrity": "sha512-Gr+FQan34CdiYAwpGJmQG8PgkyFVmARK8/xSijia3eTFgVfpcpztWLuP6FttGNfPLJhaZVP/euvujeNYar36OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.1.2", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.2.tgz", + "integrity": "sha512-g7yfUmxYS4mNxk31qbOYsSt2F4m1E02LFqO53Xpzg3zKMhLAPZAjjfyl9e6z7HrW6LvUdTwAQR3HHfLjpko16A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.2", + "@vitest/utils": "4.1.2", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.2.tgz", + "integrity": "sha512-DU4fBnbVCJGNBwVA6xSToNXrkZNSiw59H8tcuUspVMsBDBST4nfvsPsEHDHGtWRRnqBERBQu7TrTKskmjqTXKA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/ui": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-4.1.2.tgz", + "integrity": "sha512-/irhyeAcKS2u6Zokagf9tqZJ0t8S6kMZq4ZG9BHZv7I+fkRrYfQX4w7geYeC2r6obThz39PDxvXQzZX+qXqGeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.1.2", + "fflate": "^0.8.2", + "flatted": "^3.4.2", + "pathe": "^2.0.3", + "sirv": "^3.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "vitest": "4.1.2" + } + }, + "node_modules/@vitest/utils": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.2.tgz", + "integrity": "sha512-xw2/TiX82lQHA06cgbqRKFb5lCAy3axQ4H4SoUFhUsg+wztiet+co86IAMDtF6Vm1hc7J6j09oh/rgDn+JdKIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.2", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@walletconnect/core": { + "version": "2.23.9", + "resolved": "https://registry.npmjs.org/@walletconnect/core/-/core-2.23.9.tgz", + "integrity": "sha512-ws4WG8LeagUo2ERRo02HryXRcpwIRmCQ3pHLW5gWbVReLXXIpgk6ZAfID3fEGHevIwwnHSGww+nNhNpdXyiq0g==", + "license": "SEE LICENSE IN LICENSE.md", + "dependencies": { + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-provider": "1.0.14", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/jsonrpc-ws-connection": "1.0.16", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "3.0.2", + "@walletconnect/relay-api": "1.0.11", + "@walletconnect/relay-auth": "1.1.0", + "@walletconnect/safe-json": "1.0.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.23.9", + "@walletconnect/utils": "2.23.9", + "@walletconnect/window-getters": "1.0.1", + "es-toolkit": "1.44.0", + "events": "3.3.0", + "uint8arrays": "3.1.1" + }, + "engines": { + "node": ">=18.20.8" + } + }, + "node_modules/@walletconnect/core/node_modules/@walletconnect/keyvaluestorage": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@walletconnect/keyvaluestorage/-/keyvaluestorage-1.1.1.tgz", + "integrity": "sha512-V7ZQq2+mSxAq7MrRqDxanTzu2RcElfK1PfNYiaVnJgJ7Q7G7hTVwF8voIBx92qsRyGHZihrwNPHuZd1aKkd0rA==", + "license": "MIT", + "dependencies": { + "@walletconnect/safe-json": "^1.0.1", + "idb-keyval": "^6.2.1", + "unstorage": "^1.9.0" + }, + "peerDependencies": { + "@react-native-async-storage/async-storage": "1.x" + }, + "peerDependenciesMeta": { + "@react-native-async-storage/async-storage": { + "optional": true + } + } + }, + "node_modules/@walletconnect/core/node_modules/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "license": "MIT", + "dependencies": { + "readdirp": "^5.0.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@walletconnect/core/node_modules/lru-cache": { + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", + "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@walletconnect/core/node_modules/readdirp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", + "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@walletconnect/core/node_modules/unstorage": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.5.tgz", + "integrity": "sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg==", + "license": "MIT", + "dependencies": { + "anymatch": "^3.1.3", + "chokidar": "^5.0.0", + "destr": "^2.0.5", + "h3": "^1.15.10", + "lru-cache": "^11.2.7", + "node-fetch-native": "^1.6.7", + "ofetch": "^1.5.1", + "ufo": "^1.6.3" + }, + "peerDependencies": { + "@azure/app-configuration": "^1.8.0", + "@azure/cosmos": "^4.2.0", + "@azure/data-tables": "^13.3.0", + "@azure/identity": "^4.6.0", + "@azure/keyvault-secrets": "^4.9.0", + "@azure/storage-blob": "^12.26.0", + "@capacitor/preferences": "^6 || ^7 || ^8", + "@deno/kv": ">=0.9.0", + "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", + "@planetscale/database": "^1.19.0", + "@upstash/redis": "^1.34.3", + "@vercel/blob": ">=0.27.1", + "@vercel/functions": "^2.2.12 || ^3.0.0", + "@vercel/kv": "^1 || ^2 || ^3", + "aws4fetch": "^1.0.20", + "db0": ">=0.2.1", + "idb-keyval": "^6.2.1", + "ioredis": "^5.4.2", + "uploadthing": "^7.4.4" + }, + "peerDependenciesMeta": { + "@azure/app-configuration": { + "optional": true + }, + "@azure/cosmos": { + "optional": true + }, + "@azure/data-tables": { + "optional": true + }, + "@azure/identity": { + "optional": true + }, + "@azure/keyvault-secrets": { + "optional": true + }, + "@azure/storage-blob": { + "optional": true + }, + "@capacitor/preferences": { + "optional": true + }, + "@deno/kv": { + "optional": true + }, + "@netlify/blobs": { + "optional": true + }, + "@planetscale/database": { + "optional": true + }, + "@upstash/redis": { + "optional": true + }, + "@vercel/blob": { + "optional": true + }, + "@vercel/functions": { + "optional": true + }, + "@vercel/kv": { + "optional": true + }, + "aws4fetch": { + "optional": true + }, + "db0": { + "optional": true + }, + "idb-keyval": { + "optional": true + }, + "ioredis": { + "optional": true + }, + "uploadthing": { + "optional": true + } + } + }, + "node_modules/@walletconnect/environment": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@walletconnect/environment/-/environment-1.0.1.tgz", + "integrity": "sha512-T426LLZtHj8e8rYnKfzsw1aG6+M0BT1ZxayMdv/p8yM0MU+eJDISqNY3/bccxRr4LrF9csq02Rhqt08Ibl0VRg==", + "license": "MIT", + "dependencies": { + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/events": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@walletconnect/events/-/events-1.0.1.tgz", + "integrity": "sha512-NPTqaoi0oPBVNuLv7qPaJazmGHs5JGyO8eEAk5VGKmJzDR7AHzD4k6ilox5kxk1iwiOnFopBOOMLs86Oa76HpQ==", + "license": "MIT", + "dependencies": { + "keyvaluestorage-interface": "^1.0.0", + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/heartbeat": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@walletconnect/heartbeat/-/heartbeat-1.2.2.tgz", + "integrity": "sha512-uASiRmC5MwhuRuf05vq4AT48Pq8RMi876zV8rr8cV969uTOzWdB/k+Lj5yI2PBtB1bGQisGen7MM1GcZlQTBXw==", + "license": "MIT", + "dependencies": { + "@walletconnect/events": "^1.0.1", + "@walletconnect/time": "^1.0.2", + "events": "^3.3.0" + } + }, + "node_modules/@walletconnect/jsonrpc-provider": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-provider/-/jsonrpc-provider-1.0.14.tgz", + "integrity": "sha512-rtsNY1XqHvWj0EtITNeuf8PHMvlCLiS3EjQL+WOkxEOA4KPxsohFnBDeyPYiNm4ZvkQdLnece36opYidmtbmow==", + "license": "MIT", + "dependencies": { + "@walletconnect/jsonrpc-utils": "^1.0.8", + "@walletconnect/safe-json": "^1.0.2", + "events": "^3.3.0" + } + }, + "node_modules/@walletconnect/jsonrpc-types": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-types/-/jsonrpc-types-1.0.4.tgz", + "integrity": "sha512-P6679fG/M+wuWg9TY8mh6xFSdYnFyFjwFelxyISxMDrlbXokorEVXYOxiqEbrU3x1BmBoCAJJ+vtEaEoMlpCBQ==", + "license": "MIT", + "dependencies": { + "events": "^3.3.0", + "keyvaluestorage-interface": "^1.0.0" + } + }, + "node_modules/@walletconnect/jsonrpc-utils": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-utils/-/jsonrpc-utils-1.0.8.tgz", + "integrity": "sha512-vdeb03bD8VzJUL6ZtzRYsFMq1eZQcM3EAzT0a3st59dyLfJ0wq+tKMpmGH7HlB7waD858UWgfIcudbPFsbzVdw==", + "license": "MIT", + "dependencies": { + "@walletconnect/environment": "^1.0.1", + "@walletconnect/jsonrpc-types": "^1.0.3", + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/jsonrpc-ws-connection": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-ws-connection/-/jsonrpc-ws-connection-1.0.16.tgz", + "integrity": "sha512-G81JmsMqh5nJheE1mPst1W0WfVv0SG3N7JggwLLGnI7iuDZJq8cRJvQwLGKHn5H1WTW7DEPCo00zz5w62AbL3Q==", + "license": "MIT", + "dependencies": { + "@walletconnect/jsonrpc-utils": "^1.0.6", + "@walletconnect/safe-json": "^1.0.2", + "events": "^3.3.0", + "ws": "^7.5.1" + } + }, + "node_modules/@walletconnect/logger": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@walletconnect/logger/-/logger-3.0.2.tgz", + "integrity": "sha512-7wR3wAwJTOmX4gbcUZcFMov8fjftY05+5cO/d4cpDD8wDzJ+cIlKdYOXaXfxHLSYeDazMXIsxMYjHYVDfkx+nA==", + "license": "MIT", + "dependencies": { + "@walletconnect/safe-json": "^1.0.2", + "pino": "10.0.0" + } + }, + "node_modules/@walletconnect/relay-api": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@walletconnect/relay-api/-/relay-api-1.0.11.tgz", + "integrity": "sha512-tLPErkze/HmC9aCmdZOhtVmYZq1wKfWTJtygQHoWtgg722Jd4homo54Cs4ak2RUFUZIGO2RsOpIcWipaua5D5Q==", + "license": "MIT", + "dependencies": { + "@walletconnect/jsonrpc-types": "^1.0.2" + } + }, + "node_modules/@walletconnect/relay-auth": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@walletconnect/relay-auth/-/relay-auth-1.1.0.tgz", + "integrity": "sha512-qFw+a9uRz26jRCDgL7Q5TA9qYIgcNY8jpJzI1zAWNZ8i7mQjaijRnWFKsCHAU9CyGjvt6RKrRXyFtFOpWTVmCQ==", + "license": "MIT", + "dependencies": { + "@noble/curves": "1.8.0", + "@noble/hashes": "1.7.0", + "@walletconnect/safe-json": "^1.0.1", + "@walletconnect/time": "^1.0.2", + "uint8arrays": "^3.0.0" + } + }, + "node_modules/@walletconnect/safe-json": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@walletconnect/safe-json/-/safe-json-1.0.2.tgz", + "integrity": "sha512-Ogb7I27kZ3LPC3ibn8ldyUr5544t3/STow9+lzz7Sfo808YD7SBWk7SAsdBFlYgP2zDRy2hS3sKRcuSRM0OTmA==", + "license": "MIT", + "dependencies": { + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/sign-client": { + "version": "2.23.9", + "resolved": "https://registry.npmjs.org/@walletconnect/sign-client/-/sign-client-2.23.9.tgz", + "integrity": "sha512-Xj+hw4E6mGRyhCdVOT/RMgnG+up/Y3v0ho5PlkVozvXWeVSqHNh9DmjLuU97a7OACoGd/oHBF6g3NVqD7MgCMQ==", + "license": "SEE LICENSE IN LICENSE.md", + "dependencies": { + "@walletconnect/core": "2.23.9", + "@walletconnect/events": "1.0.1", + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/logger": "3.0.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.23.9", + "@walletconnect/utils": "2.23.9", + "events": "3.3.0" + } + }, + "node_modules/@walletconnect/time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@walletconnect/time/-/time-1.0.2.tgz", + "integrity": "sha512-uzdd9woDcJ1AaBZRhqy5rNC9laqWGErfc4dxA9a87mPdKOgWMD85mcFo9dIYIts/Jwocfwn07EC6EzclKubk/g==", + "license": "MIT", + "dependencies": { + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/types": { + "version": "2.23.9", + "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-2.23.9.tgz", + "integrity": "sha512-IUl1PpD/Dig8IE2OZ9XtjbPohEyOZJ73xs92EDUzoIyzRtfm36g2D340pY3iu3AAdLv1yFiaZafB8Hf8RFze8A==", + "license": "SEE LICENSE IN LICENSE.md", + "dependencies": { + "@walletconnect/events": "1.0.1", + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "3.0.2", + "events": "3.3.0" + } + }, + "node_modules/@walletconnect/types/node_modules/@walletconnect/keyvaluestorage": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@walletconnect/keyvaluestorage/-/keyvaluestorage-1.1.1.tgz", + "integrity": "sha512-V7ZQq2+mSxAq7MrRqDxanTzu2RcElfK1PfNYiaVnJgJ7Q7G7hTVwF8voIBx92qsRyGHZihrwNPHuZd1aKkd0rA==", + "license": "MIT", + "dependencies": { + "@walletconnect/safe-json": "^1.0.1", + "idb-keyval": "^6.2.1", + "unstorage": "^1.9.0" + }, + "peerDependencies": { + "@react-native-async-storage/async-storage": "1.x" + }, + "peerDependenciesMeta": { + "@react-native-async-storage/async-storage": { + "optional": true + } + } + }, + "node_modules/@walletconnect/types/node_modules/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "license": "MIT", + "dependencies": { + "readdirp": "^5.0.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@walletconnect/types/node_modules/lru-cache": { + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", + "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@walletconnect/types/node_modules/readdirp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", + "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@walletconnect/types/node_modules/unstorage": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.5.tgz", + "integrity": "sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg==", + "license": "MIT", + "dependencies": { + "anymatch": "^3.1.3", + "chokidar": "^5.0.0", + "destr": "^2.0.5", + "h3": "^1.15.10", + "lru-cache": "^11.2.7", + "node-fetch-native": "^1.6.7", + "ofetch": "^1.5.1", + "ufo": "^1.6.3" + }, + "peerDependencies": { + "@azure/app-configuration": "^1.8.0", + "@azure/cosmos": "^4.2.0", + "@azure/data-tables": "^13.3.0", + "@azure/identity": "^4.6.0", + "@azure/keyvault-secrets": "^4.9.0", + "@azure/storage-blob": "^12.26.0", + "@capacitor/preferences": "^6 || ^7 || ^8", + "@deno/kv": ">=0.9.0", + "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", + "@planetscale/database": "^1.19.0", + "@upstash/redis": "^1.34.3", + "@vercel/blob": ">=0.27.1", + "@vercel/functions": "^2.2.12 || ^3.0.0", + "@vercel/kv": "^1 || ^2 || ^3", + "aws4fetch": "^1.0.20", + "db0": ">=0.2.1", + "idb-keyval": "^6.2.1", + "ioredis": "^5.4.2", + "uploadthing": "^7.4.4" + }, + "peerDependenciesMeta": { + "@azure/app-configuration": { + "optional": true + }, + "@azure/cosmos": { + "optional": true + }, + "@azure/data-tables": { + "optional": true + }, + "@azure/identity": { + "optional": true + }, + "@azure/keyvault-secrets": { + "optional": true + }, + "@azure/storage-blob": { + "optional": true + }, + "@capacitor/preferences": { + "optional": true + }, + "@deno/kv": { + "optional": true + }, + "@netlify/blobs": { + "optional": true + }, + "@planetscale/database": { + "optional": true + }, + "@upstash/redis": { + "optional": true + }, + "@vercel/blob": { + "optional": true + }, + "@vercel/functions": { + "optional": true + }, + "@vercel/kv": { + "optional": true + }, + "aws4fetch": { + "optional": true + }, + "db0": { + "optional": true + }, + "idb-keyval": { + "optional": true + }, + "ioredis": { + "optional": true + }, + "uploadthing": { + "optional": true + } + } + }, + "node_modules/@walletconnect/utils": { + "version": "2.23.9", + "resolved": "https://registry.npmjs.org/@walletconnect/utils/-/utils-2.23.9.tgz", + "integrity": "sha512-C5TltCs8UPypNiteYnKSv8+ZDK2EjVDyXCxN6kA9bkA+j6KGsNIV7l9MUA8WBAvE5Gi5EcBdhD3R9Hpo/1HHqQ==", + "license": "SEE LICENSE IN LICENSE.md", + "dependencies": { + "@msgpack/msgpack": "3.1.3", + "@noble/ciphers": "1.3.0", + "@noble/curves": "1.9.7", + "@noble/hashes": "1.8.0", + "@scure/base": "1.2.6", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "3.0.2", + "@walletconnect/relay-api": "1.0.11", + "@walletconnect/relay-auth": "1.1.0", + "@walletconnect/safe-json": "1.0.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.23.9", + "@walletconnect/window-getters": "1.0.1", + "@walletconnect/window-metadata": "1.0.1", + "blakejs": "1.2.1", + "detect-browser": "5.3.0", + "ox": "0.9.3", + "uint8arrays": "3.1.1" + } + }, + "node_modules/@walletconnect/utils/node_modules/@noble/curves": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz", + "integrity": "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@walletconnect/utils/node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@walletconnect/utils/node_modules/@walletconnect/keyvaluestorage": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@walletconnect/keyvaluestorage/-/keyvaluestorage-1.1.1.tgz", + "integrity": "sha512-V7ZQq2+mSxAq7MrRqDxanTzu2RcElfK1PfNYiaVnJgJ7Q7G7hTVwF8voIBx92qsRyGHZihrwNPHuZd1aKkd0rA==", + "license": "MIT", + "dependencies": { + "@walletconnect/safe-json": "^1.0.1", + "idb-keyval": "^6.2.1", + "unstorage": "^1.9.0" + }, + "peerDependencies": { + "@react-native-async-storage/async-storage": "1.x" + }, + "peerDependenciesMeta": { + "@react-native-async-storage/async-storage": { + "optional": true + } + } + }, + "node_modules/@walletconnect/utils/node_modules/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "license": "MIT", + "dependencies": { + "readdirp": "^5.0.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@walletconnect/utils/node_modules/lru-cache": { + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", + "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@walletconnect/utils/node_modules/readdirp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", + "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@walletconnect/utils/node_modules/unstorage": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.5.tgz", + "integrity": "sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg==", + "license": "MIT", + "dependencies": { + "anymatch": "^3.1.3", + "chokidar": "^5.0.0", + "destr": "^2.0.5", + "h3": "^1.15.10", + "lru-cache": "^11.2.7", + "node-fetch-native": "^1.6.7", + "ofetch": "^1.5.1", + "ufo": "^1.6.3" + }, + "peerDependencies": { + "@azure/app-configuration": "^1.8.0", + "@azure/cosmos": "^4.2.0", + "@azure/data-tables": "^13.3.0", + "@azure/identity": "^4.6.0", + "@azure/keyvault-secrets": "^4.9.0", + "@azure/storage-blob": "^12.26.0", + "@capacitor/preferences": "^6 || ^7 || ^8", + "@deno/kv": ">=0.9.0", + "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", + "@planetscale/database": "^1.19.0", + "@upstash/redis": "^1.34.3", + "@vercel/blob": ">=0.27.1", + "@vercel/functions": "^2.2.12 || ^3.0.0", + "@vercel/kv": "^1 || ^2 || ^3", + "aws4fetch": "^1.0.20", + "db0": ">=0.2.1", + "idb-keyval": "^6.2.1", + "ioredis": "^5.4.2", + "uploadthing": "^7.4.4" + }, + "peerDependenciesMeta": { + "@azure/app-configuration": { + "optional": true + }, + "@azure/cosmos": { + "optional": true + }, + "@azure/data-tables": { + "optional": true + }, + "@azure/identity": { + "optional": true + }, + "@azure/keyvault-secrets": { + "optional": true + }, + "@azure/storage-blob": { + "optional": true + }, + "@capacitor/preferences": { + "optional": true + }, + "@deno/kv": { + "optional": true + }, + "@netlify/blobs": { + "optional": true + }, + "@planetscale/database": { + "optional": true + }, + "@upstash/redis": { + "optional": true + }, + "@vercel/blob": { + "optional": true + }, + "@vercel/functions": { + "optional": true + }, + "@vercel/kv": { + "optional": true + }, + "aws4fetch": { + "optional": true + }, + "db0": { + "optional": true + }, + "idb-keyval": { + "optional": true + }, + "ioredis": { + "optional": true + }, + "uploadthing": { + "optional": true + } + } + }, + "node_modules/@walletconnect/window-getters": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@walletconnect/window-getters/-/window-getters-1.0.1.tgz", + "integrity": "sha512-vHp+HqzGxORPAN8gY03qnbTMnhqIwjeRJNOMOAzePRg4xVEEE2WvYsI9G2NMjOknA8hnuYbU3/hwLcKbjhc8+Q==", + "license": "MIT", + "dependencies": { + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/window-metadata": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@walletconnect/window-metadata/-/window-metadata-1.0.1.tgz", + "integrity": "sha512-9koTqyGrM2cqFRW517BPY/iEtUDx2r1+Pwwu5m7sJ7ka79wi3EyqhqcICk/yDmv6jAS1rjKgTKXlEhanYjijcA==", + "license": "MIT", + "dependencies": { + "@walletconnect/window-getters": "^1.0.1", + "tslib": "1.14.1" + } + }, + "node_modules/@web3modal/core": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/@web3modal/core/-/core-2.4.3.tgz", + "integrity": "sha512-7Z/sDe9RIYQ2k9ITcxgEa/u7FvlI76vcVVZn9UY4ISivefqrH4JAS3GX4JmVNUUlovwuiZdyqBv4llAQOMK6Rg==", + "deprecated": "Web3Modal is now Reown AppKit. Please follow the upgrade guide at https://docs.reown.com/appkit/upgrade/from-w3m-to-reown", + "license": "Apache-2.0", + "dependencies": { + "buffer": "6.0.3", + "valtio": "1.10.5" + } + }, + "node_modules/@web3modal/standalone": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/@web3modal/standalone/-/standalone-2.4.3.tgz", + "integrity": "sha512-5ATXBoa4GGm+TIUSsKWsfWCJunv1XevOizpgTFhqyeGgRDmWhqsz9UIPzH/1mk+g0iJ/xqMKs5F6v9D2QeKxag==", + "deprecated": "This package has been deprecated in favor of @walletconnect/modal. Please read more at https://docs.walletconnect.com", + "license": "Apache-2.0", + "dependencies": { + "@web3modal/core": "2.4.3", + "@web3modal/ui": "2.4.3" + } + }, + "node_modules/@web3modal/ui": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/@web3modal/ui/-/ui-2.4.3.tgz", + "integrity": "sha512-J989p8CdtEhI9gZHf/rZ/WFqYlrAHWw9GmAhFoiNODwjAp0BoG/uoaPiijJMchXdngihZOjLGCQwDXU16DHiKg==", + "deprecated": "Web3Modal is now Reown AppKit. Please follow the upgrade guide at https://docs.reown.com/appkit/upgrade/from-w3m-to-reown", + "license": "Apache-2.0", + "dependencies": { + "@web3modal/core": "2.4.3", + "lit": "2.7.5", + "motion": "10.16.2", + "qrcode": "1.5.3" + } + }, + "node_modules/abitype": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.2.3.tgz", + "integrity": "sha512-Ofer5QUnuUdTFsBRwARMoWKOH1ND5ehwYhJ3OJ/BQO+StkwQjHw0XyVh4vDttzHB7QOFhPHa/o413PJ82gU/Tg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/wevm" + }, + "peerDependencies": { + "typescript": ">=5.0.4", + "zod": "^3.22.0 || ^4.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ajv": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true, + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true, + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/ast-v8-to-istanbul": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.0.tgz", + "integrity": "sha512-1fSfIwuDICFA4LKkCzRPO7F0hzFf0B7+Xqrl27ynQaa+Rh0e1Es0v6kWHPott3lU10AyAr7oKHa65OppjLn3Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.31", + "estree-walker": "^3.0.3", + "js-tokens": "^10.0.0" + } + }, + "node_modules/ast-v8-to-istanbul/node_modules/js-tokens": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz", + "integrity": "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.27", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.27.tgz", + "integrity": "sha512-NP9APE+tO+LuJGn7/9+cohklunJsXWiaWEfV3si4Gi/XHDwVNgkwr1J3RQYFIvPy76GmJ9/bW8vyoU1LcxwKHA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.1", + "caniuse-lite": "^1.0.30001774", + "fraction.js": "^5.3.4", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.11.2", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.11.2.tgz", + "integrity": "sha512-byD6KPdvo72y/wj2T/4zGEvvlis+PsZsn/yPS3pEO+sFpcrqRpX/TJCxvVaEsNeMrfQbCr7w163YqoD9IYwHXw==", + "dev": true, + "license": "MPL-2.0", + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.13", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.13.tgz", + "integrity": "sha512-BL2sTuHOdy0YT1lYieUxTw/QMtPBC3pmlJC6xk8BBYVv6vcw3SGdKemQ+Xsx9ik2F/lYDO9tqsFQH1r9PFuHKw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/bidi-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", + "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "require-from-string": "^2.0.2" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/blakejs": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", + "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==", + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.10.12", + "caniuse-lite": "^1.0.30001782", + "electron-to-chromium": "^1.5.328", + "node-releases": "^2.0.36", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/c8": { + "version": "10.1.3", + "resolved": "https://registry.npmjs.org/c8/-/c8-10.1.3.tgz", + "integrity": "sha512-LvcyrOAaOnrrlMpW22n690PUvxiq4Uf9WMhQwNJ9vgagkL/ph1+D4uvjvDA5XCbykrc0sx+ay6pVi9YZ1GnhyA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@bcoe/v8-coverage": "^1.0.1", + "@istanbuljs/schema": "^0.1.3", + "find-up": "^5.0.0", + "foreground-child": "^3.1.1", + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.1.6", + "test-exclude": "^7.0.1", + "v8-to-istanbul": "^9.0.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1" + }, + "bin": { + "c8": "bin/c8.js" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "monocart-coverage-reports": "^2" + }, + "peerDependenciesMeta": { + "monocart-coverage-reports": { + "optional": true + } + } + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001784", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001784.tgz", + "integrity": "sha512-WU346nBTklUV9YfUl60fqRbU5ZqyXlqvo1SgigE1OAXK5bFL8LL9q1K7aap3N739l4BvNqnkm3YrGHiY9sfUQw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie-es": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-1.2.3.tgz", + "integrity": "sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw==", + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crossws": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/crossws/-/crossws-0.3.5.tgz", + "integrity": "sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==", + "license": "MIT", + "dependencies": { + "uncrypto": "^0.1.3" + } + }, + "node_modules/css-tree": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz", + "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdn-data": "2.27.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssstyle": { + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-5.3.7.tgz", + "integrity": "sha512-7D2EPVltRrsTkhpQmksIu+LxeWAIEk6wRDMJ1qljlv+CKHJM+cJLlfhWIzNA44eAsHXSNe3+vO6DW1yCYx8SuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/css-color": "^4.1.1", + "@csstools/css-syntax-patches-for-csstree": "^1.0.21", + "css-tree": "^3.1.0", + "lru-cache": "^11.2.4" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/cssstyle/node_modules/lru-cache": { + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", + "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/data-urls": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-6.0.1.tgz", + "integrity": "sha512-euIQENZg6x8mj3fO6o9+fOW8MimUI4PpD/fZBhJfeioZVy9TUpM4UY7KjQNVZFlqwJ0UdzRDzkycB997HEq1BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-mimetype": "^5.0.0", + "whatwg-url": "^15.1.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/data-urls/node_modules/whatwg-mimetype": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz", + "integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "dev": true, + "license": "MIT" + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/defu": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.6.tgz", + "integrity": "sha512-f8mefEW4WIVg4LckePx3mALjQSPQgFlg9U8yaPdlsbdYcHQyj9n2zL2LJEA52smeYxOvmd/nB7TpMtHGMTHcug==", + "license": "MIT" + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/destr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", + "license": "MIT" + }, + "node_modules/detect-browser": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/detect-browser/-/detect-browser-5.3.0.tgz", + "integrity": "sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w==", + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/dijkstrajs": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", + "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==", + "license": "MIT" + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true, + "license": "MIT" + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.331", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.331.tgz", + "integrity": "sha512-IbxXrsTlD3hRodkLnbxAPP4OuJYdWCeM3IOdT+CpcMoIwIoDfCmRpEtSPfwBXxVkg9xmBeY7Lz2Eo2TDn/HC3Q==", + "dev": true, + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/encode-utf8": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz", + "integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==", + "license": "MIT" + }, + "node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-abstract": { + "version": "1.24.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.1.tgz", + "integrity": "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.3.1.tgz", + "integrity": "sha512-zWwRvqWiuBPr0muUG/78cW3aHROFCNIQ3zpmYDpwdbnt2m+xlNyRWpHBpa2lJjSBit7BQ+RXA1iwbSmu5yJ/EQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.1", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.1.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.3.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.5", + "math-intrinsics": "^1.1.0", + "safe-array-concat": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", + "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-toolkit": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.44.0.tgz", + "integrity": "sha512-6penXeZalaV88MM3cGkFZZfOoLGWshWWfdy0tWw/RlVVyhvMaWSBTOvXNeiW3e5FwdS5ePW0LGEu17zT139ktg==", + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks" + ] + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-next": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.2.3.tgz", + "integrity": "sha512-ZkNztm3Q7hjqvB1rRlOX8P9E/cXRL9ajRcs8jufEtwMfTVYRqnmtnaSu57QqHyBlovMuiB8LEzfLBkh5RYV6Fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@next/eslint-plugin-next": "14.2.3", + "@rushstack/eslint-patch": "^1.3.3", + "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || 7.0.0 - 7.2.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-import-resolver-typescript": "^3.5.2", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705" + }, + "peerDependencies": { + "eslint": "^7.23.0 || ^8.0.0", + "typescript": ">=3.3.1" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.10.tgz", + "integrity": "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.16.1", + "resolve": "^2.0.0-next.6" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz", + "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.4.0", + "get-tsconfig": "^4.10.0", + "is-bun-module": "^2.0.0", + "stable-hash": "^0.0.5", + "tinyglobby": "^0.2.13", + "unrs-resolver": "^1.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-import-resolver-typescript" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", + "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "aria-query": "^5.3.2", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.10.0", + "axobject-query": "^4.1.0", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.1" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "5.0.0-canary-7118f5dd7-20230705", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0-canary-7118f5dd7-20230705.tgz", + "integrity": "sha512-AZYbMo/NW9chdL7vk6HQzQhT+PvTAEVqWk9ziruUoW2kAOcN5qNyelv70e0F1VNQAbvutOC9oc+xfWycI9FxDw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/expect-type": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "dev": true, + "license": "MIT" + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true, + "license": "ISC" + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/framer-motion": { + "version": "12.38.0", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.38.0.tgz", + "integrity": "sha512-rFYkY/pigbcswl1XQSb7q424kSTQ8q6eAC+YUsSKooHQYuLdzdHjrt6uxUC+PRAO++q5IS7+TamgIw1AphxR+g==", + "license": "MIT", + "dependencies": { + "motion-dom": "^12.38.0", + "motion-utils": "^12.36.0", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/framer-motion/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.13.7", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.7.tgz", + "integrity": "sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/h3": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.11.tgz", + "integrity": "sha512-L3THSe2MPeBwgIZVSH5zLdBBU90TOxarvhK9d04IDY2AmVS8j2Jz2LIWtwsGOU3lu2I5jCN7FNvVfY2+XyF+mg==", + "license": "MIT", + "dependencies": { + "cookie-es": "^1.2.3", + "crossws": "^0.3.5", + "defu": "^6.1.6", + "destr": "^2.0.5", + "iron-webcrypto": "^1.2.1", + "node-mock-http": "^1.0.4", + "radix3": "^1.1.2", + "ufo": "^1.6.3", + "uncrypto": "^0.1.3" + } + }, + "node_modules/happy-dom": { + "version": "20.8.9", + "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-20.8.9.tgz", + "integrity": "sha512-Tz23LR9T9jOGVZm2x1EPdXqwA37G/owYMxRwU0E4miurAtFsPMQ1d2Jc2okUaSjZqAFz2oEn3FLXC5a0a+siyA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": ">=20.0.0", + "@types/whatwg-mimetype": "^3.0.2", + "@types/ws": "^8.18.1", + "entities": "^7.0.1", + "whatwg-mimetype": "^3.0.0", + "ws": "^8.18.3" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/happy-dom/node_modules/ws": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz", + "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hey-listen": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz", + "integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==", + "license": "MIT" + }, + "node_modules/html-encoding-sniffer": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz", + "integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@exodus/bytes": "^1.6.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/html-encoding-sniffer/node_modules/@exodus/bytes": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.15.0.tgz", + "integrity": "sha512-UY0nlA+feH81UGSHv92sLEPLCeZFjXOuHhrIo0HQydScuQc8s0A7kL/UdgwgDq8g8ilksmuoF35YVTNphV2aBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + }, + "peerDependencies": { + "@noble/hashes": "^1.8.0 || ^2.0.0" + }, + "peerDependenciesMeta": { + "@noble/hashes": { + "optional": true + } + } + }, + "node_modules/html-encoding-sniffer/node_modules/@noble/hashes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.0.1.tgz", + "integrity": "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/idb-keyval": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.2.tgz", + "integrity": "sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg==", + "license": "Apache-2.0" + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/iron-webcrypto": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz", + "integrity": "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/brc-dd" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bun-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", + "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.7.1" + } + }, + "node_modules/is-bun-module/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsdom": { + "version": "27.4.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-27.4.0.tgz", + "integrity": "sha512-mjzqwWRD9Y1J1KUi7W97Gja1bwOOM5Ug0EZ6UDK3xS7j7mndrkwozHtSblfomlzyB4NepioNt+B2sOSzczVgtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@acemir/cssom": "^0.9.28", + "@asamuzakjp/dom-selector": "^6.7.6", + "@exodus/bytes": "^1.6.0", + "cssstyle": "^5.3.4", + "data-urls": "^6.0.0", + "decimal.js": "^10.6.0", + "html-encoding-sniffer": "^6.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.6", + "is-potential-custom-element-name": "^1.0.1", + "parse5": "^8.0.0", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^6.0.0", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^8.0.0", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^15.1.0", + "ws": "^8.18.3", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + }, + "peerDependencies": { + "canvas": "^3.0.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/@exodus/bytes": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.15.0.tgz", + "integrity": "sha512-UY0nlA+feH81UGSHv92sLEPLCeZFjXOuHhrIo0HQydScuQc8s0A7kL/UdgwgDq8g8ilksmuoF35YVTNphV2aBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + }, + "peerDependencies": { + "@noble/hashes": "^1.8.0 || ^2.0.0" + }, + "peerDependenciesMeta": { + "@noble/hashes": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/@noble/hashes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.0.1.tgz", + "integrity": "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/jsdom/node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/jsdom/node_modules/ws": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz", + "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/keyvaluestorage-interface": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/keyvaluestorage-interface/-/keyvaluestorage-interface-1.0.0.tgz", + "integrity": "sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g==", + "license": "MIT" + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "license": "MIT", + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lit": { + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/lit/-/lit-2.7.5.tgz", + "integrity": "sha512-i/cH7Ye6nBDUASMnfwcictBnsTN91+aBjXoTHF2xARghXScKxpD4F4WYI+VLXg9lqbMinDfvoI7VnZXjyHgdfQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@lit/reactive-element": "^1.6.0", + "lit-element": "^3.3.0", + "lit-html": "^2.7.0" + } + }, + "node_modules/lit-element": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-3.3.3.tgz", + "integrity": "sha512-XbeRxmTHubXENkV4h8RIPyr8lXc+Ff28rkcQzw3G6up2xg5E8Zu1IgOWIwBLEQsu3cOVFqdYwiVi0hv0SlpqUA==", + "license": "BSD-3-Clause", + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.1.0", + "@lit/reactive-element": "^1.3.0", + "lit-html": "^2.8.0" + } + }, + "node_modules/lit-html": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.8.0.tgz", + "integrity": "sha512-o9t+MQM3P4y7M7yNzqAyjp7z+mQGa4NS4CxiyLqFPyFWyc4O+nodLrkrxSaCTrla6M5YOLaT3RpbbqjszB5g3Q==", + "license": "BSD-3-Clause", + "dependencies": { + "@types/trusted-types": "^2.0.2" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/magicast": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.2.tgz", + "integrity": "sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "source-map-js": "^1.2.1" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mdn-data": { + "version": "2.27.1", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", + "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/motion": { + "version": "10.16.2", + "resolved": "https://registry.npmjs.org/motion/-/motion-10.16.2.tgz", + "integrity": "sha512-p+PurYqfUdcJZvtnmAqu5fJgV2kR0uLFQuBKtLeFVTrYEVllI99tiOTSefVNYuip9ELTEkepIIDftNdze76NAQ==", + "license": "MIT", + "dependencies": { + "@motionone/animation": "^10.15.1", + "@motionone/dom": "^10.16.2", + "@motionone/svelte": "^10.16.2", + "@motionone/types": "^10.15.1", + "@motionone/utils": "^10.15.1", + "@motionone/vue": "^10.16.2" + } + }, + "node_modules/motion-dom": { + "version": "12.38.0", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.38.0.tgz", + "integrity": "sha512-pdkHLD8QYRp8VfiNLb8xIBJis1byQ9gPT3Jnh2jqfFtAsWUA3dEepDlsWe/xMpO8McV+VdpKVcp+E+TGJEtOoA==", + "license": "MIT", + "dependencies": { + "motion-utils": "^12.36.0" + } + }, + "node_modules/motion-utils": { + "version": "12.36.0", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.36.0.tgz", + "integrity": "sha512-eHWisygbiwVvf6PZ1vhaHCLamvkSbPIeAYxWUuL3a2PD/TROgE7FvfHWTIH4vMl798QLfMw15nRqIaRDXTlYRg==", + "license": "MIT" + }, + "node_modules/mrmime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/multiformats": { + "version": "9.9.0", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz", + "integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==", + "license": "(Apache-2.0 AND MIT)" + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/napi-postinstall": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", + "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/next": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/next/-/next-14.2.3.tgz", + "integrity": "sha512-dowFkFTR8v79NPJO4QsBUtxv0g9BrS/phluVpMAt2ku7H+cbcBJlopXjkWlwxrk/xGqMemr7JkGPGemPrLLX7A==", + "deprecated": "This version has a security vulnerability. Please upgrade to a patched version. See https://nextjs.org/blog/security-update-2025-12-11 for more details.", + "license": "MIT", + "dependencies": { + "@next/env": "14.2.3", + "@swc/helpers": "0.5.5", + "busboy": "1.6.0", + "caniuse-lite": "^1.0.30001579", + "graceful-fs": "^4.2.11", + "postcss": "8.4.31", + "styled-jsx": "5.1.1" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=18.17.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "14.2.3", + "@next/swc-darwin-x64": "14.2.3", + "@next/swc-linux-arm64-gnu": "14.2.3", + "@next/swc-linux-arm64-musl": "14.2.3", + "@next/swc-linux-x64-gnu": "14.2.3", + "@next/swc-linux-x64-musl": "14.2.3", + "@next/swc-win32-arm64-msvc": "14.2.3", + "@next/swc-win32-ia32-msvc": "14.2.3", + "@next/swc-win32-x64-msvc": "14.2.3" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.41.2", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/node-exports-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.0.tgz", + "integrity": "sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "array.prototype.flatmap": "^1.3.3", + "es-errors": "^1.3.0", + "object.entries": "^1.1.9", + "semver": "^6.3.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/node-fetch-native": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", + "license": "MIT" + }, + "node_modules/node-mock-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.4.tgz", + "integrity": "sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==", + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.37", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.37.tgz", + "integrity": "sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obug": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT" + }, + "node_modules/ofetch": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.5.1.tgz", + "integrity": "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==", + "license": "MIT", + "dependencies": { + "destr": "^2.0.5", + "node-fetch-native": "^1.6.7", + "ufo": "^1.6.1" + } + }, + "node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ox": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.9.3.tgz", + "integrity": "sha512-KzyJP+fPV4uhuuqrTZyok4DC7vFzi7HLUFiUNEmpbyh59htKWkOC98IONC1zgXJPbHAhQgqs6B0Z6StCGhmQvg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@adraffy/ens-normalize": "^1.11.0", + "@noble/ciphers": "^1.3.0", + "@noble/curves": "1.9.1", + "@noble/hashes": "^1.8.0", + "@scure/bip32": "^1.7.0", + "@scure/bip39": "^1.6.0", + "abitype": "^1.0.9", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/ox/node_modules/@noble/curves": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.1.tgz", + "integrity": "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ox/node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse5": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz", + "integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pino": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-10.0.0.tgz", + "integrity": "sha512-eI9pKwWEix40kfvSzqEP6ldqOoBIN7dwD/o91TY5z8vQI12sAffpR/pOqAD1IVVwIVHDpHjkq0joBPdJD0rafA==", + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^2.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^5.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "slow-redact": "^0.3.0", + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", + "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", + "license": "MIT", + "dependencies": { + "split2": "^4.0.0" + } + }, + "node_modules/pino-std-serializers": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.1.0.tgz", + "integrity": "sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==", + "license": "MIT" + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/playwright": { + "version": "1.59.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.59.1.tgz", + "integrity": "sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.59.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.59.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.59.1.tgz", + "integrity": "sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/pngjs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", + "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.5.8", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", + "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-import/node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/postcss-js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz", + "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/process-warning": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz", + "integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/proxy-compare": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-2.5.1.tgz", + "integrity": "sha512-oyfc0Tx87Cpwva5ZXezSp5V9vht1c7dZBhvuV/y3ctkgMVUmiAGDVeeB0dKhGSyT0v1ZTEQYpe/RXlBVBNuCLA==", + "license": "MIT" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/qrcode": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.3.tgz", + "integrity": "sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==", + "license": "MIT", + "dependencies": { + "dijkstrajs": "^1.0.1", + "encode-utf8": "^1.0.3", + "pngjs": "^5.0.0", + "yargs": "^15.3.1" + }, + "bin": { + "qrcode": "bin/qrcode" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/qrcode/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/qrcode/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/qrcode/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/qrcode/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "license": "ISC" + }, + "node_modules/qrcode/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "license": "MIT", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", + "license": "MIT" + }, + "node_modules/radix3": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.2.tgz", + "integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==", + "license": "MIT" + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/react-refresh": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", + "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "license": "MIT", + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "license": "ISC" + }, + "node_modules/resolve": { + "version": "2.0.0-next.6", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.6.tgz", + "integrity": "sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "node-exports-info": "^1.6.0", + "object-keys": "^1.1.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rolldown": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.12.tgz", + "integrity": "sha512-yP4USLIMYrwpPHEFB5JGH1uxhcslv6/hL0OyvTuY+3qlOSJvZ7ntYnoWpehBxufkgN0cvXxppuTu5hHa/zPh+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.122.0", + "@rolldown/pluginutils": "1.0.0-rc.12" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.0.0-rc.12", + "@rolldown/binding-darwin-arm64": "1.0.0-rc.12", + "@rolldown/binding-darwin-x64": "1.0.0-rc.12", + "@rolldown/binding-freebsd-x64": "1.0.0-rc.12", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.12", + "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.12", + "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.12", + "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.12", + "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.12", + "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.12", + "@rolldown/binding-linux-x64-musl": "1.0.0-rc.12", + "@rolldown/binding-openharmony-arm64": "1.0.0-rc.12", + "@rolldown/binding-wasm32-wasi": "1.0.0-rc.12", + "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.12", + "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.12" + } + }, + "node_modules/rolldown/node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.12.tgz", + "integrity": "sha512-HHMwmarRKvoFsJorqYlFeFRzXZqCt2ETQlEDOb9aqssrnVBB1/+xgTGtuTrIk5vzLNX1MjMtTf7W9z3tsSbrxw==", + "dev": true, + "license": "MIT" + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC" + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sirv": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", + "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/slow-redact": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/slow-redact/-/slow-redact-0.3.2.tgz", + "integrity": "sha512-MseHyi2+E/hBRqdOi5COy6wZ7j7DxXRz9NkseavNYSvvWC06D8a5cidVZX3tcG5eCW3NIyVU4zT63hw0Q486jw==", + "license": "MIT" + }, + "node_modules/sonic-boom": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.1.tgz", + "integrity": "sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==", + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, + "node_modules/sonner": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/sonner/-/sonner-2.0.7.tgz", + "integrity": "sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==", + "license": "MIT", + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", + "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/stable-hash": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", + "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==", + "dev": true, + "license": "MIT" + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.0.0.tgz", + "integrity": "sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/string.prototype.includes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", + "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", + "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "license": "MIT", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/sucrase": { + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", + "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "tinyglobby": "^0.2.11", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true, + "license": "MIT" + }, + "node_modules/tailwindcss": { + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz", + "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.7", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tailwindcss/node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/test-exclude": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.2.tgz", + "integrity": "sha512-u9E6A+ZDYdp7a4WnarkXPZOx8Ilz46+kby6p1yZ8zsGTz9gYa6FIS7lj2oezzNKmtdyyJNNmmXDppga5GB7kSw==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^10.4.1", + "minimatch": "^10.2.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/test-exclude/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/test-exclude/node_modules/glob/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/test-exclude/node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/test-exclude/node_modules/glob/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/test-exclude/node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/thread-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", + "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", + "license": "MIT", + "dependencies": { + "real-require": "^0.2.0" + } + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.4.tgz", + "integrity": "sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/tinyrainbow": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz", + "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tldts": { + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.27.tgz", + "integrity": "sha512-I4FZcVFcqCRuT0ph6dCDpPuO4Xgzvh+spkcTr1gK7peIvxWauoloVO0vuy1FQnijT63ss6AsHB6+OIM4aXHbPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tldts-core": "^7.0.27" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.27.tgz", + "integrity": "sha512-YQ7uPjgWUibIK6DW5lrKujGwUKhLevU4hcGbP5O6TcIUb+oTjJYJVWPS4nZsIHrEEEG6myk/oqAJUEQmpZrHsg==", + "dev": true, + "license": "MIT" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/tough-cookie": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.1.tgz", + "integrity": "sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^7.0.5" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tr46": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz", + "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/ts-api-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", + "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/ufo": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.3.tgz", + "integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==", + "license": "MIT" + }, + "node_modules/uint8arrays": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.1.1.tgz", + "integrity": "sha512-+QJa8QRnbdXVpHYjLoTpJIdCTiw9Ir62nocClWuXIq2JIh4Uta0cQsTSpFL678p2CN8B+XSApwcU+pQEqVpKWg==", + "license": "MIT", + "dependencies": { + "multiformats": "^9.4.2" + } + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/uncrypto": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz", + "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==", + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/unrs-resolver": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", + "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.0" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.11.1", + "@unrs/resolver-binding-android-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-x64": "1.11.1", + "@unrs/resolver-binding-freebsd-x64": "1.11.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-musl": "1.11.1", + "@unrs/resolver-binding-wasm32-wasi": "1.11.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", + "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", + "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/valtio": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/valtio/-/valtio-1.10.5.tgz", + "integrity": "sha512-jTp0k63VXf4r5hPoaC6a6LCG4POkVSh629WLi1+d5PlajLsbynTMd7qAgEiOSPxzoX5iNvbN7iZ/k/g29wrNiQ==", + "license": "MIT", + "dependencies": { + "proxy-compare": "2.5.1", + "use-sync-external-store": "1.2.0" + }, + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + } + } + }, + "node_modules/vite": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.3.tgz", + "integrity": "sha512-B9ifbFudT1TFhfltfaIPgjo9Z3mDynBTJSUYxTjOQruf/zHH+ezCQKcoqO+h7a9Pw9Nm/OtlXAiGT1axBgwqrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "lightningcss": "^1.32.0", + "picomatch": "^4.0.4", + "postcss": "^8.5.8", + "rolldown": "1.0.0-rc.12", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.1.0", + "esbuild": "^0.27.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vitest": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.2.tgz", + "integrity": "sha512-xjR1dMTVHlFLh98JE3i/f/WePqJsah4A0FK9cc8Ehp9Udk0AZk6ccpIZhh1qJ/yxVWRZ+Q54ocnD8TXmkhspGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "4.1.2", + "@vitest/mocker": "4.1.2", + "@vitest/pretty-format": "4.1.2", + "@vitest/runner": "4.1.2", + "@vitest/snapshot": "4.1.2", + "@vitest/spy": "4.1.2", + "@vitest/utils": "4.1.2", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.2", + "@vitest/browser-preview": "4.1.2", + "@vitest/browser-webdriverio": "4.1.2", + "@vitest/ui": "4.1.2", + "happy-dom": "*", + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "vite": { + "optional": false + } + } + }, + "node_modules/vitest/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/webidl-conversions": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz", + "integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=20" + } + }, + "node_modules/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-15.1.0.tgz", + "integrity": "sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "^6.0.0", + "webidl-conversions": "^8.0.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "license": "ISC" + }, + "node_modules/which-typed-array": { + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", + "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true, + "license": "MIT" + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/dapp/package.json b/dapp/package.json new file mode 100644 index 0000000..8eca91f --- /dev/null +++ b/dapp/package.json @@ -0,0 +1,62 @@ +{ + "name": "dapp", + "version": "0.1.0", + "description": "A decentralized application built on Hathor Network", + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint", + "test": "vitest", + "test:ui": "vitest --ui", + "test:run": "vitest run", + "test:coverage": "vitest run --coverage", + "test:e2e": "playwright test", + "test:e2e:ui": "playwright test --ui" + }, + "dependencies": { + "@walletconnect/sign-client": "^2.23.0", + "@walletconnect/utils": "^2.23.0", + "@web3modal/standalone": "^2.4.3", + "framer-motion": "^12.23.24", + "next": "14.2.3", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "sonner": "^2.0.7" + }, + "devDependencies": { + "@playwright/test": "^1.56.1", + "@testing-library/jest-dom": "^6.9.1", + "@testing-library/react": "^16.3.0", + "@testing-library/user-event": "^14.6.1", + "@types/node": "^20", + "@types/react": "^18", + "@types/react-dom": "^18", + "@vitejs/plugin-react": "^5.1.1", + "@vitest/coverage-v8": "^4.0.12", + "@vitest/ui": "^4.0.12", + "autoprefixer": "^10.4.19", + "c8": "^10.1.3", + "eslint": "^8", + "eslint-config-next": "14.2.3", + "happy-dom": "^20.0.10", + "jsdom": "^27.2.0", + "postcss": "^8.4.38", + "tailwindcss": "^3.4.3", + "typescript": "^5", + "vitest": "^4.0.12" + }, + "keywords": [ + "hathor", + "hathor-network", + "dapp", + "decentralized", + "nano-contracts", + "blockchain", + "web3", + "metamask-snaps", + "walletconnect" + ], + "author": "", + "license": "MIT" +} diff --git a/dapp/playwright.config.ts b/dapp/playwright.config.ts new file mode 100644 index 0000000..c348ce7 --- /dev/null +++ b/dapp/playwright.config.ts @@ -0,0 +1,43 @@ +import { defineConfig, devices } from '@playwright/test' + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './e2e', + fullyParallel: true, + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 2 : 0, + workers: process.env.CI ? 1 : undefined, + reporter: 'html', + use: { + baseURL: 'http://localhost:3000', + trace: 'on-first-retry', + screenshot: 'only-on-failure', + }, + + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + { + name: 'webkit', + use: { ...devices['Desktop Safari'] }, + }, + ], + + webServer: { + command: 'npm run dev', + url: 'http://localhost:3000', + reuseExistingServer: !process.env.CI, + env: { + NEXT_PUBLIC_USE_MOCK_WALLET: 'true', + NEXT_PUBLIC_DEFAULT_NETWORK: 'testnet', + }, + }, +}) diff --git a/dapp/postcss.config.js b/dapp/postcss.config.js new file mode 100644 index 0000000..33ad091 --- /dev/null +++ b/dapp/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/dapp/public/.gitkeep b/dapp/public/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/dapp/public/favicon.png b/dapp/public/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..815bd32c340fc8860cd706e4ad5bbf0863019c75 GIT binary patch literal 807680 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 z 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
=1udqYK%1m5JAuourc|q*n9PV@9?$*O- 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%0DXqYGiwENS3t>p7|e505wX@ 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 )Cs5el5k^{#Z->>Yp2@O%f+HP*fvgw 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

D>_v6*;cznNLt69X|! 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

An{D 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

fabobo+ZhsNemupOUyvL`tR6Si9_$ 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

^ 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 literal 0 HcmV?d00001 diff --git a/dapp/scripts/deploy.sh b/dapp/scripts/deploy.sh new file mode 100755 index 0000000..9be52b8 --- /dev/null +++ b/dapp/scripts/deploy.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +# Deployment script for Hathor dApp +# Usage: ./scripts/deploy.sh [aws_profile] +# +# Sites: staging, production +# Commands: build, sync, clear_cache + +if [ -z "$1" ] || [ -z "$2" ]; then + echo "Usage: $0 [aws_profile]" + echo "" + echo "Sites: staging, production" + echo "Commands: build, sync, clear_cache" + echo "" + echo "Example: $0 staging build" + echo "Example: $0 production sync my-aws-profile" + exit 1 +fi + +site=$1 +command=$2 +aws_profile=$3 + +# Define environment variables for each site +# NOTE: Update these values for your deployment +case $site in + staging) + NEXT_PUBLIC_DEFAULT_NETWORK=testnet + NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET=https://node1.india.testnet.hathor.network/v1a + NEXT_PUBLIC_HATHOR_NODE_URL_MAINNET=https://node1.mainnet.hathor.network/v1a + NEXT_PUBLIC_CONTRACT_IDS_TESTNET='["your_staging_contract_id"]' + NEXT_PUBLIC_CONTRACT_IDS_MAINNET='[]' + NEXT_PUBLIC_USE_MOCK_WALLET=false + NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=your_walletconnect_project_id + S3_BUCKET=your-staging-bucket + CLOUDFRONT_ID=your_staging_cloudfront_id + ;; + production) + NEXT_PUBLIC_DEFAULT_NETWORK=mainnet + NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET=https://node1.india.testnet.hathor.network/v1a + NEXT_PUBLIC_HATHOR_NODE_URL_MAINNET=https://node1.mainnet.hathor.network/v1a + NEXT_PUBLIC_CONTRACT_IDS_TESTNET='[]' + NEXT_PUBLIC_CONTRACT_IDS_MAINNET='["your_production_contract_id"]' + NEXT_PUBLIC_USE_MOCK_WALLET=false + NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=your_walletconnect_project_id + S3_BUCKET=your-production-bucket + CLOUDFRONT_ID=your_production_cloudfront_id + ;; + *) + echo "Unknown site: $site" + echo "Valid sites: staging, production" + exit 1 + ;; +esac + +export NEXT_PUBLIC_DEFAULT_NETWORK +export NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET +export NEXT_PUBLIC_HATHOR_NODE_URL_MAINNET +export NEXT_PUBLIC_CONTRACT_IDS_TESTNET +export NEXT_PUBLIC_CONTRACT_IDS_MAINNET +export NEXT_PUBLIC_USE_MOCK_WALLET +export NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID +export S3_BUCKET +export CLOUDFRONT_ID + +case $command in + build) + echo "Building for site: $site" + echo "NEXT_PUBLIC_DEFAULT_NETWORK: $NEXT_PUBLIC_DEFAULT_NETWORK" + echo "NEXT_PUBLIC_USE_MOCK_WALLET: $NEXT_PUBLIC_USE_MOCK_WALLET" + # Use production config for static export + cp next.config.js next.config.js.bak + cp next.config.production.js next.config.js + # Run the build command + npm run build + # Restore original config + mv next.config.js.bak next.config.js + ;; + sync) + echo "Syncing for site: $site" + if [ -n "$aws_profile" ]; then + aws s3 sync --delete ./out/ s3://$S3_BUCKET --profile $aws_profile + else + aws s3 sync --delete ./out/ s3://$S3_BUCKET + fi + ;; + clear_cache) + echo "Clearing CloudFront cache for site: $site" + if [ -z "$CLOUDFRONT_ID" ]; then + echo "Warning: CLOUDFRONT_ID not set, skipping cache invalidation" + exit 0 + fi + if [ -n "$aws_profile" ]; then + aws cloudfront create-invalidation --distribution-id $CLOUDFRONT_ID --paths "/*" --profile $aws_profile + else + aws cloudfront create-invalidation --distribution-id $CLOUDFRONT_ID --paths "/*" + fi + ;; + *) + echo "Unknown command: $command" + echo "Valid commands: build, sync, clear_cache" + exit 1 + ;; +esac diff --git a/dapp/tailwind.config.js b/dapp/tailwind.config.js new file mode 100644 index 0000000..792d48e --- /dev/null +++ b/dapp/tailwind.config.js @@ -0,0 +1,24 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + './pages/**/*.{js,ts,jsx,tsx,mdx}', + './components/**/*.{js,ts,jsx,tsx,mdx}', + './app/**/*.{js,ts,jsx,tsx,mdx}', + ], + theme: { + extend: { + colors: { + background: '#0f172a', + foreground: '#f1f5f9', + // Hathor brand colors + 'hathor-orange': '#FF7300', + 'hathor-orange-light': '#FFA600', + 'hathor-green': '#059669', + }, + backgroundImage: { + 'hathor-gradient': 'linear-gradient(244deg, rgb(255, 166, 0) 0%, rgb(255, 115, 0) 100%)', + }, + }, + }, + plugins: [], +} diff --git a/dapp/tsconfig.json b/dapp/tsconfig.json new file mode 100644 index 0000000..2c145a2 --- /dev/null +++ b/dapp/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "target": "ES2020", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./*"] + } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +} diff --git a/dapp/types/hathor.ts b/dapp/types/hathor.ts new file mode 100644 index 0000000..df159f9 --- /dev/null +++ b/dapp/types/hathor.ts @@ -0,0 +1,91 @@ +export interface ContractState { + token_uid: string; + available_tokens: bigint; + total_liquidity_provided: bigint; + [key: string]: any; +} + +export interface EscrowState { + ncId: string; + buyer: string; + seller: string; + facilitator: string; + token_uid: string; + amount: number; + phase: 'LOCKED' | 'RELEASED' | 'REFUNDED'; + deadline: number; + resource_url: string; + request_hash: string; +} + +export interface BlueprintInfo { + id: string; + name: string; + public_methods: string[]; + attributes: Record; +} + +export interface ContractHistory { + transactions: ContractTransaction[]; + total: number; + hasMore: boolean; +} + +export interface NanoContractEvent { + data: string; +} + +export interface ContractTransaction { + tx_id: string; + timestamp: number; + nc_method: string; + nc_caller: string; + first_block: string | null; + is_voided: boolean; + nc_args_decoded?: number[]; + nc_events?: NanoContractEvent[]; + contractId?: string; +} + +export interface HathorRPCRequest { + method: string; + params?: any; +} + +export interface HathorRPCResponse { + result?: T; + error?: { + code: number; + message: string; + }; +} + +export interface GetBalanceParams { + network: string; + tokens: string[]; + addressIndexes?: number[]; +} + +export interface GetAddressParams { + network: string; + type: 'first_empty' | 'full_path' | 'index' | 'client'; + full_path?: string; + index?: number; +} + +export interface SendNanoContractTxParams { + method: string; + blueprint_id?: string; + nc_id?: string; + actions: NanoContractAction[]; + args: any[]; + push_tx: boolean; +} + +export interface NanoContractAction { + type: 'deposit' | 'withdrawal'; + amount: string; + token: string; + address?: string; + changeAddress?: string; +} diff --git a/dapp/types/index.ts b/dapp/types/index.ts new file mode 100644 index 0000000..55b31c7 --- /dev/null +++ b/dapp/types/index.ts @@ -0,0 +1,6 @@ +export interface WalletState { + connected: boolean; + address: string | null; + walletBalance: number; + contractBalance: bigint; +} diff --git a/dapp/types/metamask.d.ts b/dapp/types/metamask.d.ts new file mode 100644 index 0000000..fa5fcbf --- /dev/null +++ b/dapp/types/metamask.d.ts @@ -0,0 +1,15 @@ +export {}; + +declare global { + interface Window { + ethereum?: { + isMetaMask?: boolean; + request: (args: { + method: string; + params?: any; + }) => Promise; + on?: (eventName: string, handler: (...args: any[]) => void) => void; + removeListener?: (eventName: string, handler: (...args: any[]) => void) => void; + }; + } +} diff --git a/dapp/types/wallet.ts b/dapp/types/wallet.ts new file mode 100644 index 0000000..c7e6eb0 --- /dev/null +++ b/dapp/types/wallet.ts @@ -0,0 +1,21 @@ +/** + * Wallet Adapter Interface + * This interface defines the contract that all wallet implementations must follow. + * It allows WalletContext to work with any wallet type without knowing the specifics. + */ + +export interface WalletAdapter { + // Connection state + isConnected: boolean; + isInitializing?: boolean; + address: string | null; + + // Connection methods + connect: () => Promise; + disconnect: () => Promise; + + // RPC request method - all wallet operations go through this + request: (method: string, params?: any) => Promise; +} + +export type WalletType = 'walletconnect' | 'metamask' | null; diff --git a/dapp/vitest.config.ts b/dapp/vitest.config.ts new file mode 100644 index 0000000..b4900d8 --- /dev/null +++ b/dapp/vitest.config.ts @@ -0,0 +1,44 @@ +import { defineConfig } from 'vitest/config' +import react from '@vitejs/plugin-react' +import path from 'path' + +export default defineConfig({ + plugins: [react()], + test: { + globals: true, + environment: 'jsdom', + setupFiles: ['./vitest.setup.ts'], + include: ['**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], + exclude: ['node_modules', 'dist', '.next', 'e2e'], + coverage: { + provider: 'v8', + reporter: ['text', 'json', 'html', 'lcov'], + exclude: [ + 'node_modules/', + 'vitest.setup.ts', + '**/*.d.ts', + '**/*.config.*', + '**/dist/', + '**/.next/', + 'e2e/', + '__mocks__/', + 'types/', + ], + thresholds: { + lines: 80, + functions: 80, + branches: 70, + statements: 80, + }, + }, + }, + resolve: { + alias: { + '@': path.resolve(__dirname, './'), + '@/components': path.resolve(__dirname, './components'), + '@/lib': path.resolve(__dirname, './lib'), + '@/contexts': path.resolve(__dirname, './contexts'), + '@/types': path.resolve(__dirname, './types'), + }, + }, +}) diff --git a/dapp/vitest.setup.ts b/dapp/vitest.setup.ts new file mode 100644 index 0000000..e6ba438 --- /dev/null +++ b/dapp/vitest.setup.ts @@ -0,0 +1,81 @@ +import '@testing-library/jest-dom' +import { cleanup } from '@testing-library/react' +import { afterEach, vi } from 'vitest' + +// Cleanup after each test +afterEach(() => { + cleanup() +}) + +// Mock Next.js router +vi.mock('next/navigation', () => ({ + useRouter: () => ({ + push: vi.fn(), + replace: vi.fn(), + prefetch: vi.fn(), + back: vi.fn(), + pathname: '/', + query: {}, + asPath: '/', + }), + usePathname: () => '/', + useSearchParams: () => new URLSearchParams(), +})) + +// Mock environment variables +process.env.NEXT_PUBLIC_DEFAULT_NETWORK = 'testnet' +process.env.NEXT_PUBLIC_USE_MOCK_WALLET = 'false' +process.env.NEXT_PUBLIC_TESTNET_NODE_URL = 'https://node1.india-testnet.hathor.network/v1a' +process.env.NEXT_PUBLIC_MAINNET_NODE_URL = 'https://node1.mainnet.hathor.network/v1a' +process.env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID = 'test-project-id' + +// Mock window.matchMedia +Object.defineProperty(window, 'matchMedia', { + writable: true, + value: vi.fn().mockImplementation(query => ({ + matches: false, + media: query, + onchange: null, + addListener: vi.fn(), + removeListener: vi.fn(), + addEventListener: vi.fn(), + removeEventListener: vi.fn(), + dispatchEvent: vi.fn(), + })), +}) + +// Mock localStorage +const localStorageMock = (() => { + let store: Record = {} + + return { + getItem: (key: string) => store[key] || null, + setItem: (key: string, value: string) => { + store[key] = value.toString() + }, + removeItem: (key: string) => { + delete store[key] + }, + clear: () => { + store = {} + }, + } +})() + +Object.defineProperty(window, 'localStorage', { + value: localStorageMock, +}) + +// Mock IntersectionObserver +global.IntersectionObserver = class IntersectionObserver { + root = null + rootMargin = '' + thresholds = [] + constructor() {} + disconnect() {} + observe() {} + takeRecords() { + return [] + } + unobserve() {} +} as any diff --git a/resource-server.js b/resource-server.js index f5ded93..f36039e 100644 --- a/resource-server.js +++ b/resource-server.js @@ -11,6 +11,15 @@ const { log } = require('./helpers'); const app = express(); app.use(express.json()); +// CORS — allow browser dApps to call this server +app.use((req, res, next) => { + res.header('Access-Control-Allow-Origin', '*'); + res.header('Access-Control-Allow-Headers', 'Content-Type, X-Payment'); + res.header('Access-Control-Expose-Headers', 'X-Payment-Response'); + if (req.method === 'OPTIONS') return res.sendStatus(204); + next(); +}); + // Build the list of accepted payment options function buildAcceptsList(path) { const base = { From 085ea0b3d945d2485c7d6c8104e777c2c5ead6ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Thu, 2 Apr 2026 12:29:39 -0300 Subject: [PATCH 04/37] docs: rewrite README with detailed escrow model explanation Explains how Hathor's x402 implementation works: one nano contract instance per payment, instantiated from the X402Escrow blueprint. Covers the escrow lifecycle, why not pre-signed transactions, the full payment flow with timing, multi-token support, and the dApp. Links to all three RFCs. Co-Authored-By: Claude Opus 4.6 (1M context) --- README.md | 396 +++++++++++++++++++++++------------------------------- 1 file changed, 170 insertions(+), 226 deletions(-) diff --git a/README.md b/README.md index b5cd1bd..170b8af 100644 --- a/README.md +++ b/README.md @@ -2,127 +2,181 @@ > Machines paying machines. HTTP 402 meets nano contract escrow. -This is a proof-of-concept implementation of the [x402 protocol](https://www.x402.org/) on [Hathor Network](https://hathor.network/). It enables pay-per-request HTTP APIs settled natively on Hathor's DAG-based L1 blockchain using **nano contract escrow** — no pre-signed transactions, no double-spend risk, no trust required. +This is a proof-of-concept implementation of the [x402 protocol](https://www.x402.org/) on [Hathor Network](https://hathor.network/). It enables pay-per-request HTTP APIs settled natively on Hathor's DAG-based L1 blockchain using **nano contract escrow**. -## How It Works +## What is x402? + +[x402](https://www.x402.org/) is an open protocol that repurposes the HTTP `402 Payment Required` status code for machine-to-machine payments. When a client requests a paid resource, the server returns a `402` with payment instructions. The client pays, retries the request with proof of payment, and gets the resource. No API keys, no billing accounts, no human interaction. + +The client is always code — an AI agent, a script, a backend service. Never a human clicking buttons. + +## How Hathor does it: one escrow per request + +On EVM chains (Base, Polygon), x402 payments use signed messages — the client signs an authorization off-chain, and the facilitator submits it on-chain in one step. Simple, but it relies on nonces and trust. + +**Hathor takes a different approach: on-chain escrow.** + +Every x402 payment creates a **new nano contract instance** from the [X402Escrow blueprint](blueprint/x402_escrow.py). Here's what that means concretely: + +1. The `X402Escrow` blueprint is published on-chain once (like a class definition) +2. Each payment **instantiates** a new contract from that blueprint (like creating an object) +3. The client deposits funds into this new contract — they're locked on-chain +4. The facilitator verifies the lock, the server delivers the resource +5. The facilitator calls `release()` on the contract — funds go to the seller + +So if an AI agent makes 10 API calls, there are **10 separate escrow contracts** on the Hathor DAG. Each one: + +- Has its own contract ID (`ncId`) which doubles as the payment receipt +- Holds its own funds, independently locked +- Has its own deadline (auto-refund if the facilitator disappears) +- Can be verified by anyone — just query the contract state on any full node +- Cannot be double-spent — the funds are locked in the contract, not in a UTXO + +``` + Blueprint (published once) Instances (one per payment) +┌──────────────────────────┐ +│ X402Escrow │ ┌─────────────┐ +│ │───────▶│ Payment #1 │ LOCKED → RELEASED +│ initialize() │ │ 1.00 HTR │ +│ release() │ └─────────────┘ +│ refund() │ ┌─────────────┐ +│ │───────▶│ Payment #2 │ LOCKED → RELEASED +│ │ │ 1.00 HTR │ +└──────────────────────────┘ └─────────────┘ + ┌─────────────┐ + ────▶│ Payment #3 │ LOCKED → REFUNDED + │ 5.00 hUSDC │ (buyer cancelled) + └─────────────┘ +``` + +### Why not pre-signed transactions? + +The naive approach for UTXO chains is pre-signed transactions: the client signs a tx offline and hands it to the facilitator. But the client can **double-spend those UTXOs** before the facilitator broadcasts. On EVM this is solved by nonces; Hathor doesn't have nonces. Nano contract escrow solves it completely — funds are locked on-chain the moment the client deposits. + +| | Pre-Signed TX | Nano Contract Escrow | +| ------------------ | --------------------------------------- | ------------------------------------------- | +| Double-spend risk | **High** — client can spend UTXOs | **Zero** — funds locked on-chain | +| Verification | Off-chain signature check | **On-chain state query** — trustless | +| Refund on timeout | Impossible without timelock hacks | **Built-in** — contract refunds | +| Trust model | Must trust facilitator won't hold tx | **Trustless** — contract enforces rules | + +## The escrow lifecycle + +Each escrow contract goes through exactly one of two paths: + +``` + ┌─────────────────────────────┐ + │ LOCKED │ + initialize() │ │ + + deposit ───────▶│ Funds held in contract. │ + │ Buyer, seller, facilitator, │ + │ amount, deadline recorded. │ + │ │ + └──────────┬──────────┬───────┘ + │ │ + release() │ │ refund() + by facilitator│ │ by buyer (anytime) + after server │ │ by facilitator (anytime) + delivers │ │ by anyone (after deadline) + resource │ │ + ▼ ▼ + ┌──────────────┐ ┌──────────────┐ + │ RELEASED │ │ REFUNDED │ + │ │ │ │ + │ Funds sent │ │ Funds sent │ + │ to seller │ │ back to buyer│ + └──────────────┘ └──────────────┘ +``` + +**Three roles, clear permissions:** +- **Buyer**: deposits funds (initialize), can cancel anytime (refund) +- **Facilitator**: releases funds to seller after verification, can refund if service failed +- **Anyone**: can trigger refund after the deadline — dead man's switch so funds are never locked forever + +## Full payment flow ``` - x402 Payment Flow - CLIENT (AI agent) RESOURCE SERVER FACILITATOR HATHOR ───────────────── ─────────────── ─────────── ────── │ │ │ │ 1. │── GET /weather ──────────▶ │ │ │ │ │ │ │ 2. │◀── 402 Payment Required ── │ │ │ - │ {scheme, amount, │ │ │ - │ seller, facilitator, │ │ │ + │ {amount: "100", │ │ │ + │ asset: "00", │ │ │ + │ payTo, facilitator, │ │ │ │ blueprintId} │ │ │ │ │ │ │ - 3. │── create escrow ──────────────────────────────────────────────────────────▶ │ - │ (deposit 1 HTR) │ │ LOCKED │ - │◀── ncId ──────────────────────────────────────────────────────────────────── │ + 3. │── create new X402Escrow ─────────────────────────────────────────────────▶ │ + │ contract instance │ │ │ + │ (initialize + deposit │ │ LOCKED │ + │ 1.00 HTR) │ │ │ + │◀── ncId (= tx hash) ──────────────────────────────────────────────────────── │ │ │ │ │ 4. │── GET /weather ──────────▶ │ │ │ │ + X-Payment {ncId} │ │ │ │ │── POST /x402/verify ────▶ │ │ - │ │ │── query state ─────▶│ - │ │ │◀── {LOCKED, 100} ── │ + │ │ {ncId, amount, payTo} │── query nc state ─▶ │ + │ │ │◀─ {LOCKED, 100} ── │ │ │◀── {valid: true} ──────── │ │ │ │ │ │ 5. │◀── 200 + weather data ──── │ │ │ │ │ │ │ 6. │ │── POST /x402/settle ────▶ │ │ - │ │ │── release() ───────▶│ + │ │ {ncId} │── release() ───────▶│ │ │ │ (withdraw to seller)│ │ │ │◀── txId ─────────── │ - │ │◀── {success, txId} ────── │ RELEASED│ + │ │◀── {success, txId} ────── │ RELEASED │ │ │ │ │ ``` -### The Three Components - -**1. Facilitator** (`facilitator.js` — port 8402) +**Timing:** ~10s for escrow deposit confirmation, ~100ms for verification, instant HTTP response, ~10s for settlement confirmation. The client waits ~10s before getting the resource; settlement happens async after the resource is served. -The trusted intermediary that verifies payments and triggers settlement. It exposes two endpoints: +## This POC includes -- `POST /x402/verify` — Queries the nano contract state on the Hathor full node. Checks that the escrow is `LOCKED`, the amount is sufficient, the seller address matches, the facilitator address matches, and the `token_uid` matches the requested `asset`. Returns `{valid: true}` or `{valid: false, invalidReason: "..."}`. -- `POST /x402/settle` — Calls `release()` on the escrow contract, which withdraws the escrowed funds to the seller's address. Returns the settlement transaction ID. +### Backend (Node.js) -The facilitator needs its own funded wallet to sign `release()` transactions. +| Component | File | Port | What it does | +|-----------|------|------|-------------| +| **Facilitator** | `facilitator.js` | 8402 | Verifies escrow state (`/x402/verify`) and triggers settlement (`/x402/settle`) | +| **Resource Server** | `resource-server.js` | 3000 | Example paid weather API with x402 middleware. Accepts HTR and custom tokens | +| **Client** | `client.js` | — | Programmatic x402 client. Fetches → gets 402 → creates escrow → retries → gets data | +| **Blueprint** | `blueprint/x402_escrow.py` | — | The X402Escrow nano contract source (Python 3.11) | -**2. Resource Server** (`resource-server.js` — port 3000) +### Frontend (Next.js dApp) -Any HTTP server that sells access to a resource. This POC sells weather data and accepts **multiple tokens** — HTR and an optional custom token (e.g. hUSDC). The x402 middleware: +The `dapp/` directory contains a browser-based x402 payment client built with [create-hathor-dapp](https://github.com/HathorNetwork/create-hathor-dapp): -1. If no `X-Payment` header → returns **402** with payment requirements (scheme, amount, seller, facilitator, blueprint ID) -2. If `X-Payment` present → calls the facilitator to **verify** the escrow -3. If valid → serves the resource, then asks the facilitator to **settle** (async) +1. Connect your Hathor wallet (WalletConnect / Reown) +2. Enter any x402-enabled URL +3. See the 402 payment requirements (amount, token options, seller) +4. Click "Pay & Access" — your wallet signs the escrow deposit +5. Wait for on-chain confirmation (~10s) +6. Resource data displayed -**3. Client** (`client.js`) +The dApp replaces `client.js` for interactive use — instead of the agent calling wallet-headless programmatically, the user approves the escrow deposit through their wallet app. -An AI agent / script that wants to access a paid resource. The flow: +## Multi-token support -1. Makes a regular HTTP request → gets **402 Payment Required** with one or more payment options -2. **Picks a payment option** from the `accepts` array (by token preference) -3. Creates an **X402Escrow nano contract** on Hathor — deposits the required amount in the chosen token -4. Retries the request with the `X-Payment` header containing the `ncId` -5. Receives the resource +The resource server can accept multiple tokens per route. The 402 response lists all options in the `accepts` array: -Supports `--token htr` or `--token custom` to choose which token to pay with. - -## The X402Escrow Blueprint - -The heart of the system is a [Hathor nano contract](https://hathor.network/resources/nano-contracts/) deployed on-chain. It implements a simple three-phase escrow: - -``` - ┌─────────────────────┐ - │ │ - initialize() │ LOCKED │ - + deposit ───────▶│ │ - │ funds held in │ - │ contract on-chain │ - │ │ - └──────┬────────┬─────┘ - │ │ - release() │ │ refund() - by facilitator│ │ by buyer/facilitator - withdraw to │ │ or anyone after deadline - seller │ │ withdraw to buyer - ▼ ▼ - ┌──────────┐ ┌──────────┐ - │ RELEASED │ │ REFUNDED │ - └──────────┘ └──────────┘ +```json +{ + "accepts": [ + { "asset": "00", "amount": "100", "description": "Pay 1.00 HTR" }, + { "asset": "000003e3...", "amount": "1000", "description": "Or pay 10.00 hUSDC" } + ] +} ``` -**Key properties:** -- **Zero double-spend risk** — funds are locked on-chain, not in a pre-signed transaction -- **Built-in refunds** — buyer can cancel anytime; anyone can refund after the deadline (dead man's switch) -- **Trustless verification** — anyone can query the contract state on a public full node -- **One escrow per payment** — clean isolation, each `ncId` is a receipt -- **Token-agnostic** — works with HTR or any custom Hathor token (stablecoins, etc.) - -The blueprint source is in [`blueprint/x402_escrow.py`](blueprint/x402_escrow.py). - -## Why Nano Contracts (Not Pre-Signed Transactions) - -The naive approach for UTXO chains is pre-signed transactions — the client signs a transaction offline and hands it to the facilitator. But this has a fundamental flaw: **the client can double-spend the UTXOs before the facilitator submits**. - -| | Pre-Signed TX | Nano Contract Escrow | -| ------------------ | --------------------------------------- | ------------------------------------------- | -| Double-spend risk | **High** — client can spend UTXOs | **Zero** — funds locked on-chain | -| Verification | Off-chain signature check | **On-chain state query** — trustless | -| Refund on timeout | Impossible without timelock hacks | **Built-in** — contract refunds | -| Trust model | Must trust facilitator won't hold tx | **Trustless** — contract enforces rules | - -## Quick Start with Hathor Forge +The client picks whichever token it holds. The escrow blueprint is token-agnostic — it works with any Hathor token. -The fastest way to run this POC is with [Hathor Forge](https://github.com/HathorNetwork/hathor-forge), which spins up a local Hathor blockchain with all services. +## Quick Start ### Prerequisites - Node.js 18+ -- [Hathor Forge](https://github.com/HathorNetwork/hathor-forge) installed +- [Hathor Forge](https://github.com/HathorNetwork/hathor-forge) (local blockchain) ### 1. Start Hathor Forge @@ -130,201 +184,91 @@ The fastest way to run this POC is with [Hathor Forge](https://github.com/Hathor hathor-forge-cli --start ``` -This starts a local full node, miner, tx-mining service, and wallet-headless. - ### 2. Create and fund wallets -Using the Hathor Forge MCP tools or CLI: - ```bash -# Create wallets hathor-forge create-wallet buyer hathor-forge create-wallet facilitator hathor-forge create-wallet seller - -# Fund the buyer (needs HTR to pay for resources) hathor-forge fund-wallet buyer --amount 100 - -# Fund the facilitator (needs HTR for tx fees on release/refund) hathor-forge fund-wallet facilitator --amount 10 ``` -### 3. Publish the X402Escrow blueprint +### 3. Publish the blueprint ```bash hathor-forge publish-blueprint facilitator --code blueprint/x402_escrow.py +# Note the returned blueprint_id ``` -Note the returned `blueprint_id`. - -### 4. Configure +### 4. Configure and run ```bash cp .env.example .env -# Edit .env with your values: -# FULLNODE_URL, WALLET_HEADLESS_URL (from hathor-forge) -# BLUEPRINT_ID (from step 3) -# BUYER_ADDRESS, FACILITATOR_ADDRESS, SELLER_ADDRESS (from wallet creation) -``` +# Edit .env with your wallet addresses and blueprint_id -### 5. Install and run - -```bash npm install -# Terminal 1: Start the facilitator +# Terminal 1: Facilitator node facilitator.js -# Terminal 2: Start the resource server +# Terminal 2: Resource server node resource-server.js -# Terminal 3: Run the client (defaults to HTR) +# Terminal 3: Client node client.js - -# Or pay with a custom token (e.g. hUSDC) -node client.js --token custom ``` -### Expected output - -``` -[CLIENT] === x402 Payment Flow Demo === -[CLIENT] Step 1: Requesting weather data... -[CLIENT] Got 402 Payment Required -[CLIENT] Amount: 100 cents (1 HTR) -[CLIENT] Pay to: WZe3ty22NNua6N6BWRPXFqfmcTJyr2zrdq -[CLIENT] -[CLIENT] Step 2: Creating escrow nano contract... -[CLIENT] Escrow created! ncId=00000832e422... -[CLIENT] Escrow tx confirmed on-chain -[CLIENT] -[CLIENT] Step 3: Retrying request with payment proof... -[CLIENT] -[CLIENT] === Resource Received! === -[CLIENT] { - "location": "Sao Paulo, Brazil", - "temperature": 28, - "humidity": 65, - "condition": "Partly cloudy" -} -[CLIENT] -[CLIENT] === x402 Payment Flow Complete === -``` - -On the facilitator side: - -``` -[FACILITATOR] Verify request for ncId=00000832e422... -[FACILITATOR] Verification PASSED -[FACILITATOR] Settle request for ncId=00000832e422... -[FACILITATOR] Calling release() — withdrawing 100 to seller WZe3ty22... -[FACILITATOR] Settlement SUCCESS — txId=0000286c14be... -``` - -## Docker +### 5. Or use the dApp ```bash -# Build -docker build -t x402-poc . - -# Run facilitator -docker run -p 8402:8402 --env-file .env x402-poc - -# Run resource server -docker run -p 3000:3000 --env-file .env x402-poc node resource-server.js - -# Run client -docker run --env-file .env x402-poc node client.js -``` - -## Protocol Messages - -### 402 Response (Server -> Client) - -The `accepts` array can contain **multiple payment options** with different tokens. The client picks whichever it can pay with: - -```json -{ - "accepts": [ - { - "scheme": "hathor-escrow", - "network": "hathor:privatenet", - "asset": "00", - "amount": "100", - "description": "Pay 1.00 HTR", - "payTo": "WZe3ty22...", - "extra": { - "facilitatorUrl": "http://localhost:8402", - "facilitatorAddress": "WcwKaUE5...", - "blueprintId": "00000022..." - } - }, - { - "scheme": "hathor-escrow", - "network": "hathor:privatenet", - "asset": "000003e3...", - "amount": "1000", - "description": "Or pay 10.00 hUSDC", - "payTo": "WZe3ty22...", - "extra": { "..." : "..." } - } - ] -} -``` - -> **Note on `asset` field:** Following the x402 spec, the field is called `asset` (not `tokenUid`). For Hathor, the asset value is the token UID — `"00"` for HTR or the hex hash of a custom token. - -### X-Payment Header (Client -> Server) - -```json -{ - "scheme": "hathor-escrow", - "network": "hathor:privatenet", - "payload": { - "ncId": "00000832...", - "depositTxId": "00000832...", - "buyerAddress": "Wk1PQJJk..." - } -} +cd dapp +npm install +npm run dev +# Open http://localhost:3000, connect wallet, fetch a paid URL ``` -### Verify / Settle (Server -> Facilitator) - -See [`facilitator.js`](facilitator.js) for the full request/response formats. - ## Project Structure ``` x402-poc/ ├── blueprint/ -│ └── x402_escrow.py # Nano contract blueprint (Python 3.11) -├── facilitator.js # Facilitator server (:8402) -├── resource-server.js # Example paid API (:3000) -├── client.js # AI agent / buyer script -├── config.js # Shared configuration (env vars) -├── helpers.js # Shared HTTP helpers -├── Dockerfile # Container image -├── .env.example # Environment template +│ └── x402_escrow.py # Escrow nano contract (Python 3.11) +├── facilitator.js # Verify + settle service (:8402) +├── resource-server.js # Example paid API (:3000) +├── client.js # Programmatic x402 client +├── config.js # Shared config (env vars) +├── helpers.js # HTTP helpers +├── dapp/ # Browser-based x402 client (Next.js) +│ ├── app/ # Pages (dashboard, escrow detail) +│ ├── components/ # X402Fetch, EscrowList, EscrowDetail +│ ├── contexts/ # Wallet, Hathor, WalletConnect providers +│ └── lib/ # Config, API, escrow store +├── Dockerfile +├── .env.example └── package.json ``` -## What's Next +## What's next -This is a POC. A production implementation would include: +This is a POC. A production implementation would add: -- **`@hathor/x402-client`** — TypeScript SDK wrapping the client flow -- **`@hathor/x402-server`** — Express/Fastify middleware (one-liner to add x402 to any API) -- **Facilitator as headless plugin** — Runs inside `hathor-wallet-headless` process, not as a standalone server -- **Refund monitor** — Background job watching for expired escrows -- **Payment channels** — Pre-funded escrows for repeat clients (lower latency) -- **Explorer integration** — X402Escrow detection and dashboard in hathor-explorer +- **`@hathor/x402-client`** — npm package wrapping `fetch()` to handle 402 automatically ([RFC](https://github.com/HathorNetwork/rfcs/blob/feat/x402-support/projects/x402/0002-x402-client-sdk.md)) +- **`@hathor/x402-server`** — Express middleware to add x402 to any API in 3 lines ([RFC](https://github.com/HathorNetwork/rfcs/blob/feat/x402-support/projects/x402/0003-x402-server-middleware.md)) +- **Facilitator as headless plugin** — runs inside `hathor-wallet-headless`, not as a separate server +- **Hosted public facilitator** — so sellers don't need to run their own +- **Mempool-aware verification** — verify escrow before block confirmation (~1s instead of ~10s) +- **Payment channels** — pre-funded escrows for repeat clients (eliminates per-request latency) ## References - [x402 Protocol Specification](https://www.x402.org/) -- [Hathor Nano Contracts](https://hathor.network/resources/nano-contracts/) - [RFC: x402 Support for Hathor Network](https://github.com/HathorNetwork/rfcs/blob/feat/x402-support/projects/x402/0001-x402-support.md) +- [RFC: x402 Client SDK](https://github.com/HathorNetwork/rfcs/blob/feat/x402-support/projects/x402/0002-x402-client-sdk.md) +- [RFC: x402 Server Middleware](https://github.com/HathorNetwork/rfcs/blob/feat/x402-support/projects/x402/0003-x402-server-middleware.md) +- [Hathor Nano Contracts](https://hathor.network/resources/nano-contracts/) - [Hathor Forge](https://github.com/HathorNetwork/hathor-forge) — Local development environment +- [create-hathor-dapp](https://github.com/HathorNetwork/create-hathor-dapp) — dApp scaffolding template ## License From c13559bb173c43bf1bd4e5014c379454770fa9c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Thu, 2 Apr 2026 12:40:52 -0300 Subject: [PATCH 05/37] feat: add payment channels (pre-funded, instant after setup) New X402Channel blueprint that allows a client to deposit once and make multiple payments without per-request on-chain transactions. - X402Channel blueprint (blueprint/x402_channel.py): OPEN/CLOSED lifecycle with spend(), top_up(), and close() methods - Facilitator updated to handle both hathor-escrow and hathor-channel schemes for verify and settle - Resource server advertises both escrow and channel payment options - dApp X402Fetch component supports both modes: escrow (one-shot) and channel (pre-funded, instant). Active channels persist in localStorage for seamless multi-request flows. Tested end-to-end: channel with 10 HTR deposit, 2 successful spend() calls, remaining balance 800 cents. Co-Authored-By: Claude Opus 4.6 (1M context) --- .env.example | 3 +- blueprint/x402_channel.py | 95 ++++++++ config.js | 3 +- dapp/components/X402Fetch.tsx | 420 +++++++++++++++++----------------- dapp/lib/config.ts | 3 +- facilitator.js | 211 ++++++++++------- resource-server.js | 95 ++++---- 7 files changed, 491 insertions(+), 339 deletions(-) create mode 100644 blueprint/x402_channel.py diff --git a/.env.example b/.env.example index ee648ee..a543175 100644 --- a/.env.example +++ b/.env.example @@ -2,8 +2,9 @@ FULLNODE_URL=http://127.0.0.1:8080 WALLET_HEADLESS_URL=http://localhost:8000 -# X402Escrow blueprint ID (published on-chain) +# Blueprint IDs (published on-chain) BLUEPRINT_ID= +CHANNEL_BLUEPRINT_ID= # Wallet IDs (must exist in wallet-headless) BUYER_WALLET_ID=buyer diff --git a/blueprint/x402_channel.py b/blueprint/x402_channel.py new file mode 100644 index 0000000..670c6c2 --- /dev/null +++ b/blueprint/x402_channel.py @@ -0,0 +1,95 @@ +from hathor import ( + Address, Amount, Blueprint, Context, NCDepositAction, NCFail, + NCWithdrawalAction, Timestamp, TokenUid, export, public, view +) + +PHASE_OPEN = 'OPEN' +PHASE_CLOSED = 'CLOSED' + + +@export +class X402Channel(Blueprint): + buyer: Address + facilitator: Address + token_uid: TokenUid + total_deposited: Amount + total_spent: Amount + phase: str + deadline: Timestamp + + @public(allow_deposit=True) + def initialize( + self, + ctx: Context, + facilitator: Address, + token_uid: TokenUid, + deadline: Timestamp, + ) -> None: + action = ctx.get_single_action(token_uid) + if not isinstance(action, NCDepositAction): + raise NCFail("Must include a deposit action") + + self.buyer = ctx.get_caller_address() + self.facilitator = facilitator + self.token_uid = token_uid + self.total_deposited = action.amount + self.total_spent = 0 + self.phase = PHASE_OPEN + self.deadline = deadline + + @public(allow_withdrawal=True) + def spend(self, ctx: Context, amount: Amount, seller: Address) -> None: + caller = ctx.get_caller_address() + if caller != self.facilitator: + raise NCFail("Only the facilitator can spend") + if self.phase != PHASE_OPEN: + raise NCFail("Channel is not open") + if self.total_spent + amount > self.total_deposited: + raise NCFail("Insufficient channel balance") + + action = ctx.get_single_action(self.token_uid) + if not isinstance(action, NCWithdrawalAction): + raise NCFail("Must include a withdrawal action") + if action.amount != amount: + raise NCFail("Withdrawal amount must match spend amount") + + self.total_spent = self.total_spent + amount + + @public(allow_deposit=True) + def top_up(self, ctx: Context) -> None: + caller = ctx.get_caller_address() + if caller != self.buyer: + raise NCFail("Only the buyer can top up") + if self.phase != PHASE_OPEN: + raise NCFail("Channel is not open") + + action = ctx.get_single_action(self.token_uid) + if not isinstance(action, NCDepositAction): + raise NCFail("Must include a deposit action") + + self.total_deposited = self.total_deposited + action.amount + + @public(allow_withdrawal=True) + def close(self, ctx: Context) -> None: + caller = ctx.get_caller_address() + + if self.phase != PHASE_OPEN: + raise NCFail("Channel is already closed") + + if caller != self.buyer and caller != self.facilitator: + if ctx.block.timestamp < self.deadline: + raise NCFail("Only buyer or facilitator can close before deadline") + + remaining = self.total_deposited - self.total_spent + if remaining > 0: + action = ctx.get_single_action(self.token_uid) + if not isinstance(action, NCWithdrawalAction): + raise NCFail("Must include a withdrawal action") + if action.amount != remaining: + raise NCFail("Must withdraw exact remaining balance") + + self.phase = PHASE_CLOSED + + @view + def get_remaining(self) -> Amount: + return self.total_deposited - self.total_spent diff --git a/config.js b/config.js index 84b5662..ad86129 100644 --- a/config.js +++ b/config.js @@ -8,8 +8,9 @@ module.exports = { fullnodeUrl: env.FULLNODE_URL || 'http://127.0.0.1:8080', walletHeadlessUrl: env.WALLET_HEADLESS_URL || 'http://localhost:8000', - // Blueprint published on-chain + // Blueprints published on-chain blueprintId: env.BLUEPRINT_ID || '', + channelBlueprintId: env.CHANNEL_BLUEPRINT_ID || '', // Wallet IDs (must be pre-created in wallet-headless) buyerWalletId: env.BUYER_WALLET_ID || 'buyer', diff --git a/dapp/components/X402Fetch.tsx b/dapp/components/X402Fetch.tsx index eddc919..98e2fd2 100644 --- a/dapp/components/X402Fetch.tsx +++ b/dapp/components/X402Fetch.tsx @@ -5,7 +5,6 @@ import { useWallet } from '@/contexts/WalletContext'; import { useHathor } from '@/contexts/HathorContext'; import { config } from '@/lib/config'; import { toast } from '@/lib/toast'; -import { EscrowStatusBadge } from './EscrowStatusBadge'; import { formatAddress } from '@/lib/utils'; interface PaymentOption { @@ -16,11 +15,11 @@ interface PaymentOption { description: string; resource: string; payTo: string; - maxTimeoutSeconds: number; extra: { facilitatorUrl: string; facilitatorAddress: string; - blueprintId: string; + blueprintId?: string; + channelBlueprintId?: string; deadlineSeconds: number; }; } @@ -28,15 +27,28 @@ interface PaymentOption { interface PaymentHistory { id: string; url: string; - ncId: string; + scheme: string; + contractId: string; amount: string; - asset: string; timestamp: Date; - resourceData: any; - status: 'paid' | 'failed'; } -type Step = 'idle' | 'fetching' | 'got402' | 'creating_escrow' | 'waiting_confirmation' | 'retrying' | 'done' | 'error'; +type Step = 'idle' | 'fetching' | 'got402' | 'creating' | 'waiting_confirmation' | 'retrying' | 'done' | 'error'; + +const CHANNEL_STORAGE_KEY = 'x402_active_channel'; + +function getStoredChannel(): string | null { + if (typeof window === 'undefined') return null; + return localStorage.getItem(CHANNEL_STORAGE_KEY); +} + +function storeChannel(channelId: string) { + localStorage.setItem(CHANNEL_STORAGE_KEY, channelId); +} + +function clearStoredChannel() { + localStorage.removeItem(CHANNEL_STORAGE_KEY); +} export function X402Fetch() { const { sendNanoContractTx, address, refreshBalance } = useWallet(); @@ -48,8 +60,9 @@ export function X402Fetch() { const [selectedOption, setSelectedOption] = useState(null); const [resourceData, setResourceData] = useState(null); const [error, setError] = useState(null); - const [ncId, setNcId] = useState(null); + const [contractId, setContractId] = useState(null); const [history, setHistory] = useState([]); + const [activeChannel, setActiveChannel] = useState(getStoredChannel()); const reset = () => { setStep('idle'); @@ -57,128 +70,144 @@ export function X402Fetch() { setSelectedOption(null); setResourceData(null); setError(null); - setNcId(null); + setContractId(null); + }; + + const addToHistory = (scheme: string, id: string, amount: string) => { + setHistory(prev => [{ id: Date.now().toString(), url, scheme, contractId: id, amount, timestamp: new Date() }, ...prev]); }; - // Step 1: Fetch the URL, expect 402 + // Try to pay with an existing channel (instant — no wallet interaction) + const payWithChannel = async (channelId: string): Promise => { + const paymentPayload = { + scheme: 'hathor-channel', + network: `hathor:${network}`, + payload: { channelId, buyerAddress: address }, + }; + + const resp = await fetch(url, { mode: 'cors', headers: { 'X-Payment': JSON.stringify(paymentPayload) } }); + if (!resp.ok) return false; + + const data = await resp.json(); + setResourceData(data); + setContractId(channelId); + setStep('done'); + addToHistory('hathor-channel', channelId, '100'); + refreshBalance('00', network); + return true; + }; + + // Step 1: Fetch the URL const handleFetch = async () => { reset(); + + // If we have an active channel, try instant payment first + if (activeChannel) { + setStep('retrying'); + const ok = await payWithChannel(activeChannel).catch(() => false); + if (ok) { + toast.success('Paid via channel (instant!)'); + return; + } + // Channel failed — clear it and fall through to normal 402 flow + clearStoredChannel(); + setActiveChannel(null); + toast.info('Channel exhausted. Fetching payment options...'); + } + setStep('fetching'); try { const resp = await fetch(url, { mode: 'cors' }); if (resp.ok) { - const data = await resp.json(); - setResourceData(data); + setResourceData(await resp.json()); setStep('done'); - toast.success('Resource is free — no payment needed!'); + toast.success('Resource is free!'); return; } - if (resp.status !== 402) { - throw new Error(`Unexpected status: ${resp.status}`); - } + if (resp.status !== 402) throw new Error(`Unexpected status: ${resp.status}`); const body = await resp.json(); - if (!body.accepts || body.accepts.length === 0) { - throw new Error('402 response has no payment options'); - } + if (!body.accepts?.length) throw new Error('No payment options in 402'); setPaymentOptions(body.accepts); setSelectedOption(body.accepts[0]); setStep('got402'); } catch (err: any) { - console.error('X402 fetch error:', err); setError(err.message || 'Failed to fetch'); setStep('error'); } }; - // Step 2: Create escrow and pay + // Step 2: Pay (escrow or channel) const handlePay = async () => { if (!selectedOption || !isConnected || !address) return; - const opt = selectedOption; - setStep('creating_escrow'); + const isChannel = opt.scheme === 'hathor-channel'; try { - const deadline = Math.floor(Date.now() / 1000) + opt.extra.deadlineSeconds; - const amount = parseInt(opt.amount); - - toast.info('Confirm the escrow deposit in your wallet...'); - - const result = await sendNanoContractTx({ - network, - blueprint_id: opt.extra.blueprintId, - method: 'initialize', - args: [ - opt.payTo, - opt.extra.facilitatorAddress, - opt.asset, - deadline, - opt.resource, - 'dapp-x402-fetch', - ], - actions: [{ - type: 'deposit', - amount: String(amount), - token: opt.asset, - }], - push_tx: true, - }); - - const escrowId = result?.response?.hash || result?.hash || result?.response?.response?.hash; - if (!escrowId) { - throw new Error('No transaction hash in response'); + setStep('creating'); + let id: string; + + if (isChannel) { + // Create a new channel with 10x the per-request amount + const deadline = Math.floor(Date.now() / 1000) + 3600; + const deposit = parseInt(opt.amount) * 10; + toast.info('Confirm the channel deposit in your wallet...'); + + const result = await sendNanoContractTx({ + network, blueprint_id: opt.extra.channelBlueprintId, method: 'initialize', + args: [opt.extra.facilitatorAddress, opt.asset, deadline], + actions: [{ type: 'deposit', amount: String(deposit), token: opt.asset }], + push_tx: true, + }); + id = result?.response?.hash || result?.hash || result?.response?.response?.hash; + if (!id) throw new Error('No tx hash'); + storeChannel(id); + setActiveChannel(id); + toast.success(`Channel created: ${id.slice(0, 12)}...`); + } else { + // Create a one-shot escrow + const deadline = Math.floor(Date.now() / 1000) + opt.extra.deadlineSeconds; + toast.info('Confirm the escrow deposit in your wallet...'); + + const result = await sendNanoContractTx({ + network, blueprint_id: opt.extra.blueprintId, method: 'initialize', + args: [opt.payTo, opt.extra.facilitatorAddress, opt.asset, deadline, opt.resource, 'dapp-x402'], + actions: [{ type: 'deposit', amount: opt.amount, token: opt.asset }], + push_tx: true, + }); + id = result?.response?.hash || result?.hash || result?.response?.response?.hash; + if (!id) throw new Error('No tx hash'); + await addEscrow(id); + toast.success(`Escrow created: ${id.slice(0, 12)}...`); } - setNcId(escrowId); - await addEscrow(escrowId); - toast.success(`Escrow created: ${escrowId.slice(0, 12)}...`); + setContractId(id); - // Step 3: Wait for confirmation + // Wait for confirmation setStep('waiting_confirmation'); - await waitForConfirmation(escrowId); + await waitForConfirmation(id); - // Step 4: Retry with payment proof + // Retry with payment proof setStep('retrying'); - const paymentPayload = { - scheme: 'hathor-escrow', - network: `hathor:${network}`, - payload: { - ncId: escrowId, - depositTxId: escrowId, - buyerAddress: address, - }, - }; - - const paidResp = await fetch(url, { - headers: { 'X-Payment': JSON.stringify(paymentPayload) }, - }); - - if (paidResp.status !== 200) { + const paymentPayload = isChannel + ? { scheme: 'hathor-channel', network: `hathor:${network}`, payload: { channelId: id, buyerAddress: address } } + : { scheme: 'hathor-escrow', network: `hathor:${network}`, payload: { ncId: id, depositTxId: id, buyerAddress: address } }; + + const paidResp = await fetch(url, { mode: 'cors', headers: { 'X-Payment': JSON.stringify(paymentPayload) } }); + if (!paidResp.ok) { const errBody = await paidResp.json().catch(() => ({})); - throw new Error(errBody.reason || errBody.error || `Payment rejected: ${paidResp.status}`); + throw new Error(errBody.reason || errBody.error || `Rejected: ${paidResp.status}`); } const data = await paidResp.json(); setResourceData(data); setStep('done'); toast.success('Resource received!'); - - // Add to history - setHistory(prev => [{ - id: escrowId, - url, - ncId: escrowId, - amount: opt.amount, - asset: opt.asset, - timestamp: new Date(), - resourceData: data, - status: 'paid', - }, ...prev]); - + addToHistory(opt.scheme, id, opt.amount); refreshBalance('00', network); } catch (err: any) { setError(err.message); @@ -197,28 +226,43 @@ export function X402Fetch() { } catch { /* retry */ } await new Promise(r => setTimeout(r, 1000)); } - throw new Error('Transaction confirmation timeout (60s)'); + throw new Error('Confirmation timeout (60s)'); }; - const amountDisplay = selectedOption - ? `${(parseInt(selectedOption.amount) / 100).toFixed(2)} ${selectedOption.asset === '00' ? 'HTR' : 'tokens'}` - : ''; + const amountDisplay = selectedOption ? `${(parseInt(selectedOption.amount) / 100).toFixed(2)} HTR` : ''; + const isChannel = selectedOption?.scheme === 'hathor-channel'; return (

+ {/* Active Channel Banner */} + {activeChannel && ( +
+
+ Active Payment Channel +

{formatAddress(activeChannel)}

+

Requests will be paid instantly — no wallet confirmation needed

+
+ +
+ )} + {/* URL Input */}

Access a Paid Resource

- Enter the URL of an x402-enabled API. The dApp will handle the payment flow automatically. + {activeChannel + ? 'Your channel will pay instantly — no wallet popup.' + : 'Enter an x402-enabled URL. Choose escrow (per-request) or channel (pre-funded).'}

setUrl(e.target.value)} - placeholder="https://api.example.com/data" + type="text" value={url} onChange={e => setUrl(e.target.value)} className="flex-1 bg-slate-700 border border-slate-600 rounded-lg px-4 py-3 text-white font-mono text-sm" disabled={step !== 'idle' && step !== 'error' && step !== 'done'} /> @@ -226,196 +270,150 @@ export function X402Fetch() { onClick={step === 'idle' || step === 'error' || step === 'done' ? handleFetch : undefined} disabled={!url || (step !== 'idle' && step !== 'error' && step !== 'done')} className="px-6 py-3 rounded-lg font-medium transition-colors disabled:opacity-50 whitespace-nowrap" - style={{ - background: 'linear-gradient(244deg, rgb(255, 166, 0) 0%, rgb(255, 115, 0) 100%)', - color: '#0f172a' - }} + style={{ background: 'linear-gradient(244deg, rgb(255, 166, 0) 0%, rgb(255, 115, 0) 100%)', color: '#0f172a' }} > Fetch
- {/* Step: Fetching */} + {/* Fetching */} {step === 'fetching' && (
-
Fetching resource...
-

Requesting {url}

+
Fetching resource...
)} - {/* Step: Got 402 — show payment options */} + {/* Got 402 — payment options */} {step === 'got402' && selectedOption && (
💰

402 — Payment Required

-

This resource requires payment to access

+

Choose how to pay

-
-
- Resource - {selectedOption.resource} -
-
- Amount + {/* Option selector */} +
+ {paymentOptions.map((opt, i) => { + const isCh = opt.scheme === 'hathor-channel'; + return ( + + ); + })} +
+ + {/* Details */} +
+
+ Per request {amountDisplay}
-
- Pay to (seller) + {isChannel && ( +
+ Channel deposit (10 requests) + {(parseInt(selectedOption.amount) * 10 / 100).toFixed(2)} HTR +
+ )} +
+ Seller {formatAddress(selectedOption.payTo)}
-
- Facilitator - {formatAddress(selectedOption.extra.facilitatorAddress)} -
-
- Deadline - {selectedOption.extra.deadlineSeconds}s +
+ After this + + {isChannel ? 'Next 9 requests are instant' : 'Each request needs a new escrow'} +
- {selectedOption.description && ( -
- Description - {selectedOption.description} -
- )}
- {paymentOptions.length > 1 && ( -
- -
- {paymentOptions.map((opt, i) => ( - - ))} -
-
- )} -
- - +
)} - {/* Step: Creating escrow */} - {step === 'creating_escrow' && ( + {/* Creating */} + {step === 'creating' && (
-
Creating escrow...
+
{isChannel ? 'Creating channel...' : 'Creating escrow...'}

Confirm the deposit in your wallet

)} - {/* Step: Waiting confirmation */} + {/* Waiting confirmation */} {step === 'waiting_confirmation' && (
Waiting for on-chain confirmation...
-

- Escrow ID: {ncId?.slice(0, 16)}... -

-

This usually takes 8-16 seconds

+

{contractId?.slice(0, 20)}...

+

~8-16 seconds

)} - {/* Step: Retrying */} + {/* Retrying */} {step === 'retrying' && ( -
-
Payment verified! Fetching resource...
-

Retrying request with payment proof

+
+
Payment verified! Fetching resource...
)} - {/* Step: Done — show resource */} + {/* Done */} {step === 'done' && resourceData && (

Resource Received

- {ncId &&

Paid via escrow {formatAddress(ncId)}

} + {contractId &&

Via {formatAddress(contractId)}

}
-
             {JSON.stringify(resourceData.data || resourceData, null, 2)}
           
- -
)} - {/* Step: Error */} + {/* Error */} {step === 'error' && (
-
- -

Error

-
+

Error

{error}

- +
)} - {/* Payment History */} + {/* History */} {history.length > 0 && (

Payment History

-
- {history.map((entry) => ( -
+
+ {history.map((e) => ( +
-

{entry.url}

-

- {entry.timestamp.toLocaleTimeString()} — Escrow: {formatAddress(entry.ncId)} -

-
-
-

- {(parseInt(entry.amount) / 100).toFixed(2)} {entry.asset === '00' ? 'HTR' : 'tokens'} -

- +

{e.url}

+

{e.timestamp.toLocaleTimeString()} — {formatAddress(e.contractId)}

+ + {e.scheme === 'hathor-channel' ? 'channel' : 'escrow'} +
))}
diff --git a/dapp/lib/config.ts b/dapp/lib/config.ts index 2d00185..b2ae7c9 100644 --- a/dapp/lib/config.ts +++ b/dapp/lib/config.ts @@ -9,8 +9,9 @@ export const config = { 'mainnet': process.env.NEXT_PUBLIC_HATHOR_NODE_URL_MAINNET || 'https://node1.mainnet.hathor.network/v1a', }, - // x402 Escrow config + // x402 config blueprintId: process.env.NEXT_PUBLIC_BLUEPRINT_ID || '', + channelBlueprintId: process.env.NEXT_PUBLIC_CHANNEL_BLUEPRINT_ID || '', facilitatorAddress: process.env.NEXT_PUBLIC_FACILITATOR_ADDRESS || '', sellerAddress: process.env.NEXT_PUBLIC_SELLER_ADDRESS || '', escrowDeadlineSeconds: parseInt(process.env.NEXT_PUBLIC_ESCROW_DEADLINE_SECONDS || '300'), diff --git a/facilitator.js b/facilitator.js index f1ecacc..be4056a 100644 --- a/facilitator.js +++ b/facilitator.js @@ -1,5 +1,6 @@ // x402 Facilitator Server // Exposes /x402/verify and /x402/settle endpoints +// Supports both escrow (hathor-escrow) and channel (hathor-channel) schemes // Talks to hathor-forge fullnode for state queries and wallet-headless for settlement const express = require('express'); @@ -9,122 +10,168 @@ const { walletRequest, getNanoContractState, waitForTxConfirmation, log } = requ const app = express(); app.use(express.json()); -// Validate escrow state against a single payment requirement -function validateAgainstRequirement(fields, req) { +// ============================================================================ +// ESCROW verification/settlement (one contract per payment) +// ============================================================================ + +function validateEscrowAgainstRequirement(fields, req) { const errors = []; - if (fields.phase.value !== 'LOCKED') { - errors.push(`phase is ${fields.phase.value}, expected LOCKED`); - } - if (fields.amount.value < parseInt(req.maxAmountRequired)) { - errors.push(`amount ${fields.amount.value} < required ${req.maxAmountRequired}`); - } - if (fields.seller.value !== req.payTo) { - errors.push(`seller ${fields.seller.value} != payTo ${req.payTo}`); - } - if (fields.facilitator.value !== config.facilitatorAddress) { - errors.push(`facilitator ${fields.facilitator.value} != expected ${config.facilitatorAddress}`); - } - if (req.asset && fields.token_uid.value !== req.asset) { - errors.push(`token_uid ${fields.token_uid.value} != asset ${req.asset}`); - } + if (fields.phase.value !== 'LOCKED') errors.push(`phase is ${fields.phase.value}, expected LOCKED`); + if (fields.amount.value < parseInt(req.maxAmountRequired)) errors.push(`amount ${fields.amount.value} < required ${req.maxAmountRequired}`); + if (fields.seller.value !== req.payTo) errors.push(`seller ${fields.seller.value} != payTo ${req.payTo}`); + if (fields.facilitator.value !== config.facilitatorAddress) errors.push(`facilitator mismatch`); + if (req.asset && fields.token_uid.value !== req.asset) errors.push(`token_uid ${fields.token_uid.value} != asset ${req.asset}`); return errors; } -// POST /x402/verify -// Resource server calls this to verify an escrow is valid -// paymentRequirements can be a single object or an array (multi-token) -app.post('/x402/verify', async (req, res) => { - const { paymentPayload, paymentRequirements } = req.body; - const { ncId } = paymentPayload.payload; +async function verifyEscrow(ncId, requirements) { + const stateResp = await getNanoContractState(ncId); + if (!stateResp.success) return { valid: false, invalidReason: `Cannot query contract: ${stateResp.message}` }; - log('FACILITATOR', `Verify request for ncId=${ncId}`); + const reqs = Array.isArray(requirements) ? requirements : [requirements]; + let lastErrors = []; + for (const req of reqs) { + const errors = validateEscrowAgainstRequirement(stateResp.fields, req); + if (errors.length === 0) return { valid: true }; + lastErrors = errors; + } + return { valid: false, invalidReason: lastErrors.join('; ') }; +} +async function settleEscrow(ncId) { const stateResp = await getNanoContractState(ncId); - if (!stateResp.success) { - return res.json({ valid: false, invalidReason: `Cannot query contract: ${stateResp.message}` }); - } + if (!stateResp.success) return { success: false, error: `Cannot query contract` }; const fields = stateResp.fields; + if (fields.phase.value !== 'LOCKED') return { success: false, error: `Escrow not locked (phase=${fields.phase.value})` }; - // Support both single requirement and array of requirements - const requirements = Array.isArray(paymentRequirements) - ? paymentRequirements - : [paymentRequirements]; + const amount = fields.amount.value; + const seller = fields.seller.value; + const tokenUid = fields.token_uid.value; - // Try each requirement — if any matches, the payment is valid - let lastErrors = []; - for (const requirement of requirements) { - const errors = validateAgainstRequirement(fields, requirement); - if (errors.length === 0) { - log('FACILITATOR', `Verification PASSED for ncId=${ncId} (asset: ${fields.token_uid.value})`); - return res.json({ valid: true }); - } - lastErrors = errors; - } + log('FACILITATOR', `Escrow release() — ${amount} of ${tokenUid} to ${seller}`); + const result = await walletRequest('POST', '/wallet/nano-contracts/execute', { + nc_id: ncId, + method: 'release', + address: config.facilitatorAddress, + data: { args: [], actions: [{ type: 'withdrawal', token: tokenUid, amount, address: seller }] }, + }, config.facilitatorWalletId); - log('FACILITATOR', `Verification FAILED: ${lastErrors.join('; ')}`); - res.json({ valid: false, invalidReason: lastErrors.join('; ') }); -}); + if (!result.success) return { success: false, error: result.message || 'release() failed' }; + await waitForTxConfirmation(result.hash); + return { success: true, txId: result.hash, network: 'hathor:privatenet' }; +} -// POST /x402/settle -// Resource server calls this after serving the resource -app.post('/x402/settle', async (req, res) => { - const { ncId } = req.body.paymentPayload.payload; +// ============================================================================ +// CHANNEL verification/settlement (pre-funded, multiple payments) +// ============================================================================ - log('FACILITATOR', `Settle request for ncId=${ncId}`); +const CHANNEL_FIELDS = ['buyer', 'facilitator', 'token_uid', 'total_deposited', 'total_spent', 'phase', 'deadline']; - // Get escrow state to know amount and seller - const stateResp = await getNanoContractState(ncId); - if (!stateResp.success) { - return res.json({ success: false, error: `Cannot query contract: ${stateResp.message}` }); - } +async function getChannelState(channelId) { + const queryString = CHANNEL_FIELDS.map(f => `fields[]=${f}`).join('&'); + const url = `${config.fullnodeUrl}/v1a/nano_contract/state?id=${channelId}&${queryString}`; + const resp = await require('node-fetch')(url); + return resp.json(); +} + +async function verifyChannel(channelId, requirements) { + const stateResp = await getChannelState(channelId); + if (!stateResp.success) return { valid: false, invalidReason: `Cannot query channel: ${stateResp.message}` }; const fields = stateResp.fields; - if (fields.phase.value !== 'LOCKED') { - return res.json({ success: false, error: `Escrow not locked (phase=${fields.phase.value})` }); + if (fields.phase.value !== 'OPEN') return { valid: false, invalidReason: `Channel not open (phase=${fields.phase.value})` }; + if (fields.facilitator.value !== config.facilitatorAddress) return { valid: false, invalidReason: 'Facilitator mismatch' }; + + const remaining = fields.total_deposited.value - fields.total_spent.value; + const reqs = Array.isArray(requirements) ? requirements : [requirements]; + + for (const req of reqs) { + const amount = parseInt(req.maxAmountRequired || req.amount); + if (remaining >= amount) { + if (req.asset && fields.token_uid.value !== req.asset) continue; + return { valid: true, remaining }; + } } + return { valid: false, invalidReason: `Insufficient channel balance (remaining: ${remaining})` }; +} + +async function settleChannel(channelId, amount, sellerAddress) { + const stateResp = await getChannelState(channelId); + if (!stateResp.success) return { success: false, error: 'Cannot query channel' }; + + const fields = stateResp.fields; + if (fields.phase.value !== 'OPEN') return { success: false, error: 'Channel not open' }; - const amount = fields.amount.value; - const seller = fields.seller.value; const tokenUid = fields.token_uid.value; + const remaining = fields.total_deposited.value - fields.total_spent.value; + if (remaining < amount) return { success: false, error: `Insufficient balance (${remaining} < ${amount})` }; - // Execute release() on the nano contract via wallet-headless - log('FACILITATOR', `Calling release() — withdrawing ${amount} of token ${tokenUid} to seller ${seller}`); + log('FACILITATOR', `Channel spend() — ${amount} of ${tokenUid} to ${sellerAddress}`); const result = await walletRequest('POST', '/wallet/nano-contracts/execute', { - nc_id: ncId, - method: 'release', + nc_id: channelId, + method: 'spend', address: config.facilitatorAddress, data: { - args: [], - actions: [{ - type: 'withdrawal', - token: tokenUid, - amount: amount, - address: seller, - }], + args: [amount, sellerAddress], + actions: [{ type: 'withdrawal', token: tokenUid, amount, address: sellerAddress }], }, }, config.facilitatorWalletId); - if (!result.success) { - log('FACILITATOR', `Settlement FAILED: ${JSON.stringify(result)}`); - return res.json({ success: false, error: result.message || 'release() failed' }); + if (!result.success) return { success: false, error: result.message || 'spend() failed' }; + await waitForTxConfirmation(result.hash); + return { success: true, txId: result.hash, network: 'hathor:privatenet' }; +} + +// ============================================================================ +// HTTP Endpoints (scheme-agnostic) +// ============================================================================ + +app.post('/x402/verify', async (req, res) => { + const { paymentPayload, paymentRequirements } = req.body; + const scheme = paymentPayload.scheme; + + if (scheme === 'hathor-channel') { + const { channelId } = paymentPayload.payload; + log('FACILITATOR', `Channel verify for channelId=${channelId}`); + const result = await verifyChannel(channelId, paymentRequirements); + log('FACILITATOR', `Channel verify ${result.valid ? 'PASSED' : 'FAILED'}: ${result.invalidReason || 'OK'}`); + return res.json(result); } - log('FACILITATOR', `Settlement SUCCESS — txId=${result.hash}`); + // Default: escrow + const { ncId } = paymentPayload.payload; + log('FACILITATOR', `Escrow verify for ncId=${ncId}`); + const result = await verifyEscrow(ncId, paymentRequirements); + log('FACILITATOR', `Escrow verify ${result.valid ? 'PASSED' : 'FAILED'}: ${result.invalidReason || 'OK'}`); + res.json(result); +}); - // Wait for the release tx to confirm - await waitForTxConfirmation(result.hash); - log('FACILITATOR', `Release tx confirmed: ${result.hash}`); +app.post('/x402/settle', async (req, res) => { + const { paymentPayload } = req.body; + const scheme = paymentPayload.scheme; + + if (scheme === 'hathor-channel') { + const { channelId } = paymentPayload.payload; + const amount = req.body.amount || paymentPayload.payload.amount; + const sellerAddress = req.body.sellerAddress || paymentPayload.payload.sellerAddress; + log('FACILITATOR', `Channel settle for channelId=${channelId}, amount=${amount}`); + const result = await settleChannel(channelId, amount, sellerAddress); + log('FACILITATOR', `Channel settle ${result.success ? 'SUCCESS' : 'FAILED'}: ${result.txId || result.error}`); + return res.json(result); + } - res.json({ - success: true, - txId: result.hash, - network: 'hathor:privatenet', - }); + // Default: escrow + const { ncId } = paymentPayload.payload; + log('FACILITATOR', `Escrow settle for ncId=${ncId}`); + const result = await settleEscrow(ncId); + log('FACILITATOR', `Escrow settle ${result.success ? 'SUCCESS' : 'FAILED'}: ${result.txId || result.error}`); + res.json(result); }); app.listen(config.facilitatorPort, () => { log('FACILITATOR', `x402 Facilitator running on port ${config.facilitatorPort}`); log('FACILITATOR', `Facilitator address: ${config.facilitatorAddress}`); - log('FACILITATOR', `Blueprint ID: ${config.blueprintId}`); + log('FACILITATOR', `Escrow blueprint: ${config.blueprintId}`); + log('FACILITATOR', `Channel blueprint: ${config.channelBlueprintId}`); }); diff --git a/resource-server.js b/resource-server.js index f36039e..31bfef6 100644 --- a/resource-server.js +++ b/resource-server.js @@ -1,7 +1,7 @@ // x402 Resource Server (Seller) // A simple API server that sells weather data -// Accepts payment in HTR or a custom token (e.g. hUSDC) -// Uses x402 middleware to gate access +// Accepts payment via escrow (hathor-escrow) or channel (hathor-channel) +// Supports HTR and custom tokens const express = require('express'); const fetch = require('node-fetch'); @@ -20,34 +20,43 @@ app.use((req, res, next) => { next(); }); -// Build the list of accepted payment options +// Build the list of accepted payment options (escrow + channel) function buildAcceptsList(path) { - const base = { + const baseExtra = { + facilitatorUrl: `http://localhost:${config.facilitatorPort}`, + facilitatorAddress: config.facilitatorAddress, + deadlineSeconds: config.escrowDeadlineSeconds, + }; + + const accepts = []; + + // Escrow options + accepts.push({ scheme: 'hathor-escrow', network: 'hathor:privatenet', resource: `http://localhost:${config.resourceServerPort}${path}`, mimeType: 'application/json', payTo: config.sellerAddress, maxTimeoutSeconds: config.escrowDeadlineSeconds, - extra: { - facilitatorUrl: `http://localhost:${config.facilitatorPort}`, - facilitatorAddress: config.facilitatorAddress, - blueprintId: config.blueprintId, - deadlineSeconds: config.escrowDeadlineSeconds, - }, - }; - - const accepts = [ - { ...base, asset: config.htrTokenUid, amount: String(config.htrPaymentAmount), description: 'Pay 1.00 HTR' }, - ]; + asset: config.htrTokenUid, + amount: String(config.htrPaymentAmount), + description: `Pay ${(config.htrPaymentAmount / 100).toFixed(2)} HTR (single escrow)`, + extra: { ...baseExtra, blueprintId: config.blueprintId }, + }); - // If a custom token is configured, offer it as an alternative - if (config.customTokenUid) { + // Channel options + if (config.channelBlueprintId) { accepts.push({ - ...base, - asset: config.customTokenUid, - amount: String(config.customTokenPaymentAmount), - description: 'Or pay 10.00 hUSDC', + scheme: 'hathor-channel', + network: 'hathor:privatenet', + resource: `http://localhost:${config.resourceServerPort}${path}`, + mimeType: 'application/json', + payTo: config.sellerAddress, + maxTimeoutSeconds: config.escrowDeadlineSeconds, + asset: config.htrTokenUid, + amount: String(config.htrPaymentAmount), + description: `Pay ${(config.htrPaymentAmount / 100).toFixed(2)} HTR via channel (instant if pre-funded)`, + extra: { ...baseExtra, channelBlueprintId: config.channelBlueprintId }, }); } @@ -66,14 +75,12 @@ function x402Middleware(req, res, next) { }); } - // Payment present — verify it const payment = JSON.parse(paymentHeader); req.x402Payment = payment; next(); } -// Find which accepted option the client paid with by querying the facilitator. -// The server sends ALL accepted options and the facilitator checks which one matches. +// Build payment requirements from the accepts list function buildPaymentRequirements(path) { return buildAcceptsList(path).map(opt => ({ scheme: opt.scheme, @@ -87,22 +94,18 @@ function buildPaymentRequirements(path) { // Verify payment with facilitator, serve resource, then settle app.get('/weather', x402Middleware, async (req, res) => { const payment = req.x402Payment; - const { ncId } = payment.payload; - - log('RESOURCE-SERVER', `Verifying payment ncId=${ncId}`); + const scheme = payment.scheme; + const isChannel = scheme === 'hathor-channel'; + const id = isChannel ? payment.payload.channelId : payment.payload.ncId; - // Build all accepted payment requirements — the facilitator will match - // the on-chain escrow state against each one to find a valid match - const allRequirements = buildPaymentRequirements(req.path); + log('RESOURCE-SERVER', `Verifying ${scheme} payment id=${id}`); // Step 1: Verify with facilitator + const allRequirements = buildPaymentRequirements(req.path); const verifyResp = await fetch(`http://localhost:${config.facilitatorPort}/x402/verify`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - paymentPayload: payment, - paymentRequirements: allRequirements, - }), + body: JSON.stringify({ paymentPayload: payment, paymentRequirements: allRequirements }), }); const verification = await verifyResp.json(); @@ -124,14 +127,20 @@ app.get('/weather', x402Middleware, async (req, res) => { timestamp: new Date().toISOString(), }; - // Step 3: Settle with facilitator (async — don't block response) - log('RESOURCE-SERVER', `Requesting settlement for ncId=${ncId}`); + // Step 3: Settle with facilitator (async) + log('RESOURCE-SERVER', `Requesting settlement for ${scheme} id=${id}`); + const settleBody = { paymentPayload: payment }; + + // Channel settle needs amount and seller + if (isChannel) { + settleBody.amount = config.htrPaymentAmount; + settleBody.sellerAddress = config.sellerAddress; + } + fetch(`http://localhost:${config.facilitatorPort}/x402/settle`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - paymentPayload: payment, - }), + body: JSON.stringify(settleBody), }) .then(r => r.json()) .then(result => { @@ -143,14 +152,14 @@ app.get('/weather', x402Middleware, async (req, res) => { }) .catch(err => log('RESOURCE-SERVER', `Settlement error: ${err.message}`)); - // Return the resource immediately after verification + // Return the resource res.json({ data: weatherData, payment: { success: true, - scheme: 'hathor-escrow', + scheme, network: 'hathor:privatenet', - ncId, + id, }, }); }); @@ -158,5 +167,5 @@ app.get('/weather', x402Middleware, async (req, res) => { app.listen(config.resourceServerPort, () => { log('RESOURCE-SERVER', `Weather API running on port ${config.resourceServerPort}`); log('RESOURCE-SERVER', `Seller address: ${config.sellerAddress}`); - log('RESOURCE-SERVER', `Accepts: HTR (${config.htrPaymentAmount} cents)${config.customTokenUid ? `, hUSDC (${config.customTokenPaymentAmount} cents)` : ''}`); + log('RESOURCE-SERVER', `Accepts: escrow${config.channelBlueprintId ? ' + channel' : ''}`); }); From 0341ff0e30ec40f4932185b0eeb4eb084893d480 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Thu, 2 Apr 2026 13:07:30 -0300 Subject: [PATCH 06/37] fix: settle before serving resource (no optimistic verify) The resource server now waits for settlement confirmation BEFORE serving the resource. This ensures the on-chain state is updated before the next request, preventing the race condition where multiple channel spends could be approved against stale state. The channel advantage is now correctly: saves the client from creating a new escrow per request (1 on-chain tx instead of 2), not "instant" access. Co-Authored-By: Claude Opus 4.6 (1M context) --- resource-server.js | 64 ++++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/resource-server.js b/resource-server.js index 31bfef6..77cdccb 100644 --- a/resource-server.js +++ b/resource-server.js @@ -30,7 +30,7 @@ function buildAcceptsList(path) { const accepts = []; - // Escrow options + // Escrow option accepts.push({ scheme: 'hathor-escrow', network: 'hathor:privatenet', @@ -44,7 +44,7 @@ function buildAcceptsList(path) { extra: { ...baseExtra, blueprintId: config.blueprintId }, }); - // Channel options + // Channel option if (config.channelBlueprintId) { accepts.push({ scheme: 'hathor-channel', @@ -55,7 +55,7 @@ function buildAcceptsList(path) { maxTimeoutSeconds: config.escrowDeadlineSeconds, asset: config.htrTokenUid, amount: String(config.htrPaymentAmount), - description: `Pay ${(config.htrPaymentAmount / 100).toFixed(2)} HTR via channel (instant if pre-funded)`, + description: `Pay ${(config.htrPaymentAmount / 100).toFixed(2)} HTR via channel (saves escrow creation)`, extra: { ...baseExtra, channelBlueprintId: config.channelBlueprintId }, }); } @@ -80,7 +80,6 @@ function x402Middleware(req, res, next) { next(); } -// Build payment requirements from the accepts list function buildPaymentRequirements(path) { return buildAcceptsList(path).map(opt => ({ scheme: opt.scheme, @@ -91,7 +90,7 @@ function buildPaymentRequirements(path) { })); } -// Verify payment with facilitator, serve resource, then settle +// Verify + settle + serve app.get('/weather', x402Middleware, async (req, res) => { const payment = req.x402Payment; const scheme = payment.scheme; @@ -114,9 +113,33 @@ app.get('/weather', x402Middleware, async (req, res) => { return res.status(402).json({ error: 'Payment invalid', reason: verification.invalidReason }); } - log('RESOURCE-SERVER', `Payment VALID — serving resource`); + log('RESOURCE-SERVER', `Payment VALID`); - // Step 2: Serve the resource + // Step 2: Settle BEFORE serving the resource + // For channels: spend() must confirm so on-chain state is updated before next request + // For escrow: release() must confirm so funds reach the seller + log('RESOURCE-SERVER', `Settling ${scheme} id=${id}`); + const settleBody = { paymentPayload: payment }; + if (isChannel) { + settleBody.amount = config.htrPaymentAmount; + settleBody.sellerAddress = config.sellerAddress; + } + + const settleResp = await fetch(`http://localhost:${config.facilitatorPort}/x402/settle`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(settleBody), + }); + const settlement = await settleResp.json(); + + if (!settlement.success) { + log('RESOURCE-SERVER', `Settlement FAILED: ${settlement.error}`); + return res.status(500).json({ error: 'Settlement failed', reason: settlement.error }); + } + + log('RESOURCE-SERVER', `Settlement confirmed — txId=${settlement.txId}`); + + // Step 3: Serve the resource (only after settlement is confirmed) const weatherData = { location: 'Sao Paulo, Brazil', temperature: 28, @@ -127,32 +150,6 @@ app.get('/weather', x402Middleware, async (req, res) => { timestamp: new Date().toISOString(), }; - // Step 3: Settle with facilitator (async) - log('RESOURCE-SERVER', `Requesting settlement for ${scheme} id=${id}`); - const settleBody = { paymentPayload: payment }; - - // Channel settle needs amount and seller - if (isChannel) { - settleBody.amount = config.htrPaymentAmount; - settleBody.sellerAddress = config.sellerAddress; - } - - fetch(`http://localhost:${config.facilitatorPort}/x402/settle`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(settleBody), - }) - .then(r => r.json()) - .then(result => { - if (result.success) { - log('RESOURCE-SERVER', `Settlement complete — txId=${result.txId}`); - } else { - log('RESOURCE-SERVER', `Settlement FAILED: ${result.error}`); - } - }) - .catch(err => log('RESOURCE-SERVER', `Settlement error: ${err.message}`)); - - // Return the resource res.json({ data: weatherData, payment: { @@ -160,6 +157,7 @@ app.get('/weather', x402Middleware, async (req, res) => { scheme, network: 'hathor:privatenet', id, + settleTxId: settlement.txId, }, }); }); From da573097df59dba3352fcba02352dc81a5a8a291 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Thu, 2 Apr 2026 15:15:13 -0300 Subject: [PATCH 07/37] feat: add docker-compose for production deployment Docker Compose with 4 services: - wallet-headless: connects to playground testnet node - facilitator: escrow/channel verify + settle - resource-server: example paid weather API - dapp: Next.js x402 payment client Blueprint IDs and addresses configured via env vars. Co-Authored-By: Claude Opus 4.6 (1M context) --- dapp/Dockerfile | 24 ++++++++++++------ docker-compose.yml | 63 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 7 deletions(-) create mode 100644 docker-compose.yml diff --git a/dapp/Dockerfile b/dapp/Dockerfile index 644a83e..5d2fde2 100644 --- a/dapp/Dockerfile +++ b/dapp/Dockerfile @@ -17,13 +17,23 @@ COPY . . ARG NEXT_PUBLIC_API_URL ENV NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL:-/} -# Set environment for building -ENV NEXT_PUBLIC_USE_MOCK_WALLET=false -ENV NEXT_PUBLIC_DEFAULT_NETWORK=testnet -ENV NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET=https://node1.india.testnet.hathor.network/v1a -ENV NEXT_PUBLIC_HATHOR_NODE_URL_MAINNET=https://node1.mainnet.hathor.network/v1a -ENV NEXT_PUBLIC_CONTRACT_IDS='["0000000079862340c1f7822b81f58668e2a62c5f1b69d8d2e3b8fdf1855196c1"]' -ENV NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=8264fff563181da658ce64ee80e80458 +# x402 build-time env vars (can be overridden at build time via --build-arg) +ARG NEXT_PUBLIC_USE_MOCK_WALLET=false +ARG NEXT_PUBLIC_DEFAULT_NETWORK=testnet +ARG NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET=http://node1.playground.testnet.hathor.network/v1a +ARG NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=8264fff563181da658ce64ee80e80458 +ARG NEXT_PUBLIC_BLUEPRINT_ID +ARG NEXT_PUBLIC_CHANNEL_BLUEPRINT_ID +ARG NEXT_PUBLIC_FACILITATOR_ADDRESS +ARG NEXT_PUBLIC_SELLER_ADDRESS +ENV NEXT_PUBLIC_USE_MOCK_WALLET=${NEXT_PUBLIC_USE_MOCK_WALLET} +ENV NEXT_PUBLIC_DEFAULT_NETWORK=${NEXT_PUBLIC_DEFAULT_NETWORK} +ENV NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET=${NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET} +ENV NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=${NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID} +ENV NEXT_PUBLIC_BLUEPRINT_ID=${NEXT_PUBLIC_BLUEPRINT_ID} +ENV NEXT_PUBLIC_CHANNEL_BLUEPRINT_ID=${NEXT_PUBLIC_CHANNEL_BLUEPRINT_ID} +ENV NEXT_PUBLIC_FACILITATOR_ADDRESS=${NEXT_PUBLIC_FACILITATOR_ADDRESS} +ENV NEXT_PUBLIC_SELLER_ADDRESS=${NEXT_PUBLIC_SELLER_ADDRESS} # Set environment for production build ENV NEXT_TELEMETRY_DISABLED=1 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..901c0b3 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,63 @@ +services: + wallet-headless: + image: hathornetwork/hathor-wallet-headless:v0.39.1 + environment: + HEADLESS_HTTP_BIND: "0.0.0.0" + HEADLESS_HTTP_PORT: "8000" + HEADLESS_NETWORK: testnet + HEADLESS_SERVER: http://node1.playground.testnet.hathor.network/v1a/ + HEADLESS_SEED_DEFAULT: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" + HEADLESS_ENABLED_PLUGINS: debug + entrypoint: ["node", "dist/index.js"] + ports: + - "8000:8000" + + facilitator: + build: . + environment: + FULLNODE_URL: http://node1.playground.testnet.hathor.network + WALLET_HEADLESS_URL: http://wallet-headless:8000 + BLUEPRINT_ID: ${BLUEPRINT_ID:-} + CHANNEL_BLUEPRINT_ID: ${CHANNEL_BLUEPRINT_ID:-} + FACILITATOR_WALLET_ID: facilitator + FACILITATOR_ADDRESS: ${FACILITATOR_ADDRESS:-} + SELLER_ADDRESS: ${SELLER_ADDRESS:-} + command: ["node", "facilitator.js"] + ports: + - "8402:8402" + depends_on: + - wallet-headless + + resource-server: + build: . + environment: + FULLNODE_URL: http://node1.playground.testnet.hathor.network + WALLET_HEADLESS_URL: http://wallet-headless:8000 + BLUEPRINT_ID: ${BLUEPRINT_ID:-} + CHANNEL_BLUEPRINT_ID: ${CHANNEL_BLUEPRINT_ID:-} + FACILITATOR_ADDRESS: ${FACILITATOR_ADDRESS:-} + SELLER_ADDRESS: ${SELLER_ADDRESS:-} + RESOURCE_SERVER_PORT: "3001" + command: ["node", "resource-server.js"] + ports: + - "3001:3001" + depends_on: + - wallet-headless + - facilitator + + dapp: + build: + context: ./dapp + dockerfile: Dockerfile + environment: + NEXT_PUBLIC_DEFAULT_NETWORK: testnet + NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET: http://node1.playground.testnet.hathor.network/v1a + NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID: "8264fff563181da658ce64ee80e80458" + NEXT_PUBLIC_BLUEPRINT_ID: ${BLUEPRINT_ID:-} + NEXT_PUBLIC_CHANNEL_BLUEPRINT_ID: ${CHANNEL_BLUEPRINT_ID:-} + NEXT_PUBLIC_FACILITATOR_ADDRESS: ${FACILITATOR_ADDRESS:-} + NEXT_PUBLIC_SELLER_ADDRESS: ${SELLER_ADDRESS:-} + ports: + - "3000:3000" + depends_on: + - resource-server From 17f25d235b08e929d08d19cdbe8801c6e6f40558 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Thu, 2 Apr 2026 15:17:41 -0300 Subject: [PATCH 08/37] fix: use latest tag for wallet-headless Docker image v0.39.1 doesn't exist on Docker Hub. Use latest (v0.38.0). Co-Authored-By: Claude Opus 4.6 (1M context) --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 901c0b3..5023b95 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,6 @@ services: wallet-headless: - image: hathornetwork/hathor-wallet-headless:v0.39.1 + image: hathornetwork/hathor-wallet-headless:latest environment: HEADLESS_HTTP_BIND: "0.0.0.0" HEADLESS_HTTP_PORT: "8000" From 4c9aa49312fa70c64338cf1c04a4d037669a1e27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Thu, 2 Apr 2026 15:21:30 -0300 Subject: [PATCH 09/37] fix: remove host port conflicts, add FACILITATOR_URL for Docker networking - Remove port mappings for internal services (wallet-headless, facilitator) - Add FACILITATOR_URL env var so resource-server can reach facilitator via Docker service name instead of localhost - Only expose dApp (:3000) and resource-server (:3001) to host Co-Authored-By: Claude Opus 4.6 (1M context) --- config.js | 3 ++- docker-compose.yml | 15 +++------------ resource-server.js | 6 +++--- 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/config.js b/config.js index ad86129..369d912 100644 --- a/config.js +++ b/config.js @@ -26,7 +26,8 @@ module.exports = { htrTokenUid: '00', customTokenUid: env.CUSTOM_TOKEN_UID || '', - // Ports + // Service URLs and ports + facilitatorUrl: env.FACILITATOR_URL || `http://localhost:${env.FACILITATOR_PORT || '8402'}`, facilitatorPort: parseInt(env.FACILITATOR_PORT || '8402'), resourceServerPort: parseInt(env.RESOURCE_SERVER_PORT || '3000'), diff --git a/docker-compose.yml b/docker-compose.yml index 5023b95..0da356e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,8 +9,7 @@ services: HEADLESS_SEED_DEFAULT: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" HEADLESS_ENABLED_PLUGINS: debug entrypoint: ["node", "dist/index.js"] - ports: - - "8000:8000" + # No host ports — internal only, other services reach it via docker network facilitator: build: . @@ -23,8 +22,7 @@ services: FACILITATOR_ADDRESS: ${FACILITATOR_ADDRESS:-} SELLER_ADDRESS: ${SELLER_ADDRESS:-} command: ["node", "facilitator.js"] - ports: - - "8402:8402" + # No host ports — resource-server reaches it via docker network depends_on: - wallet-headless @@ -38,6 +36,7 @@ services: FACILITATOR_ADDRESS: ${FACILITATOR_ADDRESS:-} SELLER_ADDRESS: ${SELLER_ADDRESS:-} RESOURCE_SERVER_PORT: "3001" + FACILITATOR_URL: http://facilitator:8402 command: ["node", "resource-server.js"] ports: - "3001:3001" @@ -49,14 +48,6 @@ services: build: context: ./dapp dockerfile: Dockerfile - environment: - NEXT_PUBLIC_DEFAULT_NETWORK: testnet - NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET: http://node1.playground.testnet.hathor.network/v1a - NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID: "8264fff563181da658ce64ee80e80458" - NEXT_PUBLIC_BLUEPRINT_ID: ${BLUEPRINT_ID:-} - NEXT_PUBLIC_CHANNEL_BLUEPRINT_ID: ${CHANNEL_BLUEPRINT_ID:-} - NEXT_PUBLIC_FACILITATOR_ADDRESS: ${FACILITATOR_ADDRESS:-} - NEXT_PUBLIC_SELLER_ADDRESS: ${SELLER_ADDRESS:-} ports: - "3000:3000" depends_on: diff --git a/resource-server.js b/resource-server.js index 77cdccb..570f44f 100644 --- a/resource-server.js +++ b/resource-server.js @@ -23,7 +23,7 @@ app.use((req, res, next) => { // Build the list of accepted payment options (escrow + channel) function buildAcceptsList(path) { const baseExtra = { - facilitatorUrl: `http://localhost:${config.facilitatorPort}`, + facilitatorUrl: `${config.facilitatorUrl}`, facilitatorAddress: config.facilitatorAddress, deadlineSeconds: config.escrowDeadlineSeconds, }; @@ -101,7 +101,7 @@ app.get('/weather', x402Middleware, async (req, res) => { // Step 1: Verify with facilitator const allRequirements = buildPaymentRequirements(req.path); - const verifyResp = await fetch(`http://localhost:${config.facilitatorPort}/x402/verify`, { + const verifyResp = await fetch(`${config.facilitatorUrl}/x402/verify`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ paymentPayload: payment, paymentRequirements: allRequirements }), @@ -125,7 +125,7 @@ app.get('/weather', x402Middleware, async (req, res) => { settleBody.sellerAddress = config.sellerAddress; } - const settleResp = await fetch(`http://localhost:${config.facilitatorPort}/x402/settle`, { + const settleResp = await fetch(`${config.facilitatorUrl}/x402/settle`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(settleBody), From fe23c58443676eea875d119c3b6de58354cd6fcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Thu, 2 Apr 2026 15:22:27 -0300 Subject: [PATCH 10/37] fix: use ports 4020/4021 to avoid conflicts on deploy server Co-Authored-By: Claude Opus 4.6 (1M context) --- docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 0da356e..71e5e55 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -39,7 +39,7 @@ services: FACILITATOR_URL: http://facilitator:8402 command: ["node", "resource-server.js"] ports: - - "3001:3001" + - "4021:3001" depends_on: - wallet-headless - facilitator @@ -49,6 +49,6 @@ services: context: ./dapp dockerfile: Dockerfile ports: - - "3000:3000" + - "4020:3000" depends_on: - resource-server From a03666e3e5d04e20e29eb4c0b3768c8015c412c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Thu, 2 Apr 2026 15:25:36 -0300 Subject: [PATCH 11/37] fix: add healthchecks and ordered startup for Traefik MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Each service has a healthcheck so Traefik knows when to route traffic. Services start in order via depends_on + service_healthy: wallet-headless → facilitator → resource-server → dapp Co-Authored-By: Claude Opus 4.6 (1M context) --- docker-compose.yml | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 71e5e55..b7946d2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,7 +9,12 @@ services: HEADLESS_SEED_DEFAULT: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" HEADLESS_ENABLED_PLUGINS: debug entrypoint: ["node", "dist/index.js"] - # No host ports — internal only, other services reach it via docker network + healthcheck: + test: ["CMD", "node", "-e", "require('http').get('http://localhost:8000/wallet/status',r=>{process.exit(r.statusCode<500?0:1)}).on('error',()=>process.exit(1))"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 15s facilitator: build: . @@ -22,9 +27,15 @@ services: FACILITATOR_ADDRESS: ${FACILITATOR_ADDRESS:-} SELLER_ADDRESS: ${SELLER_ADDRESS:-} command: ["node", "facilitator.js"] - # No host ports — resource-server reaches it via docker network + healthcheck: + test: ["CMD", "node", "-e", "require('http').get('http://localhost:8402/x402/verify',r=>{process.exit(r.statusCode<500?0:1)}).on('error',()=>process.exit(1))"] + interval: 10s + timeout: 5s + retries: 3 + start_period: 10s depends_on: - - wallet-headless + wallet-headless: + condition: service_healthy resource-server: build: . @@ -38,17 +49,32 @@ services: RESOURCE_SERVER_PORT: "3001" FACILITATOR_URL: http://facilitator:8402 command: ["node", "resource-server.js"] + healthcheck: + test: ["CMD", "node", "-e", "require('http').get('http://localhost:3001/weather',r=>{process.exit(r.statusCode<500?0:1)}).on('error',()=>process.exit(1))"] + interval: 10s + timeout: 5s + retries: 3 + start_period: 10s ports: - "4021:3001" depends_on: - - wallet-headless - - facilitator + wallet-headless: + condition: service_healthy + facilitator: + condition: service_healthy dapp: build: context: ./dapp dockerfile: Dockerfile + healthcheck: + test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/',r=>{process.exit(r.statusCode===200?0:1)}).on('error',()=>process.exit(1))"] + interval: 10s + timeout: 5s + retries: 3 + start_period: 10s ports: - "4020:3000" depends_on: - - resource-server + resource-server: + condition: service_healthy From 72938f63e4dc3afce4689081c2c17ebf2363316b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Thu, 2 Apr 2026 15:28:06 -0300 Subject: [PATCH 12/37] fix: use curl for dApp healthcheck (already installed in image) Co-Authored-By: Claude Opus 4.6 (1M context) --- docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index b7946d2..1400bb3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -68,11 +68,11 @@ services: context: ./dapp dockerfile: Dockerfile healthcheck: - test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/',r=>{process.exit(r.statusCode===200?0:1)}).on('error',()=>process.exit(1))"] + test: ["CMD", "curl", "-f", "http://localhost:3000/"] interval: 10s timeout: 5s retries: 3 - start_period: 10s + start_period: 15s ports: - "4020:3000" depends_on: From 5d266f42b2801112a4604861abdeca1a50f27037 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Thu, 2 Apr 2026 15:31:25 -0300 Subject: [PATCH 13/37] fix: expose facilitator port for Traefik routing Co-Authored-By: Claude Opus 4.6 (1M context) --- docker-compose.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker-compose.yml b/docker-compose.yml index 1400bb3..611aebc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -27,6 +27,8 @@ services: FACILITATOR_ADDRESS: ${FACILITATOR_ADDRESS:-} SELLER_ADDRESS: ${SELLER_ADDRESS:-} command: ["node", "facilitator.js"] + ports: + - "8402:8402" healthcheck: test: ["CMD", "node", "-e", "require('http').get('http://localhost:8402/x402/verify',r=>{process.exit(r.statusCode<500?0:1)}).on('error',()=>process.exit(1))"] interval: 10s From 3e91a762391ef71a5e8904de6edc9499a074dae7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Thu, 2 Apr 2026 15:42:32 -0300 Subject: [PATCH 14/37] fix: add tx-mining service URL for wallet-headless Without a tx-mining service, wallet-headless can't mine PoW for transactions. Uses the playground testnet tx-mining service. Co-Authored-By: Claude Opus 4.6 (1M context) --- docker-compose.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/docker-compose.yml b/docker-compose.yml index 611aebc..a38e5fc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,6 +8,7 @@ services: HEADLESS_SERVER: http://node1.playground.testnet.hathor.network/v1a/ HEADLESS_SEED_DEFAULT: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" HEADLESS_ENABLED_PLUGINS: debug + HEADLESS_TX_MINING_URL: https://txmining.playground.testnet.hathor.network/ entrypoint: ["node", "dist/index.js"] healthcheck: test: ["CMD", "node", "-e", "require('http').get('http://localhost:8000/wallet/status',r=>{process.exit(r.statusCode<500?0:1)}).on('error',()=>process.exit(1))"] From 367dd5b9acfd6b1823384eaffe21e1a46c8d221d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Thu, 2 Apr 2026 15:55:10 -0300 Subject: [PATCH 15/37] fix: use public URLs for deployed services - dApp default URL points to https://api.x402.hathor.dev/weather - Resource server 402 response uses public facilitator and resource server URLs (not localhost) - Add FACILITATOR_PUBLIC_URL, RESOURCE_SERVER_PUBLIC_URL, HATHOR_NETWORK env vars for Docker deployment - Internal facilitator communication still uses Docker service name Co-Authored-By: Claude Opus 4.6 (1M context) --- config.js | 3 +++ dapp/components/X402Fetch.tsx | 2 +- docker-compose.yml | 3 +++ resource-server.js | 12 ++++++------ 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/config.js b/config.js index 369d912..1dda4c6 100644 --- a/config.js +++ b/config.js @@ -28,6 +28,9 @@ module.exports = { // Service URLs and ports facilitatorUrl: env.FACILITATOR_URL || `http://localhost:${env.FACILITATOR_PORT || '8402'}`, + facilitatorPublicUrl: env.FACILITATOR_PUBLIC_URL || env.FACILITATOR_URL || `http://localhost:${env.FACILITATOR_PORT || '8402'}`, + resourceServerPublicUrl: env.RESOURCE_SERVER_PUBLIC_URL || `http://localhost:${env.RESOURCE_SERVER_PORT || '3000'}`, + network: env.HATHOR_NETWORK || 'privatenet', facilitatorPort: parseInt(env.FACILITATOR_PORT || '8402'), resourceServerPort: parseInt(env.RESOURCE_SERVER_PORT || '3000'), diff --git a/dapp/components/X402Fetch.tsx b/dapp/components/X402Fetch.tsx index 98e2fd2..3b6d900 100644 --- a/dapp/components/X402Fetch.tsx +++ b/dapp/components/X402Fetch.tsx @@ -54,7 +54,7 @@ export function X402Fetch() { const { sendNanoContractTx, address, refreshBalance } = useWallet(); const { network, isConnected, addEscrow } = useHathor(); - const [url, setUrl] = useState('http://localhost:3001/weather'); + const [url, setUrl] = useState('https://api.x402.hathor.dev/weather'); const [step, setStep] = useState('idle'); const [paymentOptions, setPaymentOptions] = useState([]); const [selectedOption, setSelectedOption] = useState(null); diff --git a/docker-compose.yml b/docker-compose.yml index a38e5fc..00bc7b4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -51,6 +51,9 @@ services: SELLER_ADDRESS: ${SELLER_ADDRESS:-} RESOURCE_SERVER_PORT: "3001" FACILITATOR_URL: http://facilitator:8402 + FACILITATOR_PUBLIC_URL: https://facilitator.x402.hathor.dev + RESOURCE_SERVER_PUBLIC_URL: https://api.x402.hathor.dev + HATHOR_NETWORK: testnet command: ["node", "resource-server.js"] healthcheck: test: ["CMD", "node", "-e", "require('http').get('http://localhost:3001/weather',r=>{process.exit(r.statusCode<500?0:1)}).on('error',()=>process.exit(1))"] diff --git a/resource-server.js b/resource-server.js index 570f44f..7b33bd0 100644 --- a/resource-server.js +++ b/resource-server.js @@ -23,7 +23,7 @@ app.use((req, res, next) => { // Build the list of accepted payment options (escrow + channel) function buildAcceptsList(path) { const baseExtra = { - facilitatorUrl: `${config.facilitatorUrl}`, + facilitatorUrl: config.facilitatorPublicUrl, facilitatorAddress: config.facilitatorAddress, deadlineSeconds: config.escrowDeadlineSeconds, }; @@ -33,8 +33,8 @@ function buildAcceptsList(path) { // Escrow option accepts.push({ scheme: 'hathor-escrow', - network: 'hathor:privatenet', - resource: `http://localhost:${config.resourceServerPort}${path}`, + network: 'hathor:${config.network}', + resource: `${config.resourceServerPublicUrl}${path}`, mimeType: 'application/json', payTo: config.sellerAddress, maxTimeoutSeconds: config.escrowDeadlineSeconds, @@ -48,8 +48,8 @@ function buildAcceptsList(path) { if (config.channelBlueprintId) { accepts.push({ scheme: 'hathor-channel', - network: 'hathor:privatenet', - resource: `http://localhost:${config.resourceServerPort}${path}`, + network: 'hathor:${config.network}', + resource: `${config.resourceServerPublicUrl}${path}`, mimeType: 'application/json', payTo: config.sellerAddress, maxTimeoutSeconds: config.escrowDeadlineSeconds, @@ -155,7 +155,7 @@ app.get('/weather', x402Middleware, async (req, res) => { payment: { success: true, scheme, - network: 'hathor:privatenet', + network: 'hathor:${config.network}', id, settleTxId: settlement.txId, }, From e4799f528f8176d2fbbb0a9adf2c5334bb1bb944 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Thu, 2 Apr 2026 16:32:12 -0300 Subject: [PATCH 16/37] feat: auto-initialize wallets on deploy Add init-wallets.sh that starts facilitator and seller wallets on the deployed wallet-headless before launching the facilitator service. Seeds are injected via Dokploy env vars (not in git). Co-Authored-By: Claude Opus 4.6 (1M context) --- Dockerfile | 3 +++ docker-compose.yml | 4 +++- init-wallets.sh | 29 +++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100755 init-wallets.sh diff --git a/Dockerfile b/Dockerfile index 95b6a94..5f91ff7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,14 @@ FROM node:22-alpine +RUN apk add --no-cache curl + WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci --production COPY *.js ./ +COPY *.sh ./ COPY blueprint/ ./blueprint/ EXPOSE 8402 3000 diff --git a/docker-compose.yml b/docker-compose.yml index 00bc7b4..4e0eaf3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -27,7 +27,9 @@ services: FACILITATOR_WALLET_ID: facilitator FACILITATOR_ADDRESS: ${FACILITATOR_ADDRESS:-} SELLER_ADDRESS: ${SELLER_ADDRESS:-} - command: ["node", "facilitator.js"] + FACILITATOR_SEED: ${FACILITATOR_SEED:-} + SELLER_SEED: ${SELLER_SEED:-} + command: ["sh", "init-wallets.sh", "node", "facilitator.js"] ports: - "8402:8402" healthcheck: diff --git a/init-wallets.sh b/init-wallets.sh new file mode 100755 index 0000000..ce98a84 --- /dev/null +++ b/init-wallets.sh @@ -0,0 +1,29 @@ +#!/bin/sh +# Wait for wallet-headless to be ready +echo "Waiting for wallet-headless..." +until curl -sf http://wallet-headless:8000/wallet/status > /dev/null 2>&1; do + sleep 2 +done +echo "Wallet-headless is ready" + +# Start facilitator wallet +echo "Starting facilitator wallet..." +curl -s -X POST http://wallet-headless:8000/start \ + -H "Content-Type: application/json" \ + -d "{\"wallet-id\":\"facilitator\",\"seed\":\"$FACILITATOR_SEED\"}" +echo "" + +# Start seller wallet +echo "Starting seller wallet..." +curl -s -X POST http://wallet-headless:8000/start \ + -H "Content-Type: application/json" \ + -d "{\"wallet-id\":\"seller\",\"seed\":\"$SELLER_SEED\"}" +echo "" + +# Wait for wallets to sync +echo "Waiting for wallets to sync..." +sleep 10 +echo "Wallets initialized" + +# Start the actual service (passed as arguments) +exec "$@" From a6222d7476763a6c9b26023607961953e9dfc1ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Thu, 2 Apr 2026 16:37:20 -0300 Subject: [PATCH 17/37] fix: use HTTPS for fullnode URLs (mixed content blocked by browser) Co-Authored-By: Claude Opus 4.6 (1M context) --- dapp/Dockerfile | 2 +- dapp/lib/config.ts | 2 +- docker-compose.yml | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dapp/Dockerfile b/dapp/Dockerfile index 5d2fde2..b3ea3a9 100644 --- a/dapp/Dockerfile +++ b/dapp/Dockerfile @@ -20,7 +20,7 @@ ENV NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL:-/} # x402 build-time env vars (can be overridden at build time via --build-arg) ARG NEXT_PUBLIC_USE_MOCK_WALLET=false ARG NEXT_PUBLIC_DEFAULT_NETWORK=testnet -ARG NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET=http://node1.playground.testnet.hathor.network/v1a +ARG NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET=https://node1.playground.testnet.hathor.network/v1a ARG NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=8264fff563181da658ce64ee80e80458 ARG NEXT_PUBLIC_BLUEPRINT_ID ARG NEXT_PUBLIC_CHANNEL_BLUEPRINT_ID diff --git a/dapp/lib/config.ts b/dapp/lib/config.ts index b2ae7c9..62e92dd 100644 --- a/dapp/lib/config.ts +++ b/dapp/lib/config.ts @@ -4,7 +4,7 @@ export const config = { useMockWallet: process.env.NEXT_PUBLIC_USE_MOCK_WALLET === 'true', defaultNetwork: (process.env.NEXT_PUBLIC_DEFAULT_NETWORK || 'privatenet') as Network, hathorNodeUrls: { - 'privatenet': process.env.NEXT_PUBLIC_HATHOR_NODE_URL_PRIVATENET || 'http://127.0.0.1:49180/v1a', + 'privatenet': process.env.NEXT_PUBLIC_HATHOR_NODE_URL_PRIVATENET || 'https://node1.playground.testnet.hathor.network/v1a', 'testnet': process.env.NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET || 'https://node1.india.testnet.hathor.network/v1a', 'mainnet': process.env.NEXT_PUBLIC_HATHOR_NODE_URL_MAINNET || 'https://node1.mainnet.hathor.network/v1a', }, diff --git a/docker-compose.yml b/docker-compose.yml index 4e0eaf3..7a48561 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,7 +5,7 @@ services: HEADLESS_HTTP_BIND: "0.0.0.0" HEADLESS_HTTP_PORT: "8000" HEADLESS_NETWORK: testnet - HEADLESS_SERVER: http://node1.playground.testnet.hathor.network/v1a/ + HEADLESS_SERVER: https://node1.playground.testnet.hathor.network/v1a/ HEADLESS_SEED_DEFAULT: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" HEADLESS_ENABLED_PLUGINS: debug HEADLESS_TX_MINING_URL: https://txmining.playground.testnet.hathor.network/ @@ -20,7 +20,7 @@ services: facilitator: build: . environment: - FULLNODE_URL: http://node1.playground.testnet.hathor.network + FULLNODE_URL: https://node1.playground.testnet.hathor.network WALLET_HEADLESS_URL: http://wallet-headless:8000 BLUEPRINT_ID: ${BLUEPRINT_ID:-} CHANNEL_BLUEPRINT_ID: ${CHANNEL_BLUEPRINT_ID:-} @@ -45,7 +45,7 @@ services: resource-server: build: . environment: - FULLNODE_URL: http://node1.playground.testnet.hathor.network + FULLNODE_URL: https://node1.playground.testnet.hathor.network WALLET_HEADLESS_URL: http://wallet-headless:8000 BLUEPRINT_ID: ${BLUEPRINT_ID:-} CHANNEL_BLUEPRINT_ID: ${CHANNEL_BLUEPRINT_ID:-} From 02a4a3e1add1ad7d91a09aec08a1da4abdeedf04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Thu, 2 Apr 2026 22:43:53 -0300 Subject: [PATCH 18/37] fix: upgrade wallet-headless to v0.39.0-rc.1 v0.38.0 (latest) has incompatible nano contract validation with hathor-core v0.69.0. The RC version should match. Co-Authored-By: Claude Opus 4.6 (1M context) --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 7a48561..504ae0a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,6 @@ services: wallet-headless: - image: hathornetwork/hathor-wallet-headless:latest + image: hathornetwork/hathor-wallet-headless:v0.39.0-rc.1 environment: HEADLESS_HTTP_BIND: "0.0.0.0" HEADLESS_HTTP_PORT: "8000" From 3e7e7ec95e820965618695a8ef62f2a7cdf2cff9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Thu, 2 Apr 2026 22:46:53 -0300 Subject: [PATCH 19/37] revert: back to wallet-headless:latest Co-Authored-By: Claude Opus 4.6 (1M context) --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 504ae0a..7a48561 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,6 @@ services: wallet-headless: - image: hathornetwork/hathor-wallet-headless:v0.39.0-rc.1 + image: hathornetwork/hathor-wallet-headless:latest environment: HEADLESS_HTTP_BIND: "0.0.0.0" HEADLESS_HTTP_PORT: "8000" From 361beb490739613a1431fae9b184def22b67c837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Mon, 6 Apr 2026 12:08:45 -0300 Subject: [PATCH 20/37] fix: remove debug plugin from wallet-headless The debug plugin crashes on startup and may be causing NC execution failures. Local headless without it works fine. Co-Authored-By: Claude Opus 4.6 (1M context) --- docker-compose.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 7a48561..029578f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,7 +7,6 @@ services: HEADLESS_NETWORK: testnet HEADLESS_SERVER: https://node1.playground.testnet.hathor.network/v1a/ HEADLESS_SEED_DEFAULT: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" - HEADLESS_ENABLED_PLUGINS: debug HEADLESS_TX_MINING_URL: https://txmining.playground.testnet.hathor.network/ entrypoint: ["node", "dist/index.js"] healthcheck: From 821b459672a0f95f9cf727c393c24ef05e3493fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Mon, 6 Apr 2026 13:51:00 -0300 Subject: [PATCH 21/37] fix: force Docker to always pull latest wallet-headless image The Dokploy server had 0.36.0 cached as 'latest' while the actual latest on Docker Hub is 0.38.0. Add pull_policy: always. Co-Authored-By: Claude Opus 4.6 (1M context) --- docker-compose.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/docker-compose.yml b/docker-compose.yml index 029578f..e06a430 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,7 @@ services: wallet-headless: image: hathornetwork/hathor-wallet-headless:latest + pull_policy: always environment: HEADLESS_HTTP_BIND: "0.0.0.0" HEADLESS_HTTP_PORT: "8000" From 8b163342e16b132ff9cb56d2bddc9be281987459 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Mon, 6 Apr 2026 14:01:50 -0300 Subject: [PATCH 22/37] fix: settle async to avoid Traefik timeout on deployment Settlement takes 30-45s waiting for on-chain confirmation. Traefik times out before that. Serve resource immediately after verification, settle in background. Co-Authored-By: Claude Opus 4.6 (1M context) --- resource-server.js | 46 +++++++++++++++++++--------------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/resource-server.js b/resource-server.js index 7b33bd0..4941f15 100644 --- a/resource-server.js +++ b/resource-server.js @@ -115,31 +115,7 @@ app.get('/weather', x402Middleware, async (req, res) => { log('RESOURCE-SERVER', `Payment VALID`); - // Step 2: Settle BEFORE serving the resource - // For channels: spend() must confirm so on-chain state is updated before next request - // For escrow: release() must confirm so funds reach the seller - log('RESOURCE-SERVER', `Settling ${scheme} id=${id}`); - const settleBody = { paymentPayload: payment }; - if (isChannel) { - settleBody.amount = config.htrPaymentAmount; - settleBody.sellerAddress = config.sellerAddress; - } - - const settleResp = await fetch(`${config.facilitatorUrl}/x402/settle`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(settleBody), - }); - const settlement = await settleResp.json(); - - if (!settlement.success) { - log('RESOURCE-SERVER', `Settlement FAILED: ${settlement.error}`); - return res.status(500).json({ error: 'Settlement failed', reason: settlement.error }); - } - - log('RESOURCE-SERVER', `Settlement confirmed — txId=${settlement.txId}`); - - // Step 3: Serve the resource (only after settlement is confirmed) + // Step 2: Serve the resource first, then settle const weatherData = { location: 'Sao Paulo, Brazil', temperature: 28, @@ -150,16 +126,32 @@ app.get('/weather', x402Middleware, async (req, res) => { timestamp: new Date().toISOString(), }; + // Serve immediately res.json({ data: weatherData, payment: { success: true, scheme, - network: 'hathor:${config.network}', + network: `hathor:${config.network}`, id, - settleTxId: settlement.txId, }, }); + + // Settle async after response + log('RESOURCE-SERVER', `Settling ${scheme} id=${id} (async)`); + const settleBody = { paymentPayload: payment }; + if (isChannel) { + settleBody.amount = config.htrPaymentAmount; + settleBody.sellerAddress = config.sellerAddress; + } + fetch(`${config.facilitatorUrl}/x402/settle`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(settleBody), + }) + .then(r => r.json()) + .then(r => log('RESOURCE-SERVER', r.success ? `Settlement OK — ${r.txId}` : `Settlement FAILED: ${r.error}`)) + .catch(e => log('RESOURCE-SERVER', `Settlement error: ${e.message}`)); }); app.listen(config.resourceServerPort, () => { From 33cee783125c0a6119bb61e130a98f540740dff8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Mon, 6 Apr 2026 14:05:22 -0300 Subject: [PATCH 23/37] fix: don't wait for block confirmation on settlement MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The facilitator no longer waits for the release/spend tx to be confirmed in a block. The tx is accepted by the node (PoW mined), which is sufficient — it will confirm in the next block. This avoids the 30-45s timeout that was causing 502s through Traefik. The resource server still waits for the facilitator to respond (sync settlement), but the facilitator responds immediately after the tx is accepted, not after it's confirmed. Co-Authored-By: Claude Opus 4.6 (1M context) --- facilitator.js | 7 +++---- resource-server.js | 48 +++++++++++++++++++++++++++------------------- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/facilitator.js b/facilitator.js index be4056a..4a34bb6 100644 --- a/facilitator.js +++ b/facilitator.js @@ -58,8 +58,8 @@ async function settleEscrow(ncId) { }, config.facilitatorWalletId); if (!result.success) return { success: false, error: result.message || 'release() failed' }; - await waitForTxConfirmation(result.hash); - return { success: true, txId: result.hash, network: 'hathor:privatenet' }; + // Don't wait for block confirmation — tx is accepted by the node, it will confirm eventually + return { success: true, txId: result.hash, network: `hathor:${config.network || 'privatenet'}` }; } // ============================================================================ @@ -119,8 +119,7 @@ async function settleChannel(channelId, amount, sellerAddress) { }, config.facilitatorWalletId); if (!result.success) return { success: false, error: result.message || 'spend() failed' }; - await waitForTxConfirmation(result.hash); - return { success: true, txId: result.hash, network: 'hathor:privatenet' }; + return { success: true, txId: result.hash, network: `hathor:${config.network || 'privatenet'}` }; } // ============================================================================ diff --git a/resource-server.js b/resource-server.js index 4941f15..eb45433 100644 --- a/resource-server.js +++ b/resource-server.js @@ -33,7 +33,7 @@ function buildAcceptsList(path) { // Escrow option accepts.push({ scheme: 'hathor-escrow', - network: 'hathor:${config.network}', + network: `hathor:${config.network}`, resource: `${config.resourceServerPublicUrl}${path}`, mimeType: 'application/json', payTo: config.sellerAddress, @@ -48,7 +48,7 @@ function buildAcceptsList(path) { if (config.channelBlueprintId) { accepts.push({ scheme: 'hathor-channel', - network: 'hathor:${config.network}', + network: `hathor:${config.network}`, resource: `${config.resourceServerPublicUrl}${path}`, mimeType: 'application/json', payTo: config.sellerAddress, @@ -115,7 +115,31 @@ app.get('/weather', x402Middleware, async (req, res) => { log('RESOURCE-SERVER', `Payment VALID`); - // Step 2: Serve the resource first, then settle + // Step 2: Settle BEFORE serving the resource + // For channels: spend() must confirm so on-chain state is updated before next request + // For escrow: release() must confirm so funds reach the seller + log('RESOURCE-SERVER', `Settling ${scheme} id=${id}`); + const settleBody = { paymentPayload: payment }; + if (isChannel) { + settleBody.amount = config.htrPaymentAmount; + settleBody.sellerAddress = config.sellerAddress; + } + + const settleResp = await fetch(`${config.facilitatorUrl}/x402/settle`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(settleBody), + }); + const settlement = await settleResp.json(); + + if (!settlement.success) { + log('RESOURCE-SERVER', `Settlement FAILED: ${settlement.error}`); + return res.status(500).json({ error: 'Settlement failed', reason: settlement.error }); + } + + log('RESOURCE-SERVER', `Settlement confirmed — txId=${settlement.txId}`); + + // Step 3: Serve the resource (only after settlement is confirmed) const weatherData = { location: 'Sao Paulo, Brazil', temperature: 28, @@ -126,7 +150,6 @@ app.get('/weather', x402Middleware, async (req, res) => { timestamp: new Date().toISOString(), }; - // Serve immediately res.json({ data: weatherData, payment: { @@ -134,24 +157,9 @@ app.get('/weather', x402Middleware, async (req, res) => { scheme, network: `hathor:${config.network}`, id, + settleTxId: settlement.txId, }, }); - - // Settle async after response - log('RESOURCE-SERVER', `Settling ${scheme} id=${id} (async)`); - const settleBody = { paymentPayload: payment }; - if (isChannel) { - settleBody.amount = config.htrPaymentAmount; - settleBody.sellerAddress = config.sellerAddress; - } - fetch(`${config.facilitatorUrl}/x402/settle`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(settleBody), - }) - .then(r => r.json()) - .then(r => log('RESOURCE-SERVER', r.success ? `Settlement OK — ${r.txId}` : `Settlement FAILED: ${r.error}`)) - .catch(e => log('RESOURCE-SERVER', `Settlement error: ${e.message}`)); }); app.listen(config.resourceServerPort, () => { From 461da83b8207d1432abf3ad5c893f75bb30b06a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Tue, 7 Apr 2026 09:44:36 -0300 Subject: [PATCH 24/37] feat: align with x402 V2 spec and add production stability Implements issues #2-#5, #7-#8, #12-#13: - Use PAYMENT-SIGNATURE header (Base64) with X-Payment fallback (#2) - Add PAYMENT-RESPONSE header on 200 responses (#3) - Add x402Version: 2 to all protocol messages (#4) - Use config.network consistently for CAIP-2 identifiers (#5) - Rename 'amount' to 'price' in 402 accepts array (#7) - Add settlement cache for Payment-Identifier idempotency (#8) - Add /health endpoint with wallet connectivity check (#12) - Add wallet auto-recovery (periodic check + restart) (#12) - Add MCP server POC example in examples/mcp-server/ (#13) Co-Authored-By: Claude Opus 4.6 --- client.js | 11 +- dapp/components/X402Fetch.tsx | 23 ++-- docker-compose.yml | 2 +- examples/mcp-server/README.md | 66 +++++++++ examples/mcp-server/package.json | 17 +++ examples/mcp-server/server.js | 226 +++++++++++++++++++++++++++++++ facilitator.js | 127 ++++++++++++++--- resource-server.js | 40 ++++-- 8 files changed, 462 insertions(+), 50 deletions(-) create mode 100644 examples/mcp-server/README.md create mode 100644 examples/mcp-server/package.json create mode 100644 examples/mcp-server/server.js diff --git a/client.js b/client.js index a73dd9a..0915341 100644 --- a/client.js +++ b/client.js @@ -51,7 +51,7 @@ async function main() { log('CLIENT', `Got 402 Payment Required`); log('CLIENT', ` ${paymentRequired.accepts.length} payment option(s) available:`); for (const opt of paymentRequired.accepts) { - log('CLIENT', ` - ${opt.description} (asset: ${opt.asset}, amount: ${opt.amount})`); + log('CLIENT', ` - ${opt.description} (asset: ${opt.asset}, price: ${opt.price})`); } log('CLIENT', ''); @@ -59,7 +59,7 @@ async function main() { const chosen = pickPaymentOption(paymentRequired.accepts); log('CLIENT', `Step 2: Chose payment option: ${chosen.description}`); log('CLIENT', ` Asset: ${chosen.asset}`); - log('CLIENT', ` Amount: ${chosen.amount}`); + log('CLIENT', ` Price: ${chosen.price}`); log('CLIENT', ` Pay to: ${chosen.payTo}`); log('CLIENT', ` Facilitator: ${chosen.extra.facilitatorAddress}`); log('CLIENT', ''); @@ -68,7 +68,7 @@ async function main() { log('CLIENT', 'Step 3: Creating escrow nano contract...'); const deadline = Math.floor(Date.now() / 1000) + chosen.extra.deadlineSeconds; - const amount = parseInt(chosen.amount); + const amount = parseInt(chosen.price); const createResult = await walletRequest('POST', '/wallet/nano-contracts/create', { blueprint_id: chosen.extra.blueprintId, @@ -107,8 +107,9 @@ async function main() { log('CLIENT', 'Step 4: Retrying request with payment proof...'); const paymentPayload = { + x402Version: 2, scheme: 'hathor-escrow', - network: 'hathor:privatenet', + network: `hathor:${config.network}`, payload: { ncId: ncId, depositTxId: ncId, @@ -118,7 +119,7 @@ async function main() { const paidResp = await fetch(`http://localhost:${config.resourceServerPort}/weather`, { headers: { - 'X-Payment': JSON.stringify(paymentPayload), + 'PAYMENT-SIGNATURE': Buffer.from(JSON.stringify(paymentPayload)).toString('base64'), }, }); diff --git a/dapp/components/X402Fetch.tsx b/dapp/components/X402Fetch.tsx index 3b6d900..67f6829 100644 --- a/dapp/components/X402Fetch.tsx +++ b/dapp/components/X402Fetch.tsx @@ -11,7 +11,7 @@ interface PaymentOption { scheme: string; network: string; asset: string; - amount: string; + price: string; description: string; resource: string; payTo: string; @@ -80,12 +80,13 @@ export function X402Fetch() { // Try to pay with an existing channel (instant — no wallet interaction) const payWithChannel = async (channelId: string): Promise => { const paymentPayload = { + x402Version: 2, scheme: 'hathor-channel', network: `hathor:${network}`, payload: { channelId, buyerAddress: address }, }; - const resp = await fetch(url, { mode: 'cors', headers: { 'X-Payment': JSON.stringify(paymentPayload) } }); + const resp = await fetch(url, { mode: 'cors', headers: { 'PAYMENT-SIGNATURE': btoa(JSON.stringify(paymentPayload)) } }); if (!resp.ok) return false; const data = await resp.json(); @@ -154,7 +155,7 @@ export function X402Fetch() { if (isChannel) { // Create a new channel with 10x the per-request amount const deadline = Math.floor(Date.now() / 1000) + 3600; - const deposit = parseInt(opt.amount) * 10; + const deposit = parseInt(opt.price) * 10; toast.info('Confirm the channel deposit in your wallet...'); const result = await sendNanoContractTx({ @@ -176,7 +177,7 @@ export function X402Fetch() { const result = await sendNanoContractTx({ network, blueprint_id: opt.extra.blueprintId, method: 'initialize', args: [opt.payTo, opt.extra.facilitatorAddress, opt.asset, deadline, opt.resource, 'dapp-x402'], - actions: [{ type: 'deposit', amount: opt.amount, token: opt.asset }], + actions: [{ type: 'deposit', amount: opt.price, token: opt.asset }], push_tx: true, }); id = result?.response?.hash || result?.hash || result?.response?.response?.hash; @@ -194,10 +195,10 @@ export function X402Fetch() { // Retry with payment proof setStep('retrying'); const paymentPayload = isChannel - ? { scheme: 'hathor-channel', network: `hathor:${network}`, payload: { channelId: id, buyerAddress: address } } - : { scheme: 'hathor-escrow', network: `hathor:${network}`, payload: { ncId: id, depositTxId: id, buyerAddress: address } }; + ? { x402Version: 2, scheme: 'hathor-channel', network: `hathor:${network}`, payload: { channelId: id, buyerAddress: address } } + : { x402Version: 2, scheme: 'hathor-escrow', network: `hathor:${network}`, payload: { ncId: id, depositTxId: id, buyerAddress: address } }; - const paidResp = await fetch(url, { mode: 'cors', headers: { 'X-Payment': JSON.stringify(paymentPayload) } }); + const paidResp = await fetch(url, { mode: 'cors', headers: { 'PAYMENT-SIGNATURE': btoa(JSON.stringify(paymentPayload)) } }); if (!paidResp.ok) { const errBody = await paidResp.json().catch(() => ({})); throw new Error(errBody.reason || errBody.error || `Rejected: ${paidResp.status}`); @@ -207,7 +208,7 @@ export function X402Fetch() { setResourceData(data); setStep('done'); toast.success('Resource received!'); - addToHistory(opt.scheme, id, opt.amount); + addToHistory(opt.scheme, id, opt.price); refreshBalance('00', network); } catch (err: any) { setError(err.message); @@ -229,7 +230,7 @@ export function X402Fetch() { throw new Error('Confirmation timeout (60s)'); }; - const amountDisplay = selectedOption ? `${(parseInt(selectedOption.amount) / 100).toFixed(2)} HTR` : ''; + const amountDisplay = selectedOption ? `${(parseInt(selectedOption.price) / 100).toFixed(2)} HTR` : ''; const isChannel = selectedOption?.scheme === 'hathor-channel'; return ( @@ -320,7 +321,7 @@ export function X402Fetch() { {isChannel && (
Channel deposit (10 requests) - {(parseInt(selectedOption.amount) * 10 / 100).toFixed(2)} HTR + {(parseInt(selectedOption.price) * 10 / 100).toFixed(2)} HTR
)}
@@ -340,7 +341,7 @@ export function X402Fetch() { className="flex-1 px-6 py-3 rounded-lg font-medium transition-colors disabled:opacity-50" style={{ background: isConnected ? 'linear-gradient(244deg, rgb(255, 166, 0) 0%, rgb(255, 115, 0) 100%)' : '#475569', color: '#0f172a' }}> {!isConnected ? 'Connect Wallet First' - : isChannel ? `Open Channel (${(parseInt(selectedOption.amount) * 10 / 100).toFixed(2)} HTR)` + : isChannel ? `Open Channel (${(parseInt(selectedOption.price) * 10 / 100).toFixed(2)} HTR)` : `Pay ${amountDisplay}`} diff --git a/docker-compose.yml b/docker-compose.yml index e06a430..93cf9ce 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -33,7 +33,7 @@ services: ports: - "8402:8402" healthcheck: - test: ["CMD", "node", "-e", "require('http').get('http://localhost:8402/x402/verify',r=>{process.exit(r.statusCode<500?0:1)}).on('error',()=>process.exit(1))"] + test: ["CMD", "curl", "-f", "http://localhost:8402/health"] interval: 10s timeout: 5s retries: 3 diff --git a/examples/mcp-server/README.md b/examples/mcp-server/README.md new file mode 100644 index 0000000..f10a095 --- /dev/null +++ b/examples/mcp-server/README.md @@ -0,0 +1,66 @@ +# x402 Payment-Gated MCP Server + +A minimal example of an MCP server with payment-gated tools using x402 on Hathor Network. + +## What this demonstrates + +- **`get_weather`** tool: Costs 1.00 HTR per call via hathor-escrow +- **`get_price`** tool: Free — returns pricing info for any tool + +When an AI agent calls `get_weather` without payment, it receives a 402-style response with Hathor escrow payment requirements. The agent creates an escrow, includes the payment proof, and gets the data. + +## Setup + +```bash +cd examples/mcp-server +npm install +``` + +## Running + +```bash +FACILITATOR_URL=https://facilitator.x402.hathor.dev \ +SELLER_ADDRESS=WZe3ty22... \ +FACILITATOR_ADDRESS=Wb6eLTZS... \ +BLUEPRINT_ID=0000121e... \ +node server.js +``` + +## Using with Claude Code + +Add to your Claude Code MCP config (`~/.claude/claude_desktop_config.json`): + +```json +{ + "mcpServers": { + "x402-weather": { + "command": "node", + "args": ["/path/to/examples/mcp-server/server.js"], + "env": { + "FACILITATOR_URL": "https://facilitator.x402.hathor.dev", + "SELLER_ADDRESS": "WZe3ty22...", + "FACILITATOR_ADDRESS": "Wb6eLTZS...", + "BLUEPRINT_ID": "0000121e..." + } + } + } +} +``` + +## Payment flow + +``` +Agent MCP Server Facilitator Hathor + | | | | + |-- get_weather(city) ---->| | | + |<---- 402 + accepts[] ----| | | + | | | | + |-- create escrow ---------|------------------------|----deposit---->| + | | | | + |-- get_weather(city, ---->| | | + | payment=proof) |-- verify ------------->| | + | |<--- valid: true -------| | + | |-- settle ------------->|--release()---->| + | |<--- txId --------------| | + |<---- weather data -------| | | +``` diff --git a/examples/mcp-server/package.json b/examples/mcp-server/package.json new file mode 100644 index 0000000..9531096 --- /dev/null +++ b/examples/mcp-server/package.json @@ -0,0 +1,17 @@ +{ + "name": "x402-mcp-server-example", + "version": "0.1.0", + "description": "Example MCP server with x402 payment-gated tools on Hathor Network", + "license": "MIT", + "type": "module", + "scripts": { + "start": "node server.js" + }, + "dependencies": { + "@modelcontextprotocol/sdk": "^1.12.1", + "node-fetch": "^3.3.2" + }, + "engines": { + "node": ">=18" + } +} diff --git a/examples/mcp-server/server.js b/examples/mcp-server/server.js new file mode 100644 index 0000000..62b1cc7 --- /dev/null +++ b/examples/mcp-server/server.js @@ -0,0 +1,226 @@ +#!/usr/bin/env node + +// x402 Payment-Gated MCP Server Example +// +// Demonstrates how to build an MCP server where tool calls require x402 payment +// on Hathor Network. AI agents (Claude Code, etc.) can discover and pay for tools. +// +// Flow: +// 1. Agent calls a tool (e.g., get_weather) +// 2. Server returns a 402-style error with payment requirements +// 3. Agent creates an escrow on Hathor, sends payment proof +// 4. Server verifies + settles via the facilitator, returns data +// +// Usage: +// FACILITATOR_URL=https://facilitator.x402.hathor.dev \ +// SELLER_ADDRESS=WZe3... \ +// BLUEPRINT_ID=0000121e... \ +// node server.js + +import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; +import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; +import { z } from 'zod'; + +// --------------------------------------------------------------------------- +// Configuration +// --------------------------------------------------------------------------- + +const config = { + facilitatorUrl: process.env.FACILITATOR_URL || 'https://facilitator.x402.hathor.dev', + facilitatorAddress: process.env.FACILITATOR_ADDRESS || '', + sellerAddress: process.env.SELLER_ADDRESS || '', + blueprintId: process.env.BLUEPRINT_ID || '', + network: process.env.HATHOR_NETWORK || 'testnet', + htrTokenUid: '00', + pricePerCall: 100, // 1.00 HTR in smallest units + deadlineSeconds: 300, +}; + +// --------------------------------------------------------------------------- +// x402 helpers +// --------------------------------------------------------------------------- + +function buildPaymentRequired(toolName) { + return { + x402Version: 2, + accepts: [ + { + scheme: 'hathor-escrow', + network: `hathor:${config.network}`, + resource: `mcp://x402-mcp-server/tool/${toolName}`, + mimeType: 'application/json', + payTo: config.sellerAddress, + maxTimeoutSeconds: config.deadlineSeconds, + asset: config.htrTokenUid, + price: String(config.pricePerCall), + description: `Pay ${(config.pricePerCall / 100).toFixed(2)} HTR for ${toolName}`, + extra: { + facilitatorUrl: config.facilitatorUrl, + facilitatorAddress: config.facilitatorAddress, + blueprintId: config.blueprintId, + deadlineSeconds: config.deadlineSeconds, + }, + }, + ], + }; +} + +async function verifyAndSettle(paymentProof) { + const paymentPayload = typeof paymentProof === 'string' + ? JSON.parse(Buffer.from(paymentProof, 'base64').toString('utf-8')) + : paymentProof; + + // Verify + const verifyResp = await fetch(`${config.facilitatorUrl}/x402/verify`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + paymentPayload, + paymentRequirements: [{ + scheme: 'hathor-escrow', + network: `hathor:${config.network}`, + maxAmountRequired: String(config.pricePerCall), + payTo: config.sellerAddress, + asset: config.htrTokenUid, + }], + }), + }); + const verification = await verifyResp.json(); + if (!verification.valid) { + throw new Error(`Payment invalid: ${verification.invalidReason}`); + } + + // Settle + const settleResp = await fetch(`${config.facilitatorUrl}/x402/settle`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ paymentPayload }), + }); + const settlement = await settleResp.json(); + if (!settlement.success) { + throw new Error(`Settlement failed: ${settlement.error}`); + } + + return settlement; +} + +// --------------------------------------------------------------------------- +// MCP Server +// --------------------------------------------------------------------------- + +const server = new McpServer({ + name: 'x402-weather', + version: '0.1.0', +}); + +// Paid tool: get_weather +server.tool( + 'get_weather', + 'Get current weather for a city. Costs 1.00 HTR per call via x402 payment.', + { + city: z.string().describe('City name (e.g., "Sao Paulo")'), + payment: z.string().optional().describe('Base64-encoded x402 PAYMENT-SIGNATURE (hathor-escrow proof)'), + }, + async ({ city, payment }) => { + // No payment? Return 402-style payment requirements + if (!payment) { + const requirements = buildPaymentRequired('get_weather'); + return { + content: [ + { + type: 'text', + text: JSON.stringify({ + error: 'payment_required', + status: 402, + message: `This tool costs ${(config.pricePerCall / 100).toFixed(2)} HTR per call. Include a "payment" parameter with your x402 payment proof.`, + ...requirements, + }, null, 2), + }, + ], + isError: true, + }; + } + + // Verify and settle payment + let settlement; + try { + settlement = await verifyAndSettle(payment); + } catch (err) { + return { + content: [{ type: 'text', text: JSON.stringify({ error: 'payment_failed', message: err.message }) }], + isError: true, + }; + } + + // Payment confirmed — return the weather data + const weatherData = { + city, + temperature: Math.round(20 + Math.random() * 15), + humidity: Math.round(40 + Math.random() * 40), + condition: ['Sunny', 'Partly cloudy', 'Cloudy', 'Light rain'][Math.floor(Math.random() * 4)], + wind: `${Math.round(5 + Math.random() * 20)} km/h`, + timestamp: new Date().toISOString(), + }; + + return { + content: [ + { + type: 'text', + text: JSON.stringify({ + data: weatherData, + payment: { + x402Version: 2, + success: true, + scheme: 'hathor-escrow', + network: `hathor:${config.network}`, + settleTxId: settlement.txId, + }, + }, null, 2), + }, + ], + }; + }, +); + +// Free tool: get_price (shows how to mix free and paid tools) +server.tool( + 'get_price', + 'Get the current x402 price for a tool call. Free — no payment needed.', + { + tool_name: z.string().describe('Name of the tool to check pricing for'), + }, + async ({ tool_name }) => { + const requirements = buildPaymentRequired(tool_name); + return { + content: [ + { + type: 'text', + text: JSON.stringify({ + tool: tool_name, + price: `${(config.pricePerCall / 100).toFixed(2)} HTR`, + network: `hathor:${config.network}`, + paymentInfo: requirements, + }, null, 2), + }, + ], + }; + }, +); + +// --------------------------------------------------------------------------- +// Start +// --------------------------------------------------------------------------- + +async function main() { + const transport = new StdioServerTransport(); + await server.connect(transport); + console.error('[x402-mcp-server] Running on stdio'); + console.error(`[x402-mcp-server] Seller: ${config.sellerAddress}`); + console.error(`[x402-mcp-server] Facilitator: ${config.facilitatorUrl}`); + console.error(`[x402-mcp-server] Price per call: ${(config.pricePerCall / 100).toFixed(2)} HTR`); +} + +main().catch(err => { + console.error(`[x402-mcp-server] Fatal: ${err.message}`); + process.exit(1); +}); diff --git a/facilitator.js b/facilitator.js index 4a34bb6..3ec697d 100644 --- a/facilitator.js +++ b/facilitator.js @@ -10,6 +10,12 @@ const { walletRequest, getNanoContractState, waitForTxConfirmation, log } = requ const app = express(); app.use(express.json()); +// ============================================================================ +// Settlement cache for Payment-Identifier idempotency (#8) +// Key: ncId or channelId+amount, Value: settlement result +// ============================================================================ +const settlementCache = new Map(); + // ============================================================================ // ESCROW verification/settlement (one contract per payment) // ============================================================================ @@ -26,24 +32,24 @@ function validateEscrowAgainstRequirement(fields, req) { async function verifyEscrow(ncId, requirements) { const stateResp = await getNanoContractState(ncId); - if (!stateResp.success) return { valid: false, invalidReason: `Cannot query contract: ${stateResp.message}` }; + if (!stateResp.success) return { x402Version: 2, valid: false, invalidReason: `Cannot query contract: ${stateResp.message}` }; const reqs = Array.isArray(requirements) ? requirements : [requirements]; let lastErrors = []; for (const req of reqs) { const errors = validateEscrowAgainstRequirement(stateResp.fields, req); - if (errors.length === 0) return { valid: true }; + if (errors.length === 0) return { x402Version: 2, valid: true }; lastErrors = errors; } - return { valid: false, invalidReason: lastErrors.join('; ') }; + return { x402Version: 2, valid: false, invalidReason: lastErrors.join('; ') }; } async function settleEscrow(ncId) { const stateResp = await getNanoContractState(ncId); - if (!stateResp.success) return { success: false, error: `Cannot query contract` }; + if (!stateResp.success) return { x402Version: 2, success: false, error: `Cannot query contract` }; const fields = stateResp.fields; - if (fields.phase.value !== 'LOCKED') return { success: false, error: `Escrow not locked (phase=${fields.phase.value})` }; + if (fields.phase.value !== 'LOCKED') return { x402Version: 2, success: false, error: `Escrow not locked (phase=${fields.phase.value})` }; const amount = fields.amount.value; const seller = fields.seller.value; @@ -57,9 +63,9 @@ async function settleEscrow(ncId) { data: { args: [], actions: [{ type: 'withdrawal', token: tokenUid, amount, address: seller }] }, }, config.facilitatorWalletId); - if (!result.success) return { success: false, error: result.message || 'release() failed' }; + if (!result.success) return { x402Version: 2, success: false, error: result.message || 'release() failed' }; // Don't wait for block confirmation — tx is accepted by the node, it will confirm eventually - return { success: true, txId: result.hash, network: `hathor:${config.network || 'privatenet'}` }; + return { x402Version: 2, success: true, txId: result.hash, network: `hathor:${config.network || 'privatenet'}` }; } // ============================================================================ @@ -77,35 +83,35 @@ async function getChannelState(channelId) { async function verifyChannel(channelId, requirements) { const stateResp = await getChannelState(channelId); - if (!stateResp.success) return { valid: false, invalidReason: `Cannot query channel: ${stateResp.message}` }; + if (!stateResp.success) return { x402Version: 2, valid: false, invalidReason: `Cannot query channel: ${stateResp.message}` }; const fields = stateResp.fields; - if (fields.phase.value !== 'OPEN') return { valid: false, invalidReason: `Channel not open (phase=${fields.phase.value})` }; - if (fields.facilitator.value !== config.facilitatorAddress) return { valid: false, invalidReason: 'Facilitator mismatch' }; + if (fields.phase.value !== 'OPEN') return { x402Version: 2, valid: false, invalidReason: `Channel not open (phase=${fields.phase.value})` }; + if (fields.facilitator.value !== config.facilitatorAddress) return { x402Version: 2, valid: false, invalidReason: 'Facilitator mismatch' }; const remaining = fields.total_deposited.value - fields.total_spent.value; const reqs = Array.isArray(requirements) ? requirements : [requirements]; for (const req of reqs) { - const amount = parseInt(req.maxAmountRequired || req.amount); + const amount = parseInt(req.maxAmountRequired || req.price || req.amount); if (remaining >= amount) { if (req.asset && fields.token_uid.value !== req.asset) continue; - return { valid: true, remaining }; + return { x402Version: 2, valid: true, remaining }; } } - return { valid: false, invalidReason: `Insufficient channel balance (remaining: ${remaining})` }; + return { x402Version: 2, valid: false, invalidReason: `Insufficient channel balance (remaining: ${remaining})` }; } async function settleChannel(channelId, amount, sellerAddress) { const stateResp = await getChannelState(channelId); - if (!stateResp.success) return { success: false, error: 'Cannot query channel' }; + if (!stateResp.success) return { x402Version: 2, success: false, error: 'Cannot query channel' }; const fields = stateResp.fields; - if (fields.phase.value !== 'OPEN') return { success: false, error: 'Channel not open' }; + if (fields.phase.value !== 'OPEN') return { x402Version: 2, success: false, error: 'Channel not open' }; const tokenUid = fields.token_uid.value; const remaining = fields.total_deposited.value - fields.total_spent.value; - if (remaining < amount) return { success: false, error: `Insufficient balance (${remaining} < ${amount})` }; + if (remaining < amount) return { x402Version: 2, success: false, error: `Insufficient balance (${remaining} < ${amount})` }; log('FACILITATOR', `Channel spend() — ${amount} of ${tokenUid} to ${sellerAddress}`); const result = await walletRequest('POST', '/wallet/nano-contracts/execute', { @@ -118,8 +124,8 @@ async function settleChannel(channelId, amount, sellerAddress) { }, }, config.facilitatorWalletId); - if (!result.success) return { success: false, error: result.message || 'spend() failed' }; - return { success: true, txId: result.hash, network: `hathor:${config.network || 'privatenet'}` }; + if (!result.success) return { x402Version: 2, success: false, error: result.message || 'spend() failed' }; + return { x402Version: 2, success: true, txId: result.hash, network: `hathor:${config.network || 'privatenet'}` }; } // ============================================================================ @@ -154,23 +160,108 @@ app.post('/x402/settle', async (req, res) => { const { channelId } = paymentPayload.payload; const amount = req.body.amount || paymentPayload.payload.amount; const sellerAddress = req.body.sellerAddress || paymentPayload.payload.sellerAddress; + const cacheKey = `channel:${channelId}:${amount}`; + + // Idempotency: return cached result if already settled with same params + if (settlementCache.has(cacheKey)) { + log('FACILITATOR', `Channel settle CACHED for channelId=${channelId}`); + return res.json(settlementCache.get(cacheKey)); + } + log('FACILITATOR', `Channel settle for channelId=${channelId}, amount=${amount}`); const result = await settleChannel(channelId, amount, sellerAddress); log('FACILITATOR', `Channel settle ${result.success ? 'SUCCESS' : 'FAILED'}: ${result.txId || result.error}`); + if (result.success) settlementCache.set(cacheKey, result); return res.json(result); } // Default: escrow const { ncId } = paymentPayload.payload; + const cacheKey = `escrow:${ncId}`; + + // Idempotency: return cached result if already settled + if (settlementCache.has(cacheKey)) { + log('FACILITATOR', `Escrow settle CACHED for ncId=${ncId}`); + return res.json(settlementCache.get(cacheKey)); + } + log('FACILITATOR', `Escrow settle for ncId=${ncId}`); const result = await settleEscrow(ncId); log('FACILITATOR', `Escrow settle ${result.success ? 'SUCCESS' : 'FAILED'}: ${result.txId || result.error}`); + if (result.success) settlementCache.set(cacheKey, result); res.json(result); }); +// ============================================================================ +// Health check & wallet auto-recovery (#12) +// ============================================================================ + +async function checkWalletStatus(walletId) { + try { + const result = await walletRequest('GET', '/wallet/status', null, walletId); + return result.statusCode === 3; // 3 = READY + } catch { + return false; + } +} + +async function restartWallet(walletId, seed) { + try { + log('FACILITATOR', `Restarting wallet: ${walletId}`); + // Stop first (ignore errors if not started) + await walletRequest('POST', '/wallet/stop', {}, walletId).catch(() => {}); + // Start with seed + const result = await require('node-fetch')(`${config.walletHeadlessUrl}/start`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ 'wallet-id': walletId, seed }), + }).then(r => r.json()); + log('FACILITATOR', `Wallet ${walletId} restart result: ${JSON.stringify(result)}`); + return result.success !== false; + } catch (err) { + log('FACILITATOR', `Wallet ${walletId} restart failed: ${err.message}`); + return false; + } +} + +async function ensureWalletsReady() { + const facilitatorOk = await checkWalletStatus(config.facilitatorWalletId); + const sellerOk = await checkWalletStatus(config.sellerWalletId); + + if (!facilitatorOk && process.env.FACILITATOR_SEED) { + await restartWallet(config.facilitatorWalletId, process.env.FACILITATOR_SEED); + } + if (!sellerOk && process.env.SELLER_SEED) { + await restartWallet(config.sellerWalletId, process.env.SELLER_SEED); + } +} + +// Periodic wallet health check (every 30 seconds) +setInterval(() => { + ensureWalletsReady().catch(err => log('FACILITATOR', `Wallet check error: ${err.message}`)); +}, 30000); + +app.get('/health', async (req, res) => { + const facilitatorOk = await checkWalletStatus(config.facilitatorWalletId); + const sellerOk = await checkWalletStatus(config.sellerWalletId); + const healthy = facilitatorOk && sellerOk; + + res.status(healthy ? 200 : 503).json({ + status: healthy ? 'healthy' : 'degraded', + wallets: { + facilitator: facilitatorOk ? 'ready' : 'disconnected', + seller: sellerOk ? 'ready' : 'disconnected', + }, + settlementCacheSize: settlementCache.size, + uptime: process.uptime(), + }); +}); + app.listen(config.facilitatorPort, () => { log('FACILITATOR', `x402 Facilitator running on port ${config.facilitatorPort}`); log('FACILITATOR', `Facilitator address: ${config.facilitatorAddress}`); log('FACILITATOR', `Escrow blueprint: ${config.blueprintId}`); log('FACILITATOR', `Channel blueprint: ${config.channelBlueprintId}`); + // Initial wallet check on startup + ensureWalletsReady().catch(err => log('FACILITATOR', `Initial wallet check error: ${err.message}`)); }); diff --git a/resource-server.js b/resource-server.js index eb45433..1af1fd3 100644 --- a/resource-server.js +++ b/resource-server.js @@ -14,8 +14,8 @@ app.use(express.json()); // CORS — allow browser dApps to call this server app.use((req, res, next) => { res.header('Access-Control-Allow-Origin', '*'); - res.header('Access-Control-Allow-Headers', 'Content-Type, X-Payment'); - res.header('Access-Control-Expose-Headers', 'X-Payment-Response'); + res.header('Access-Control-Allow-Headers', 'Content-Type, PAYMENT-SIGNATURE, X-Payment'); + res.header('Access-Control-Expose-Headers', 'PAYMENT-RESPONSE, X-Payment-Response'); if (req.method === 'OPTIONS') return res.sendStatus(204); next(); }); @@ -39,7 +39,7 @@ function buildAcceptsList(path) { payTo: config.sellerAddress, maxTimeoutSeconds: config.escrowDeadlineSeconds, asset: config.htrTokenUid, - amount: String(config.htrPaymentAmount), + price: String(config.htrPaymentAmount), description: `Pay ${(config.htrPaymentAmount / 100).toFixed(2)} HTR (single escrow)`, extra: { ...baseExtra, blueprintId: config.blueprintId }, }); @@ -54,7 +54,7 @@ function buildAcceptsList(path) { payTo: config.sellerAddress, maxTimeoutSeconds: config.escrowDeadlineSeconds, asset: config.htrTokenUid, - amount: String(config.htrPaymentAmount), + price: String(config.htrPaymentAmount), description: `Pay ${(config.htrPaymentAmount / 100).toFixed(2)} HTR via channel (saves escrow creation)`, extra: { ...baseExtra, channelBlueprintId: config.channelBlueprintId }, }); @@ -65,17 +65,22 @@ function buildAcceptsList(path) { // x402 middleware — checks for payment, returns 402 if none function x402Middleware(req, res, next) { - const paymentHeader = req.headers['x-payment']; + // x402 V2: PAYMENT-SIGNATURE (Base64-encoded JSON), fallback to X-Payment (raw JSON) for backward compat + const signatureHeader = req.headers['payment-signature']; + const legacyHeader = req.headers['x-payment']; - if (!paymentHeader) { + if (!signatureHeader && !legacyHeader) { log('RESOURCE-SERVER', `402 — No payment for ${req.path}`); return res.status(402).json({ + x402Version: 2, accepts: buildAcceptsList(req.path), version: '1', }); } - const payment = JSON.parse(paymentHeader); + const payment = signatureHeader + ? JSON.parse(Buffer.from(signatureHeader, 'base64').toString('utf-8')) + : JSON.parse(legacyHeader); req.x402Payment = payment; next(); } @@ -84,7 +89,7 @@ function buildPaymentRequirements(path) { return buildAcceptsList(path).map(opt => ({ scheme: opt.scheme, network: opt.network, - maxAmountRequired: opt.amount, + maxAmountRequired: opt.price, payTo: opt.payTo, asset: opt.asset, })); @@ -150,15 +155,20 @@ app.get('/weather', x402Middleware, async (req, res) => { timestamp: new Date().toISOString(), }; + // x402 V2: PAYMENT-RESPONSE header with Base64-encoded settlement result + const paymentResponse = { + x402Version: 2, + success: true, + scheme, + network: `hathor:${config.network}`, + ...(isChannel ? { channelId: id } : { ncId: id }), + settleTxId: settlement.txId, + }; + res.set('PAYMENT-RESPONSE', Buffer.from(JSON.stringify(paymentResponse)).toString('base64')); + res.json({ data: weatherData, - payment: { - success: true, - scheme, - network: `hathor:${config.network}`, - id, - settleTxId: settlement.txId, - }, + payment: paymentResponse, }); }); From b8cb857ed421102d05f4b9109ac3b029d4cf6c9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Tue, 7 Apr 2026 11:11:36 -0300 Subject: [PATCH 25/37] fix: add detailed RPC error logging for balance fetch debugging Log full error object (message, code, data, raw) on RPC failures and log successful responses to help diagnose WalletConnect relay issues. Co-Authored-By: Claude Opus 4.6 --- .gitignore | 1 + dapp/contexts/WalletContext.tsx | 7 ++++++- dapp/lib/hathorRPC.ts | 19 +++++++++++++++++-- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 8a433ab..484ef6e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ node_modules/ *.log .env +.deploy .DS_Store diff --git a/dapp/contexts/WalletContext.tsx b/dapp/contexts/WalletContext.tsx index 216e4dc..8e275b7 100644 --- a/dapp/contexts/WalletContext.tsx +++ b/dapp/contexts/WalletContext.tsx @@ -128,7 +128,12 @@ export function WalletProvider({ children }: { children: ReactNode }) { setBalanceVerified(true); saveCachedBalance(addr, balanceValue); } catch (error: any) { - console.log('Balance fetch was rejected or failed:', error); + console.error('Balance fetch failed:', { + message: error?.message, + code: error?.code, + data: error?.data, + raw: error, + }); setBalance(0n); setBalanceVerified(false); } finally { diff --git a/dapp/lib/hathorRPC.ts b/dapp/lib/hathorRPC.ts index ecbcab5..7723c4b 100644 --- a/dapp/lib/hathorRPC.ts +++ b/dapp/lib/hathorRPC.ts @@ -42,9 +42,16 @@ export class HathorRPCService { if (this.customRequest) { try { const result = await this.customRequest(method, params); + console.log(`RPC [${method}] response:`, JSON.stringify(result, null, 2)); return result; } catch (error: any) { - console.error('RPC request failed:', error); + console.error(`RPC [${method}] failed via custom request:`, { + message: error?.message, + code: error?.code, + data: error?.data, + stack: error?.stack, + raw: error, + }); throw new Error(error?.message || 'RPC request failed'); } } @@ -55,6 +62,7 @@ export class HathorRPCService { } try { + console.log(`RPC [${method}] requesting via WalletConnect (chain: hathor:${this.network}, topic: ${this.session.topic.slice(0, 8)}...)`); const result = await this.client.request({ chainId: `hathor:${this.network}`, topic: this.session.topic, @@ -64,9 +72,16 @@ export class HathorRPCService { }, }); + console.log(`RPC [${method}] response:`, JSON.stringify(result, null, 2)); return result; } catch (error: any) { - console.error('RPC request failed:', error); + console.error(`RPC [${method}] failed via WalletConnect:`, { + message: error?.message, + code: error?.code, + data: error?.data, + stack: error?.stack, + raw: error, + }); throw new Error(error?.message || 'RPC request failed'); } } From 2a9ea64716442788abb7b5fd19104b5a9067d2dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Tue, 7 Apr 2026 11:14:47 -0300 Subject: [PATCH 26/37] fix: log raw error keys and JSON on RPC failure The thrown error is a non-Error object with all standard properties undefined. Log Object.keys() and JSON.stringify() to reveal its actual contents. Co-Authored-By: Claude Opus 4.6 --- dapp/lib/hathorRPC.ts | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/dapp/lib/hathorRPC.ts b/dapp/lib/hathorRPC.ts index 7723c4b..f9bd2ca 100644 --- a/dapp/lib/hathorRPC.ts +++ b/dapp/lib/hathorRPC.ts @@ -45,13 +45,9 @@ export class HathorRPCService { console.log(`RPC [${method}] response:`, JSON.stringify(result, null, 2)); return result; } catch (error: any) { - console.error(`RPC [${method}] failed via custom request:`, { - message: error?.message, - code: error?.code, - data: error?.data, - stack: error?.stack, - raw: error, - }); + console.error(`RPC [${method}] failed via custom request. Raw error:`, error); + console.error(`RPC [${method}] error keys:`, error ? Object.keys(error) : 'null/undefined'); + try { console.error(`RPC [${method}] error JSON:`, JSON.stringify(error)); } catch {} throw new Error(error?.message || 'RPC request failed'); } } From ef1beea4b2e4a0ac86f41e1a9d55b3049a0e0cc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Tue, 7 Apr 2026 11:19:53 -0300 Subject: [PATCH 27/37] fix: fallback to fullnode API for balance when wallet RPC fails WalletConnect relay intermittently throws empty {} errors on htr_getBalance. When this happens, query the fullnode's thin_wallet/address_balance endpoint directly as a fallback. Co-Authored-By: Claude Opus 4.6 --- dapp/contexts/WalletContext.tsx | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/dapp/contexts/WalletContext.tsx b/dapp/contexts/WalletContext.tsx index 8e275b7..a7af248 100644 --- a/dapp/contexts/WalletContext.tsx +++ b/dapp/contexts/WalletContext.tsx @@ -6,6 +6,18 @@ import { HathorRPCService } from '@/lib/hathorRPC'; import { useUnifiedWallet } from './UnifiedWalletContext'; import { config, Network } from '@/lib/config'; +// Direct fullnode balance query — fallback when WalletConnect RPC fails +async function fetchBalanceFromFullnode(address: string, tokenUid: string, network: Network): Promise { + const nodeUrl = config.hathorNodeUrls[network]; + const resp = await fetch(`${nodeUrl}/thin_wallet/address_balance?address=${address}`); + if (!resp.ok) throw new Error(`Fullnode balance query failed: ${resp.status}`); + const data = await resp.json(); + if (!data.success) throw new Error(`Fullnode balance query error: ${data.message}`); + const tokenBalance = data.tokens_data?.[tokenUid]; + if (!tokenBalance) return 0n; + return BigInt(tokenBalance.unlocked); +} + interface WalletContextType { connected: boolean; address: string | null; @@ -128,14 +140,19 @@ export function WalletProvider({ children }: { children: ReactNode }) { setBalanceVerified(true); saveCachedBalance(addr, balanceValue); } catch (error: any) { - console.error('Balance fetch failed:', { - message: error?.message, - code: error?.code, - data: error?.data, - raw: error, - }); - setBalance(0n); - setBalanceVerified(false); + console.error('Balance fetch via wallet RPC failed, trying fullnode fallback:', error?.message); + // Fallback: query the fullnode directly (read-only, no wallet needed) + try { + const balanceValue = await fetchBalanceFromFullnode(addr, tokenUid, network); + console.log('Fullnode fallback balance:', balanceValue.toString()); + setBalance(balanceValue); + setBalanceVerified(true); + saveCachedBalance(addr, balanceValue); + } catch (fallbackError: any) { + console.error('Fullnode balance fallback also failed:', fallbackError?.message); + setBalance(0n); + setBalanceVerified(false); + } } finally { setIsLoadingBalance(false); } From b4f5c167271d7b16d8a5f0b0dffbc698ed7db7f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Tue, 7 Apr 2026 11:24:53 -0300 Subject: [PATCH 28/37] fix: JSON.stringify crash on BigInt response was causing RPC "failure" The RPC call was actually succeeding, but our debug log line JSON.stringify(result) crashed on BigInt values in the response, which became the thrown error. Use console.log directly instead. Also fix fullnode fallback to use received-spent (not unlocked). Co-Authored-By: Claude Opus 4.6 --- dapp/contexts/WalletContext.tsx | 2 +- dapp/lib/hathorRPC.ts | 16 ++++------------ 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/dapp/contexts/WalletContext.tsx b/dapp/contexts/WalletContext.tsx index a7af248..3b98f57 100644 --- a/dapp/contexts/WalletContext.tsx +++ b/dapp/contexts/WalletContext.tsx @@ -15,7 +15,7 @@ async function fetchBalanceFromFullnode(address: string, tokenUid: string, netwo if (!data.success) throw new Error(`Fullnode balance query error: ${data.message}`); const tokenBalance = data.tokens_data?.[tokenUid]; if (!tokenBalance) return 0n; - return BigInt(tokenBalance.unlocked); + return BigInt(tokenBalance.received - tokenBalance.spent); } interface WalletContextType { diff --git a/dapp/lib/hathorRPC.ts b/dapp/lib/hathorRPC.ts index f9bd2ca..d4d9aba 100644 --- a/dapp/lib/hathorRPC.ts +++ b/dapp/lib/hathorRPC.ts @@ -42,12 +42,10 @@ export class HathorRPCService { if (this.customRequest) { try { const result = await this.customRequest(method, params); - console.log(`RPC [${method}] response:`, JSON.stringify(result, null, 2)); + console.log(`RPC [${method}] response:`, result); return result; } catch (error: any) { - console.error(`RPC [${method}] failed via custom request. Raw error:`, error); - console.error(`RPC [${method}] error keys:`, error ? Object.keys(error) : 'null/undefined'); - try { console.error(`RPC [${method}] error JSON:`, JSON.stringify(error)); } catch {} + console.error(`RPC [${method}] failed via custom request:`, error); throw new Error(error?.message || 'RPC request failed'); } } @@ -68,16 +66,10 @@ export class HathorRPCService { }, }); - console.log(`RPC [${method}] response:`, JSON.stringify(result, null, 2)); + console.log(`RPC [${method}] response:`, result); return result; } catch (error: any) { - console.error(`RPC [${method}] failed via WalletConnect:`, { - message: error?.message, - code: error?.code, - data: error?.data, - stack: error?.stack, - raw: error, - }); + console.error(`RPC [${method}] failed via WalletConnect:`, error); throw new Error(error?.message || 'RPC request failed'); } } From 875cbd7c150a21238afb9fb480df89996244de5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Tue, 7 Apr 2026 12:07:13 -0300 Subject: [PATCH 29/37] fix: remove idempotency cache for channel settlements The cache key channel:id:amount is identical for every request on the same channel, so after the first spend() all subsequent requests returned the cached result without actually spending. Escrow cache (keyed by unique ncId) is correct and remains. Co-Authored-By: Claude Opus 4.6 --- facilitator.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/facilitator.js b/facilitator.js index 3ec697d..96a8c7f 100644 --- a/facilitator.js +++ b/facilitator.js @@ -160,18 +160,10 @@ app.post('/x402/settle', async (req, res) => { const { channelId } = paymentPayload.payload; const amount = req.body.amount || paymentPayload.payload.amount; const sellerAddress = req.body.sellerAddress || paymentPayload.payload.sellerAddress; - const cacheKey = `channel:${channelId}:${amount}`; - - // Idempotency: return cached result if already settled with same params - if (settlementCache.has(cacheKey)) { - log('FACILITATOR', `Channel settle CACHED for channelId=${channelId}`); - return res.json(settlementCache.get(cacheKey)); - } - + // No idempotency cache for channels — same channelId is reused across requests log('FACILITATOR', `Channel settle for channelId=${channelId}, amount=${amount}`); const result = await settleChannel(channelId, amount, sellerAddress); log('FACILITATOR', `Channel settle ${result.success ? 'SUCCESS' : 'FAILED'}: ${result.txId || result.error}`); - if (result.success) settlementCache.set(cacheKey, result); return res.json(result); } From 8f1e4ea0256701b72ddf81d8c64b6bce93ef2eb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Thu, 9 Apr 2026 17:02:55 -0300 Subject: [PATCH 30/37] feat: add x402 "upto" scheme for usage-based billing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements the x402 "upto" payment scheme alongside the existing "exact" scheme (per CDP docs). Clients authorize a maximum amount; the server settles only the actual usage, and the remainder is refunded to the buyer in the same settle call. - blueprint/x402_escrow.py: add release_upto(charged_amount) method that withdraws charged_amount to the seller and decrements the escrow balance, leaving the remainder claimable via the existing refund() flow (no new state/phase fields needed). - facilitator.js: add settleEscrowUpto() which calls release_upto followed by refund() to return the difference to the buyer. /x402/settle now routes on scheme=hathor-escrow-upto and keys the idempotency cache separately from exact settlements. - resource-server.js: refactor middleware into an x402Middleware(routeConfig) factory; settlement now happens AFTER the handler runs so handlers can call setSettlementOverrides({ amount }) to report actual usage. Adds GET /generate, a simulated LLM endpoint that charges per token up to a configurable max (default 5.00 HTR). NOTE: the blueprint change adds a new method — requires republishing the X402Escrow blueprint and updating BLUEPRINT_ID for /generate to work. /weather (exact scheme) keeps working with the current blueprint. Co-Authored-By: Claude Opus 4.6 --- blueprint/x402_escrow.py | 32 +++++ facilitator.js | 119 ++++++++++++++++-- resource-server.js | 253 +++++++++++++++++++++++++++------------ 3 files changed, 318 insertions(+), 86 deletions(-) diff --git a/blueprint/x402_escrow.py b/blueprint/x402_escrow.py index 860d927..5563afc 100644 --- a/blueprint/x402_escrow.py +++ b/blueprint/x402_escrow.py @@ -47,6 +47,8 @@ def initialize( @public(allow_withdrawal=True) def release(self, ctx: Context) -> None: + # Exact release: withdraw the entire escrow amount to the seller. + # Used by the "hathor-escrow" (exact) scheme. caller = ctx.get_caller_address() if caller != self.facilitator: raise NCFail("Only the facilitator can release funds") @@ -61,6 +63,36 @@ def release(self, ctx: Context) -> None: self.phase = PHASE_RELEASED + @public(allow_withdrawal=True) + def release_upto(self, ctx: Context, charged_amount: Amount) -> None: + # Partial release: withdraw `charged_amount` to the seller and leave the + # remainder locked so the buyer (or facilitator) can claim it back via + # refund(). Used by the "hathor-escrow-upto" scheme. + # + # After this call, self.amount becomes the remainder. If the remainder + # is zero, the phase transitions to RELEASED. Otherwise the phase stays + # LOCKED and the remaining amount can be refunded to the buyer using + # the existing refund() flow. + caller = ctx.get_caller_address() + if caller != self.facilitator: + raise NCFail("Only the facilitator can release funds") + if self.phase != PHASE_LOCKED: + raise NCFail("Escrow is not locked") + if charged_amount <= 0: + raise NCFail("charged_amount must be positive") + if charged_amount > self.amount: + raise NCFail("charged_amount exceeds escrow amount") + + action = ctx.get_single_action(self.token_uid) + if not isinstance(action, NCWithdrawalAction): + raise NCFail("Must include a withdrawal action") + if action.amount != charged_amount: + raise NCFail("Withdrawal amount must equal charged_amount") + + self.amount = self.amount - charged_amount + if self.amount == 0: + self.phase = PHASE_RELEASED + @public(allow_withdrawal=True) def refund(self, ctx: Context) -> None: caller = ctx.get_caller_address() diff --git a/facilitator.js b/facilitator.js index 96a8c7f..d55d1fb 100644 --- a/facilitator.js +++ b/facilitator.js @@ -65,7 +65,98 @@ async function settleEscrow(ncId) { if (!result.success) return { x402Version: 2, success: false, error: result.message || 'release() failed' }; // Don't wait for block confirmation — tx is accepted by the node, it will confirm eventually - return { x402Version: 2, success: true, txId: result.hash, network: `hathor:${config.network || 'privatenet'}` }; + return { + x402Version: 2, + success: true, + scheme: 'hathor-escrow', + txId: result.hash, + chargedAmount: amount, + network: `hathor:${config.network || 'privatenet'}`, + }; +} + +// "upto" scheme: release `chargedAmount` to seller, refund the remainder to buyer. +// Two on-chain calls: +// 1. release_upto(chargedAmount) -> withdraws chargedAmount to seller +// 2. refund() -> withdraws remainder to buyer (only if > 0) +async function settleEscrowUpto(ncId, chargedAmount) { + const stateResp = await getNanoContractState(ncId); + if (!stateResp.success) return { x402Version: 2, success: false, error: `Cannot query contract` }; + + const fields = stateResp.fields; + if (fields.phase.value !== 'LOCKED') return { x402Version: 2, success: false, error: `Escrow not locked (phase=${fields.phase.value})` }; + + const maxAmount = fields.amount.value; + const seller = fields.seller.value; + const buyer = fields.buyer.value; + const tokenUid = fields.token_uid.value; + + const charged = parseInt(chargedAmount); + if (!Number.isFinite(charged) || charged <= 0) { + return { x402Version: 2, success: false, error: `Invalid chargedAmount: ${chargedAmount}` }; + } + if (charged > maxAmount) { + return { x402Version: 2, success: false, error: `chargedAmount ${charged} exceeds escrow ${maxAmount}` }; + } + + const refund = maxAmount - charged; + + // Step 1: release_upto(charged) — withdraws charged to seller + log('FACILITATOR', `Escrow release_upto(${charged}) — to seller ${seller} (max ${maxAmount}, refund ${refund})`); + const releaseResult = await walletRequest('POST', '/wallet/nano-contracts/execute', { + nc_id: ncId, + method: 'release_upto', + address: config.facilitatorAddress, + data: { + args: [charged], + actions: [{ type: 'withdrawal', token: tokenUid, amount: charged, address: seller }], + }, + }, config.facilitatorWalletId); + + if (!releaseResult.success) { + return { x402Version: 2, success: false, error: releaseResult.message || 'release_upto() failed' }; + } + + // Step 2 (only if there is a remainder): refund() — withdraws remainder to buyer + let refundTxId = null; + if (refund > 0) { + log('FACILITATOR', `Escrow refund() — ${refund} of ${tokenUid} to buyer ${buyer}`); + const refundResult = await walletRequest('POST', '/wallet/nano-contracts/execute', { + nc_id: ncId, + method: 'refund', + address: config.facilitatorAddress, + data: { + args: [], + actions: [{ type: 'withdrawal', token: tokenUid, amount: refund, address: buyer }], + }, + }, config.facilitatorWalletId); + if (!refundResult.success) { + // The charge went through but the refund failed. Return partial success so the + // seller still gets paid and the buyer can retry the refund later. + return { + x402Version: 2, + success: true, + scheme: 'hathor-escrow-upto', + txId: releaseResult.hash, + chargedAmount: charged, + refundAmount: 0, + refundError: refundResult.message || 'refund() failed', + network: `hathor:${config.network || 'privatenet'}`, + }; + } + refundTxId = refundResult.hash; + } + + return { + x402Version: 2, + success: true, + scheme: 'hathor-escrow-upto', + txId: releaseResult.hash, + refundTxId, + chargedAmount: charged, + refundAmount: refund, + network: `hathor:${config.network || 'privatenet'}`, + }; } // ============================================================================ @@ -144,9 +235,9 @@ app.post('/x402/verify', async (req, res) => { return res.json(result); } - // Default: escrow + // Default: escrow (both "hathor-escrow" exact and "hathor-escrow-upto" verify against the same contract state) const { ncId } = paymentPayload.payload; - log('FACILITATOR', `Escrow verify for ncId=${ncId}`); + log('FACILITATOR', `Escrow verify for ncId=${ncId} (scheme=${scheme})`); const result = await verifyEscrow(ncId, paymentRequirements); log('FACILITATOR', `Escrow verify ${result.valid ? 'PASSED' : 'FAILED'}: ${result.invalidReason || 'OK'}`); res.json(result); @@ -167,18 +258,30 @@ app.post('/x402/settle', async (req, res) => { return res.json(result); } - // Default: escrow + // Escrow (exact or upto) const { ncId } = paymentPayload.payload; - const cacheKey = `escrow:${ncId}`; + const isUpto = scheme === 'hathor-escrow-upto'; + // Cache key differs between schemes so an exact/upto mismatch can never collide + const cacheKey = isUpto ? `escrow-upto:${ncId}` : `escrow:${ncId}`; // Idempotency: return cached result if already settled if (settlementCache.has(cacheKey)) { - log('FACILITATOR', `Escrow settle CACHED for ncId=${ncId}`); + log('FACILITATOR', `Escrow settle CACHED for ncId=${ncId} (scheme=${scheme})`); return res.json(settlementCache.get(cacheKey)); } - log('FACILITATOR', `Escrow settle for ncId=${ncId}`); - const result = await settleEscrow(ncId); + let result; + if (isUpto) { + const chargedAmount = req.body.chargedAmount ?? paymentPayload.payload.chargedAmount; + if (chargedAmount == null) { + return res.json({ x402Version: 2, success: false, error: 'chargedAmount required for hathor-escrow-upto' }); + } + log('FACILITATOR', `Escrow-upto settle for ncId=${ncId}, chargedAmount=${chargedAmount}`); + result = await settleEscrowUpto(ncId, chargedAmount); + } else { + log('FACILITATOR', `Escrow settle for ncId=${ncId}`); + result = await settleEscrow(ncId); + } log('FACILITATOR', `Escrow settle ${result.success ? 'SUCCESS' : 'FAILED'}: ${result.txId || result.error}`); if (result.success) settlementCache.set(cacheKey, result); res.json(result); diff --git a/resource-server.js b/resource-server.js index 1af1fd3..d243501 100644 --- a/resource-server.js +++ b/resource-server.js @@ -1,6 +1,7 @@ // x402 Resource Server (Seller) -// A simple API server that sells weather data -// Accepts payment via escrow (hathor-escrow) or channel (hathor-channel) +// A simple API server that sells: +// GET /weather -> exact scheme (hathor-escrow / hathor-channel) +// GET /generate -> upto scheme (hathor-escrow-upto) — usage-billed (simulated LLM) // Supports HTR and custom tokens const express = require('express'); @@ -20,8 +21,11 @@ app.use((req, res, next) => { next(); }); -// Build the list of accepted payment options (escrow + channel) -function buildAcceptsList(path) { +// Build the list of accepted payment options for a route. +// `routeConfig` describes the pricing mode for that route: +// { mode: 'exact', price } -> one-shot escrow or channel +// { mode: 'upto', maxPrice } -> upto-scheme escrow (server settles actual usage) +function buildAcceptsList(path, routeConfig) { const baseExtra = { facilitatorUrl: config.facilitatorPublicUrl, facilitatorAddress: config.facilitatorAddress, @@ -30,7 +34,26 @@ function buildAcceptsList(path) { const accepts = []; - // Escrow option + if (routeConfig.mode === 'upto') { + // Usage-based: client authorizes up to maxPrice, server settles actual usage. + accepts.push({ + scheme: 'hathor-escrow-upto', + network: `hathor:${config.network}`, + resource: `${config.resourceServerPublicUrl}${path}`, + mimeType: 'application/json', + payTo: config.sellerAddress, + maxTimeoutSeconds: config.escrowDeadlineSeconds, + asset: config.htrTokenUid, + price: String(routeConfig.maxPrice), + description: `Pay up to ${(routeConfig.maxPrice / 100).toFixed(2)} HTR — billed by actual usage`, + extra: { ...baseExtra, blueprintId: config.blueprintId, pricing: 'upto' }, + }); + return accepts; + } + + // Default: exact pricing (escrow + optional channel) + const price = routeConfig.price; + accepts.push({ scheme: 'hathor-escrow', network: `hathor:${config.network}`, @@ -39,12 +62,11 @@ function buildAcceptsList(path) { payTo: config.sellerAddress, maxTimeoutSeconds: config.escrowDeadlineSeconds, asset: config.htrTokenUid, - price: String(config.htrPaymentAmount), - description: `Pay ${(config.htrPaymentAmount / 100).toFixed(2)} HTR (single escrow)`, - extra: { ...baseExtra, blueprintId: config.blueprintId }, + price: String(price), + description: `Pay ${(price / 100).toFixed(2)} HTR (single escrow)`, + extra: { ...baseExtra, blueprintId: config.blueprintId, pricing: 'exact' }, }); - // Channel option if (config.channelBlueprintId) { accepts.push({ scheme: 'hathor-channel', @@ -54,82 +76,138 @@ function buildAcceptsList(path) { payTo: config.sellerAddress, maxTimeoutSeconds: config.escrowDeadlineSeconds, asset: config.htrTokenUid, - price: String(config.htrPaymentAmount), - description: `Pay ${(config.htrPaymentAmount / 100).toFixed(2)} HTR via channel (saves escrow creation)`, - extra: { ...baseExtra, channelBlueprintId: config.channelBlueprintId }, + price: String(price), + description: `Pay ${(price / 100).toFixed(2)} HTR via channel (saves escrow creation)`, + extra: { ...baseExtra, channelBlueprintId: config.channelBlueprintId, pricing: 'exact' }, }); } return accepts; } -// x402 middleware — checks for payment, returns 402 if none -function x402Middleware(req, res, next) { - // x402 V2: PAYMENT-SIGNATURE (Base64-encoded JSON), fallback to X-Payment (raw JSON) for backward compat - const signatureHeader = req.headers['payment-signature']; - const legacyHeader = req.headers['x-payment']; - - if (!signatureHeader && !legacyHeader) { - log('RESOURCE-SERVER', `402 — No payment for ${req.path}`); - return res.status(402).json({ - x402Version: 2, - accepts: buildAcceptsList(req.path), - version: '1', - }); - } - - const payment = signatureHeader - ? JSON.parse(Buffer.from(signatureHeader, 'base64').toString('utf-8')) - : JSON.parse(legacyHeader); - req.x402Payment = payment; - next(); +// Handlers call res.setSettlementOverrides({ amount }) during request processing +// to specify the actual amount to charge in the "upto" scheme. Ignored by "exact". +function setSettlementOverrides(res, overrides) { + res.locals.x402SettlementOverrides = { + ...(res.locals.x402SettlementOverrides || {}), + ...overrides, + }; } -function buildPaymentRequirements(path) { - return buildAcceptsList(path).map(opt => ({ +// Factory: build a middleware that verifies payment up-front and defers +// settlement until after the route handler has finished (so handlers can +// call setSettlementOverrides() for the "upto" scheme). +function x402Middleware(routeConfig) { + const paymentRequirements = buildAcceptsList('', routeConfig).map(opt => ({ scheme: opt.scheme, network: opt.network, maxAmountRequired: opt.price, payTo: opt.payTo, asset: opt.asset, })); -} -// Verify + settle + serve -app.get('/weather', x402Middleware, async (req, res) => { - const payment = req.x402Payment; - const scheme = payment.scheme; - const isChannel = scheme === 'hathor-channel'; - const id = isChannel ? payment.payload.channelId : payment.payload.ncId; + return async function (req, res, next) { + // x402 V2: PAYMENT-SIGNATURE (Base64-encoded JSON), fallback to X-Payment (raw JSON) for backward compat + const signatureHeader = req.headers['payment-signature']; + const legacyHeader = req.headers['x-payment']; - log('RESOURCE-SERVER', `Verifying ${scheme} payment id=${id}`); + if (!signatureHeader && !legacyHeader) { + log('RESOURCE-SERVER', `402 — No payment for ${req.path}`); + return res.status(402).json({ + x402Version: 2, + accepts: buildAcceptsList(req.path, routeConfig), + }); + } - // Step 1: Verify with facilitator - const allRequirements = buildPaymentRequirements(req.path); - const verifyResp = await fetch(`${config.facilitatorUrl}/x402/verify`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ paymentPayload: payment, paymentRequirements: allRequirements }), - }); - const verification = await verifyResp.json(); + let payment; + try { + payment = signatureHeader + ? JSON.parse(Buffer.from(signatureHeader, 'base64').toString('utf-8')) + : JSON.parse(legacyHeader); + } catch (err) { + return res.status(400).json({ error: 'Invalid PAYMENT-SIGNATURE header' }); + } - if (!verification.valid) { - log('RESOURCE-SERVER', `Payment INVALID: ${verification.invalidReason}`); - return res.status(402).json({ error: 'Payment invalid', reason: verification.invalidReason }); - } + const scheme = payment.scheme; + const isChannel = scheme === 'hathor-channel'; + const isUpto = scheme === 'hathor-escrow-upto'; + const id = isChannel ? payment.payload.channelId : payment.payload.ncId; + + log('RESOURCE-SERVER', `Verifying ${scheme} payment id=${id}`); + + // Step 1: Verify with facilitator (up-front, before running the handler) + const verifyResp = await fetch(`${config.facilitatorUrl}/x402/verify`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ paymentPayload: payment, paymentRequirements }), + }); + const verification = await verifyResp.json(); + + if (!verification.valid) { + log('RESOURCE-SERVER', `Payment INVALID: ${verification.invalidReason}`); + return res.status(402).json({ error: 'Payment invalid', reason: verification.invalidReason }); + } + log('RESOURCE-SERVER', `Payment VALID`); + + // Stash context for post-handler settlement + res.locals.x402 = { payment, scheme, isChannel, isUpto, id, routeConfig }; + + // Hook res.json so we can settle AFTER the handler finishes building its payload. + // This lets "upto" handlers compute actual usage and call setSettlementOverrides(). + const originalJson = res.json.bind(res); + res.json = async function (body) { + // Only settle on 2xx responses — skip if the handler returned an error. + if (res.statusCode >= 400) { + return originalJson(body); + } + try { + const { chargedAmount, settlement } = await settlePayment(res); + const paymentResponse = { + x402Version: 2, + success: true, + scheme, + network: `hathor:${config.network}`, + ...(isChannel ? { channelId: id } : { ncId: id }), + settleTxId: settlement.txId, + ...(isUpto ? { chargedAmount, refundAmount: settlement.refundAmount, refundTxId: settlement.refundTxId } : {}), + }; + res.set('PAYMENT-RESPONSE', Buffer.from(JSON.stringify(paymentResponse)).toString('base64')); + return originalJson({ data: body, payment: paymentResponse }); + } catch (err) { + log('RESOURCE-SERVER', `Settlement FAILED: ${err.message}`); + // Use originalJson directly to avoid recursion through the wrapped res.json + res.status(500); + return originalJson({ error: 'Settlement failed', reason: err.message }); + } + }; + + next(); + }; +} - log('RESOURCE-SERVER', `Payment VALID`); +// Internal: call the facilitator to settle. Picks the right shape based on scheme. +async function settlePayment(res) { + const { payment, scheme, isChannel, isUpto, id, routeConfig } = res.locals.x402; + const overrides = res.locals.x402SettlementOverrides || {}; - // Step 2: Settle BEFORE serving the resource - // For channels: spend() must confirm so on-chain state is updated before next request - // For escrow: release() must confirm so funds reach the seller - log('RESOURCE-SERVER', `Settling ${scheme} id=${id}`); const settleBody = { paymentPayload: payment }; + let chargedAmount; + if (isChannel) { - settleBody.amount = config.htrPaymentAmount; + settleBody.amount = routeConfig.price; settleBody.sellerAddress = config.sellerAddress; + chargedAmount = routeConfig.price; + } else if (isUpto) { + // Handler MUST call setSettlementOverrides({ amount }) — otherwise charge the full max. + chargedAmount = overrides.amount != null ? parseInt(overrides.amount) : routeConfig.maxPrice; + if (chargedAmount > routeConfig.maxPrice) chargedAmount = routeConfig.maxPrice; + if (chargedAmount < 1) chargedAmount = 1; + settleBody.chargedAmount = chargedAmount; + } else { + chargedAmount = routeConfig.price; } + log('RESOURCE-SERVER', `Settling ${scheme} id=${id}${isUpto ? ` chargedAmount=${chargedAmount}` : ''}`); const settleResp = await fetch(`${config.facilitatorUrl}/x402/settle`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, @@ -138,13 +216,16 @@ app.get('/weather', x402Middleware, async (req, res) => { const settlement = await settleResp.json(); if (!settlement.success) { - log('RESOURCE-SERVER', `Settlement FAILED: ${settlement.error}`); - return res.status(500).json({ error: 'Settlement failed', reason: settlement.error }); + throw new Error(settlement.error || 'settle failed'); } - log('RESOURCE-SERVER', `Settlement confirmed — txId=${settlement.txId}`); + return { chargedAmount, settlement }; +} - // Step 3: Serve the resource (only after settlement is confirmed) +// ----- Routes ----- + +// EXACT scheme: classic fixed-price endpoint +app.get('/weather', x402Middleware({ mode: 'exact', price: config.htrPaymentAmount }), async (req, res) => { const weatherData = { location: 'Sao Paulo, Brazil', temperature: 28, @@ -154,26 +235,42 @@ app.get('/weather', x402Middleware, async (req, res) => { forecast: 'Warm with chance of afternoon showers', timestamp: new Date().toISOString(), }; + res.json(weatherData); +}); - // x402 V2: PAYMENT-RESPONSE header with Base64-encoded settlement result - const paymentResponse = { - x402Version: 2, - success: true, - scheme, - network: `hathor:${config.network}`, - ...(isChannel ? { channelId: id } : { ncId: id }), - settleTxId: settlement.txId, - }; - res.set('PAYMENT-RESPONSE', Buffer.from(JSON.stringify(paymentResponse)).toString('base64')); +// UPTO scheme: usage-based endpoint (simulated LLM generation) +// Client authorizes up to `maxPrice`; server charges based on tokens actually generated. +const GENERATE_MAX_PRICE = parseInt(process.env.GENERATE_MAX_PRICE || '500'); // 5.00 HTR +const GENERATE_PRICE_PER_TOKEN = 1; // 0.01 HTR per token generated + +app.get('/generate', x402Middleware({ mode: 'upto', maxPrice: GENERATE_MAX_PRICE }), async (req, res) => { + // Simulate variable LLM token usage between 50 and GENERATE_MAX_PRICE/PRICE_PER_TOKEN tokens + const maxTokens = Math.floor(GENERATE_MAX_PRICE / GENERATE_PRICE_PER_TOKEN); + const tokensUsed = Math.floor(50 + Math.random() * (maxTokens - 50)); + const actualCost = tokensUsed * GENERATE_PRICE_PER_TOKEN; + // Tell the middleware how much to actually charge + setSettlementOverrides(res, { amount: actualCost }); + + const prompt = req.query.prompt || 'default prompt'; res.json({ - data: weatherData, - payment: paymentResponse, + prompt, + completion: `Generated response for: "${prompt}". This mock response simulates variable-length LLM output billed per token.`, + usage: { + tokensUsed, + pricePerToken: GENERATE_PRICE_PER_TOKEN, + authorizedMaxAtomic: GENERATE_MAX_PRICE, + actualChargedAtomic: actualCost, + }, + timestamp: new Date().toISOString(), }); }); app.listen(config.resourceServerPort, () => { - log('RESOURCE-SERVER', `Weather API running on port ${config.resourceServerPort}`); + log('RESOURCE-SERVER', `Paid API running on port ${config.resourceServerPort}`); log('RESOURCE-SERVER', `Seller address: ${config.sellerAddress}`); - log('RESOURCE-SERVER', `Accepts: escrow${config.channelBlueprintId ? ' + channel' : ''}`); + log('RESOURCE-SERVER', `Routes:`); + log('RESOURCE-SERVER', ` GET /weather — exact: ${(config.htrPaymentAmount / 100).toFixed(2)} HTR`); + log('RESOURCE-SERVER', ` GET /generate — upto: up to ${(GENERATE_MAX_PRICE / 100).toFixed(2)} HTR (usage-billed)`); + log('RESOURCE-SERVER', `Schemes: hathor-escrow${config.channelBlueprintId ? ' + hathor-channel' : ''} + hathor-escrow-upto`); }); From 3d6aa6f4f4b984607ac4eec8e2ee1383671bf102 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Abadesso?= Date: Thu, 9 Apr 2026 17:11:51 -0300 Subject: [PATCH 31/37] feat(dapp): demonstrate the upto scheme in X402Fetch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Recognize hathor-escrow-upto in the 402 options selector and render it with its own label ("Upto · Usage-billed") and blue accent. - Pay button now says "Authorize up to X HTR" for upto options. - After a successful upto request, show a "Usage-Based Settlement" panel with max authorized, actual charged, refund amount, and refund txId. - Payment history badge distinguishes upto / channel / escrow, and upto rows show "charged X HTR · refunded Y HTR". - Add preset URL buttons (/weather exact, /generate upto) so users can try both schemes without typing the URL. Co-Authored-By: Claude Opus 4.6 --- dapp/components/X402Fetch.tsx | 127 +++++++++++++++++++++++++++------- 1 file changed, 103 insertions(+), 24 deletions(-) diff --git a/dapp/components/X402Fetch.tsx b/dapp/components/X402Fetch.tsx index 67f6829..67adec2 100644 --- a/dapp/components/X402Fetch.tsx +++ b/dapp/components/X402Fetch.tsx @@ -21,6 +21,7 @@ interface PaymentOption { blueprintId?: string; channelBlueprintId?: string; deadlineSeconds: number; + pricing?: 'exact' | 'upto'; }; } @@ -30,6 +31,8 @@ interface PaymentHistory { scheme: string; contractId: string; amount: string; + chargedAmount?: string; + refundAmount?: string; timestamp: Date; } @@ -73,8 +76,8 @@ export function X402Fetch() { setContractId(null); }; - const addToHistory = (scheme: string, id: string, amount: string) => { - setHistory(prev => [{ id: Date.now().toString(), url, scheme, contractId: id, amount, timestamp: new Date() }, ...prev]); + const addToHistory = (scheme: string, id: string, amount: string, chargedAmount?: string, refundAmount?: string) => { + setHistory(prev => [{ id: Date.now().toString(), url, scheme, contractId: id, amount, chargedAmount, refundAmount, timestamp: new Date() }, ...prev]); }; // Try to pay with an existing channel (instant — no wallet interaction) @@ -142,11 +145,12 @@ export function X402Fetch() { } }; - // Step 2: Pay (escrow or channel) + // Step 2: Pay (escrow, channel, or upto escrow) const handlePay = async () => { if (!selectedOption || !isConnected || !address) return; const opt = selectedOption; const isChannel = opt.scheme === 'hathor-channel'; + const isUpto = opt.scheme === 'hathor-escrow-upto'; try { setStep('creating'); @@ -170,9 +174,12 @@ export function X402Fetch() { setActiveChannel(id); toast.success(`Channel created: ${id.slice(0, 12)}...`); } else { - // Create a one-shot escrow + // Create a one-shot escrow (same initialize() for both exact and upto — + // the difference is how the facilitator settles it: release() vs release_upto()). const deadline = Math.floor(Date.now() / 1000) + opt.extra.deadlineSeconds; - toast.info('Confirm the escrow deposit in your wallet...'); + toast.info(isUpto + ? `Confirm the escrow deposit (max ${(parseInt(opt.price) / 100).toFixed(2)} HTR) in your wallet...` + : 'Confirm the escrow deposit in your wallet...'); const result = await sendNanoContractTx({ network, blueprint_id: opt.extra.blueprintId, method: 'initialize', @@ -192,11 +199,11 @@ export function X402Fetch() { setStep('waiting_confirmation'); await waitForConfirmation(id); - // Retry with payment proof + // Retry with payment proof — scheme in the payload must match the 402 accept setStep('retrying'); const paymentPayload = isChannel ? { x402Version: 2, scheme: 'hathor-channel', network: `hathor:${network}`, payload: { channelId: id, buyerAddress: address } } - : { x402Version: 2, scheme: 'hathor-escrow', network: `hathor:${network}`, payload: { ncId: id, depositTxId: id, buyerAddress: address } }; + : { x402Version: 2, scheme: opt.scheme, network: `hathor:${network}`, payload: { ncId: id, depositTxId: id, buyerAddress: address } }; const paidResp = await fetch(url, { mode: 'cors', headers: { 'PAYMENT-SIGNATURE': btoa(JSON.stringify(paymentPayload)) } }); if (!paidResp.ok) { @@ -208,7 +215,9 @@ export function X402Fetch() { setResourceData(data); setStep('done'); toast.success('Resource received!'); - addToHistory(opt.scheme, id, opt.price); + const charged = data?.payment?.chargedAmount != null ? String(data.payment.chargedAmount) : undefined; + const refund = data?.payment?.refundAmount != null ? String(data.payment.refundAmount) : undefined; + addToHistory(opt.scheme, id, opt.price, charged, refund); refreshBalance('00', network); } catch (err: any) { setError(err.message); @@ -232,6 +241,7 @@ export function X402Fetch() { const amountDisplay = selectedOption ? `${(parseInt(selectedOption.price) / 100).toFixed(2)} HTR` : ''; const isChannel = selectedOption?.scheme === 'hathor-channel'; + const isUpto = selectedOption?.scheme === 'hathor-escrow-upto'; return (
@@ -276,6 +286,25 @@ export function X402Fetch() { Fetch
+ + {/* Preset URLs */} +
+ Try: + + +
{/* Fetching */} @@ -300,13 +329,16 @@ export function X402Fetch() {
{paymentOptions.map((opt, i) => { const isCh = opt.scheme === 'hathor-channel'; + const isUp = opt.scheme === 'hathor-escrow-upto'; + const label = isCh ? '⚡ Channel' : isUp ? '📊 Upto' : '🔒 Escrow'; + const sub = isCh ? 'Instant after setup' : isUp ? 'Usage-billed' : 'One-shot per request'; return ( ); })} @@ -315,8 +347,8 @@ export function X402Fetch() { {/* Details */}
- Per request - {amountDisplay} + {isUpto ? 'Max authorized' : 'Per request'} + {isUpto ? `up to ${amountDisplay}` : amountDisplay}
{isChannel && (
@@ -330,8 +362,10 @@ export function X402Fetch() {
After this - - {isChannel ? 'Next 9 requests are instant' : 'Each request needs a new escrow'} + + {isChannel ? 'Next 9 requests are instant' + : isUpto ? 'Server settles actual usage, remainder refunded' + : 'Each request needs a new escrow'}
@@ -342,6 +376,7 @@ export function X402Fetch() { style={{ background: isConnected ? 'linear-gradient(244deg, rgb(255, 166, 0) 0%, rgb(255, 115, 0) 100%)' : '#475569', color: '#0f172a' }}> {!isConnected ? 'Connect Wallet First' : isChannel ? `Open Channel (${(parseInt(selectedOption.price) * 10 / 100).toFixed(2)} HTR)` + : isUpto ? `Authorize up to ${amountDisplay}` : `Pay ${amountDisplay}`} @@ -383,6 +418,36 @@ export function X402Fetch() { {contractId &&

Via {formatAddress(contractId)}

}
+ + {/* Upto billing summary */} + {resourceData?.payment?.scheme === 'hathor-escrow-upto' && resourceData?.payment?.chargedAmount != null && ( +
+
📊 Usage-Based Settlement
+
+
+ Max authorized + {(parseInt(selectedOption?.price || '0') / 100).toFixed(2)} HTR +
+
+ Actually charged + {(parseInt(resourceData.payment.chargedAmount) / 100).toFixed(2)} HTR +
+ {resourceData.payment.refundAmount > 0 && ( +
+ Refunded to you + {(parseInt(resourceData.payment.refundAmount) / 100).toFixed(2)} HTR +
+ )} + {resourceData.payment.refundTxId && ( +
+ Refund tx + {formatAddress(resourceData.payment.refundTxId)} +
+ )} +
+
+ )} +
             {JSON.stringify(resourceData.data || resourceData, null, 2)}
           
@@ -406,17 +471,31 @@ export function X402Fetch() {

Payment History

- {history.map((e) => ( -
-
-

{e.url}

-

{e.timestamp.toLocaleTimeString()} — {formatAddress(e.contractId)}

+ {history.map((e) => { + const badgeClass = e.scheme === 'hathor-channel' ? 'bg-green-500/20 text-green-400' + : e.scheme === 'hathor-escrow-upto' ? 'bg-blue-500/20 text-blue-400' + : 'bg-amber-500/20 text-amber-400'; + const badgeLabel = e.scheme === 'hathor-channel' ? 'channel' + : e.scheme === 'hathor-escrow-upto' ? 'upto' + : 'escrow'; + return ( +
+
+

{e.url}

+

+ {e.timestamp.toLocaleTimeString()} — {formatAddress(e.contractId)} + {e.chargedAmount != null && ( + + charged {(parseInt(e.chargedAmount) / 100).toFixed(2)} HTR + {e.refundAmount && parseInt(e.refundAmount) > 0 && ` · refunded ${(parseInt(e.refundAmount) / 100).toFixed(2)} HTR`} + + )} +

+
+ {badgeLabel}
- - {e.scheme === 'hathor-channel' ? 'channel' : 'escrow'} - -
- ))} + ); + })}
)} From 749b66bf664ba8860a451b5f11463b9b525a7667 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira Date: Thu, 28 May 2026 15:43:40 -0300 Subject: [PATCH 32/37] =?UTF-8?q?feat:=20hathor-direct=20PoC=20=E2=80=94?= =?UTF-8?q?=20drop=20nano=20contracts,=20add=20UTXO-payment=20+=20signed-r?= =?UTF-8?q?equestId=20scheme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace X402Escrow / X402Channel blueprints with regular send-tx flow - Read-only verifier + better-sqlite3 dedup/blocklist - htr_sendTransaction + htr_signWithAddress on the dApp (UTXOs filtered to address-0) - Two schemes: hathor-direct (exact) + hathor-direct-upto (refund remainder) - Optional standalone facilitator; resource-server self-verifies by default --- .env.example | 56 +- Dockerfile | 19 +- README.md | 356 ++++------ blueprint/x402_channel.py | 95 --- blueprint/x402_escrow.py | 117 ---- client.js | 266 ++++---- config.js | 78 ++- dapp/.env.example | 34 +- dapp/.env.local.example | 18 +- dapp/AGENTS.md | 493 +++----------- dapp/Dockerfile | 51 +- dapp/README.md | 344 ++-------- dapp/app/escrow/[id]/page.tsx | 76 --- dapp/app/layout.tsx | 4 +- dapp/app/page.tsx | 29 +- dapp/app/payment/[txId]/page.tsx | 253 +++++++ dapp/components/BalanceCard.tsx | 34 +- dapp/components/ContractInfoPanel.tsx | 77 --- dapp/components/CreateEscrowForm.tsx | 173 ----- dapp/components/EscrowDetail.tsx | 121 ---- dapp/components/EscrowList.tsx | 81 --- dapp/components/EscrowStatusBadge.tsx | 16 - dapp/components/Header.tsx | 75 +- dapp/components/TokenSelector.tsx | 32 - dapp/components/X402Fetch.tsx | 665 ++++++++++-------- dapp/contexts/HathorContext.tsx | 111 +-- dapp/contexts/WalletConnectContext.tsx | 4 +- dapp/contexts/WalletContext.tsx | 206 +++--- dapp/lib/config.ts | 28 +- dapp/lib/escrowStore.ts | 21 - dapp/lib/hathorCoreAPI.ts | 132 +--- dapp/lib/hathorRPC.ts | 181 ++++- dapp/lib/paymentHistory.ts | 74 ++ dapp/scripts/deploy.sh | 28 +- dapp/types/hathor.ts | 146 ++-- data/payments.sqlite | Bin 0 -> 4096 bytes data/payments.sqlite-shm | Bin 0 -> 32768 bytes data/payments.sqlite-wal | Bin 0 -> 45352 bytes dedupStore.js | 142 ++++ docker-compose.yml | 90 ++- examples/mcp-server/README.md | 94 ++- examples/mcp-server/package.json | 10 +- examples/mcp-server/server.js | 299 ++++---- facilitator.js | 445 +++--------- helpers.js | 131 +++- init-seller-wallet.sh | 34 + init-wallets.sh | 29 - package-lock.json | 901 +++++++++++++++++++++++-- package.json | 12 +- refundIssuer.js | 64 ++ requestId.js | 81 +++ resource-server.js | 499 ++++++++------ verifier.js | 131 ++++ voidWatcher.js | 60 ++ 54 files changed, 3793 insertions(+), 3723 deletions(-) delete mode 100644 blueprint/x402_channel.py delete mode 100644 blueprint/x402_escrow.py delete mode 100644 dapp/app/escrow/[id]/page.tsx create mode 100644 dapp/app/payment/[txId]/page.tsx delete mode 100644 dapp/components/ContractInfoPanel.tsx delete mode 100644 dapp/components/CreateEscrowForm.tsx delete mode 100644 dapp/components/EscrowDetail.tsx delete mode 100644 dapp/components/EscrowList.tsx delete mode 100644 dapp/components/EscrowStatusBadge.tsx delete mode 100644 dapp/components/TokenSelector.tsx delete mode 100644 dapp/lib/escrowStore.ts create mode 100644 dapp/lib/paymentHistory.ts create mode 100644 data/payments.sqlite create mode 100644 data/payments.sqlite-shm create mode 100644 data/payments.sqlite-wal create mode 100644 dedupStore.js create mode 100755 init-seller-wallet.sh delete mode 100755 init-wallets.sh create mode 100644 refundIssuer.js create mode 100644 requestId.js create mode 100644 verifier.js create mode 100644 voidWatcher.js diff --git a/.env.example b/.env.example index a543175..a03df86 100644 --- a/.env.example +++ b/.env.example @@ -1,32 +1,40 @@ -# Hathor services -FULLNODE_URL=http://127.0.0.1:8080 -WALLET_HEADLESS_URL=http://localhost:8000 +# --- Hathor fullnode (read-only) -------------------------------------------- +FULLNODE_URL=https://node1.testnet.hathor.network +HATHOR_NETWORK=testnet -# Blueprint IDs (published on-chain) -BLUEPRINT_ID= -CHANNEL_BLUEPRINT_ID= - -# Wallet IDs (must exist in wallet-headless) -BUYER_WALLET_ID=buyer -FACILITATOR_WALLET_ID=facilitator -SELLER_WALLET_ID=seller +# --- Resource server -------------------------------------------------------- +RESOURCE_SERVER_PORT=3000 +RESOURCE_SERVER_PUBLIC_URL=http://localhost:3000 -# Wallet addresses -BUYER_ADDRESS= -FACILITATOR_ADDRESS= +# Seller's static receiving address. The resource server emits this in 402's +# `payTo`. The seller controls this address (in any wallet of their choosing). SELLER_ADDRESS= -# Custom token UID (optional — leave empty for HTR-only) -# The server will accept both HTR and this token if set -CUSTOM_TOKEN_UID= +# --- Server secret (HMACs the requestId) ------------------------------------ +# Must be at least 32 bytes of entropy in prod. Local dev: any non-empty string. +SERVER_SECRET=change-me-32-bytes-min +REQUEST_ID_TTL_SECONDS=120 -# Ports -FACILITATOR_PORT=8402 -RESOURCE_SERVER_PORT=3000 +# --- Dedup + blocklist store ------------------------------------------------ +DEDUP_DB_PATH=./data/payments.sqlite -# Escrow settings -ESCROW_DEADLINE_SECONDS=300 +# Above this amount, the verifier refuses zero-conf (requires meta.first_block). +# Default: never require a block (zero-conf for everything — fine for POC). +ZERO_CONF_MAX_AMOUNT=9007199254740991 -# Payment amounts (in smallest unit — 1 HTR = 100) +# --- Pricing (atomic units; 1 HTR = 100) ------------------------------------ HTR_PAYMENT_AMOUNT=100 -CUSTOM_TOKEN_PAYMENT_AMOUNT=1000 +GENERATE_MAX_PRICE=500 + +# --- Verify path: 'self' or 'facilitator' ----------------------------------- +VERIFY_MODE=self +FACILITATOR_PORT=8402 +FACILITATOR_URL=http://localhost:8402 + +# --- Seller's wallet-headless (only needed for the upto refund) ------------ +SELLER_WALLET_URL=http://wallet-headless:8000 +SELLER_WALLET_ID=seller +SELLER_SEED= + +# --- Optional: only needed if you want to run the CLI client.js ------------- +BUYER_SEED= diff --git a/Dockerfile b/Dockerfile index 5f91ff7..d6c7592 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,17 +1,26 @@ FROM node:22-alpine +# `curl` for the init script + container healthchecks; build deps installed +# transiently for the `better-sqlite3` native compile. RUN apk add --no-cache curl WORKDIR /app -COPY package.json package-lock.json ./ -RUN npm ci --production +COPY package.json package-lock.json* ./ + +# Install with build deps, then drop them to keep the image small. +RUN apk add --no-cache --virtual .build python3 make g++ \ + && npm install --omit=dev \ + && apk del .build COPY *.js ./ COPY *.sh ./ -COPY blueprint/ ./blueprint/ + +# Persistent dedup + blocklist SQLite file lives here. +RUN mkdir -p /app/data +VOLUME ["/app/data"] EXPOSE 8402 3000 -# Default: run the facilitator. Override CMD for other components. -CMD ["node", "facilitator.js"] +# Default: run the resource server. Override CMD for the facilitator service. +CMD ["node", "resource-server.js"] diff --git a/README.md b/README.md index 170b8af..0a9c7fa 100644 --- a/README.md +++ b/README.md @@ -1,274 +1,166 @@ -# x402 Payment Protocol POC for Hathor Network +# x402 Payment Protocol PoC for Hathor Network -> Machines paying machines. HTTP 402 meets nano contract escrow. +> Machines paying machines, settled on Hathor with regular UTXO payments. +> No nano contracts, no escrow blueprint, no facilitator hot wallet. -This is a proof-of-concept implementation of the [x402 protocol](https://www.x402.org/) on [Hathor Network](https://hathor.network/). It enables pay-per-request HTTP APIs settled natively on Hathor's DAG-based L1 blockchain using **nano contract escrow**. +This is a proof-of-concept implementation of the [x402 protocol](https://www.x402.org/) +on [Hathor Network](https://hathor.network/) using the **`hathor-direct`** scheme: the +client makes an ordinary "send tokens" transaction to the seller, signs a server-issued +challenge with its payer key, and the server verifies the on-chain payment + signature +read-only. -## What is x402? - -[x402](https://www.x402.org/) is an open protocol that repurposes the HTTP `402 Payment Required` status code for machine-to-machine payments. When a client requests a paid resource, the server returns a `402` with payment instructions. The client pays, retries the request with proof of payment, and gets the resource. No API keys, no billing accounts, no human interaction. - -The client is always code — an AI agent, a script, a backend service. Never a human clicking buttons. - -## How Hathor does it: one escrow per request - -On EVM chains (Base, Polygon), x402 payments use signed messages — the client signs an authorization off-chain, and the facilitator submits it on-chain in one step. Simple, but it relies on nonces and trust. - -**Hathor takes a different approach: on-chain escrow.** - -Every x402 payment creates a **new nano contract instance** from the [X402Escrow blueprint](blueprint/x402_escrow.py). Here's what that means concretely: - -1. The `X402Escrow` blueprint is published on-chain once (like a class definition) -2. Each payment **instantiates** a new contract from that blueprint (like creating an object) -3. The client deposits funds into this new contract — they're locked on-chain -4. The facilitator verifies the lock, the server delivers the resource -5. The facilitator calls `release()` on the contract — funds go to the seller - -So if an AI agent makes 10 API calls, there are **10 separate escrow contracts** on the Hathor DAG. Each one: - -- Has its own contract ID (`ncId`) which doubles as the payment receipt -- Holds its own funds, independently locked -- Has its own deadline (auto-refund if the facilitator disappears) -- Can be verified by anyone — just query the contract state on any full node -- Cannot be double-spent — the funds are locked in the contract, not in a UTXO - -``` - Blueprint (published once) Instances (one per payment) -┌──────────────────────────┐ -│ X402Escrow │ ┌─────────────┐ -│ │───────▶│ Payment #1 │ LOCKED → RELEASED -│ initialize() │ │ 1.00 HTR │ -│ release() │ └─────────────┘ -│ refund() │ ┌─────────────┐ -│ │───────▶│ Payment #2 │ LOCKED → RELEASED -│ │ │ 1.00 HTR │ -└──────────────────────────┘ └─────────────┘ - ┌─────────────┐ - ────▶│ Payment #3 │ LOCKED → REFUNDED - │ 5.00 hUSDC │ (buyer cancelled) - └─────────────┘ -``` - -### Why not pre-signed transactions? - -The naive approach for UTXO chains is pre-signed transactions: the client signs a tx offline and hands it to the facilitator. But the client can **double-spend those UTXOs** before the facilitator broadcasts. On EVM this is solved by nonces; Hathor doesn't have nonces. Nano contract escrow solves it completely — funds are locked on-chain the moment the client deposits. - -| | Pre-Signed TX | Nano Contract Escrow | -| ------------------ | --------------------------------------- | ------------------------------------------- | -| Double-spend risk | **High** — client can spend UTXOs | **Zero** — funds locked on-chain | -| Verification | Off-chain signature check | **On-chain state query** — trustless | -| Refund on timeout | Impossible without timelock hacks | **Built-in** — contract refunds | -| Trust model | Must trust facilitator won't hold tx | **Trustless** — contract enforces rules | - -## The escrow lifecycle - -Each escrow contract goes through exactly one of two paths: +See the full design rationale (with the rejected nano-contract design and the +fair-exchange / trust analysis) in +[`../x402-hathor-no-nc-proposal.md`](../x402-hathor-no-nc-proposal.md). -``` - ┌─────────────────────────────┐ - │ LOCKED │ - initialize() │ │ - + deposit ───────▶│ Funds held in contract. │ - │ Buyer, seller, facilitator, │ - │ amount, deadline recorded. │ - │ │ - └──────────┬──────────┬───────┘ - │ │ - release() │ │ refund() - by facilitator│ │ by buyer (anytime) - after server │ │ by facilitator (anytime) - delivers │ │ by anyone (after deadline) - resource │ │ - ▼ ▼ - ┌──────────────┐ ┌──────────────┐ - │ RELEASED │ │ REFUNDED │ - │ │ │ │ - │ Funds sent │ │ Funds sent │ - │ to seller │ │ back to buyer│ - └──────────────┘ └──────────────┘ -``` +## What is x402? -**Three roles, clear permissions:** -- **Buyer**: deposits funds (initialize), can cancel anytime (refund) -- **Facilitator**: releases funds to seller after verification, can refund if service failed -- **Anyone**: can trigger refund after the deadline — dead man's switch so funds are never locked forever +[x402](https://www.x402.org/) repurposes the HTTP `402 Payment Required` status code +for machine-to-machine payments: a client requests a paid resource, the server returns +a 402 with payment requirements, the client pays, retries the request with proof, and +gets the resource. The client is always code — an AI agent, a script, a backend +service. Never a human clicking buttons. -## Full payment flow +## How Hathor does it (this PoC) ``` - CLIENT (AI agent) RESOURCE SERVER FACILITATOR HATHOR - ───────────────── ─────────────── ─────────── ────── - │ │ │ │ - 1. │── GET /weather ──────────▶ │ │ │ - │ │ │ │ - 2. │◀── 402 Payment Required ── │ │ │ - │ {amount: "100", │ │ │ - │ asset: "00", │ │ │ - │ payTo, facilitator, │ │ │ - │ blueprintId} │ │ │ - │ │ │ │ - 3. │── create new X402Escrow ─────────────────────────────────────────────────▶ │ - │ contract instance │ │ │ - │ (initialize + deposit │ │ LOCKED │ - │ 1.00 HTR) │ │ │ - │◀── ncId (= tx hash) ──────────────────────────────────────────────────────── │ - │ │ │ │ - 4. │── GET /weather ──────────▶ │ │ │ - │ + X-Payment {ncId} │ │ │ - │ │── POST /x402/verify ────▶ │ │ - │ │ {ncId, amount, payTo} │── query nc state ─▶ │ - │ │ │◀─ {LOCKED, 100} ── │ - │ │◀── {valid: true} ──────── │ │ - │ │ │ │ - 5. │◀── 200 + weather data ──── │ │ │ - │ │ │ │ - 6. │ │── POST /x402/settle ────▶ │ │ - │ │ {ncId} │── release() ───────▶│ - │ │ │ (withdraw to seller)│ - │ │ │◀── txId ─────────── │ - │ │◀── {success, txId} ────── │ RELEASED │ - │ │ │ │ +┌──────────────┐ ┌──────────────────────────┐ ┌─────────────────┐ +│ dApp / │──fetch──▶│ resource-server │──read───▶│ Hathor fullnode │ +│ agent │ │ verifier.js + │ │ (testnet/etc.) │ +│ │ │ dedupStore + │ └─────────────────┘ +│ htr_sendTx │ │ voidWatcher + │ ▲ +│ htr_signWith │ │ (refundIssuer for │ │ +│ Address │ │ the upto scheme) │ │ +└──────┬───────┘ └──────────┬───────────────┘ │ + │ │ POST /wallet/send-tx (refund only) + ▼ ▼ + Hathor wallet wallet-headless (seller refund wallet) + (desktop / mobile / + MetaMask snap) ``` -**Timing:** ~10s for escrow deposit confirmation, ~100ms for verification, instant HTTP response, ~10s for settlement confirmation. The client waits ~10s before getting the resource; settlement happens async after the resource is served. +Two on-chain transactions in the worst case: -## This POC includes +1. **Client → seller**: a plain `sendTransaction` paying `amount` to `payTo`. + This is the *only* tx for `hathor-direct` (exact). +2. **Seller → client** (upto only): a refund tx for `amount - chargedAmount`, + issued by the seller's wallet-headless after the route handler reports + actual usage. -### Backend (Node.js) +The server (or an optional facilitator wrapper) is purely read-only against the +fullnode: -| Component | File | Port | What it does | -|-----------|------|------|-------------| -| **Facilitator** | `facilitator.js` | 8402 | Verifies escrow state (`/x402/verify`) and triggers settlement (`/x402/settle`) | -| **Resource Server** | `resource-server.js` | 3000 | Example paid weather API with x402 middleware. Accepts HTR and custom tokens | -| **Client** | `client.js` | — | Programmatic x402 client. Fetches → gets 402 → creates escrow → retries → gets data | -| **Blueprint** | `blueprint/x402_escrow.py` | — | The X402Escrow nano contract source (Python 3.11) | - -### Frontend (Next.js dApp) +- Verify the on-chain payment (correct `payTo`, `amount`, asset, not voided). +- Verify the payer signature over the server-issued `requestId`. +- Atomically dedup against the SQLite ledger so the same payment can't be replayed. +- Kick off a void-watcher for zero-conf payments; double-spending payers get + blocklisted. -The `dapp/` directory contains a browser-based x402 payment client built with [create-hathor-dapp](https://github.com/HathorNetwork/create-hathor-dapp): +## Schemes -1. Connect your Hathor wallet (WalletConnect / Reown) -2. Enter any x402-enabled URL -3. See the 402 payment requirements (amount, token options, seller) -4. Click "Pay & Access" — your wallet signs the escrow deposit -5. Wait for on-chain confirmation (~10s) -6. Resource data displayed +| Scheme | Semantics | Settlement | +|---|---|---| +| `hathor-direct` | Pay exact amount up front. | No-op — payment is final on-chain. | +| `hathor-direct-upto` | Authorize a max. Server charges actual usage. | Server issues a refund tx for `max - charged` from its own wallet. | -The dApp replaces `client.js` for interactive use — instead of the agent calling wallet-headless programmatically, the user approves the escrow deposit through their wallet app. +Both use the same wire protocol and verifier code path; `upto` adds the optional +refund step. -## Multi-token support +## Wire protocol -The resource server can accept multiple tokens per route. The 402 response lists all options in the `accepts` array: +402 body returned by the resource server: -```json +```jsonc { - "accepts": [ - { "asset": "00", "amount": "100", "description": "Pay 1.00 HTR" }, - { "asset": "000003e3...", "amount": "1000", "description": "Or pay 10.00 hUSDC" } - ] + "x402Version": 2, + "accepts": [{ + "scheme": "hathor-direct" | "hathor-direct-upto", + "network": "hathor:testnet", + "amount": "100", // atomic units; 1 HTR = 100. For upto, this is MAX. + "asset": "00", // "00" = HTR + "payTo": "WXf4x…", + "resource": "https://host/route", + "maxTimeoutSeconds": 120, + "description": "Pay 1.00 HTR", + "extra": { + "requestId": ".", + "facilitatorUrl": "https://…" // optional + } + }] } ``` -The client picks whichever token it holds. The escrow blueprint is token-agnostic — it works with any Hathor token. - -## Quick Start +The client retries with a `PAYMENT-SIGNATURE` header (base64-encoded JSON): -### Prerequisites - -- Node.js 18+ -- [Hathor Forge](https://github.com/HathorNetwork/hathor-forge) (local blockchain) - -### 1. Start Hathor Forge - -```bash -hathor-forge-cli --start +```jsonc +{ + "x402Version": 2, + "scheme": "hathor-direct", + "network": "hathor:testnet", + "payload": { + "txId": "000abc…", + "payerAddress": "WPo2…", + "signature": "BASE64…", + "requestId": "." + } +} ``` -### 2. Create and fund wallets +## Components -```bash -hathor-forge create-wallet buyer -hathor-forge create-wallet facilitator -hathor-forge create-wallet seller -hathor-forge fund-wallet buyer --amount 100 -hathor-forge fund-wallet facilitator --amount 10 -``` - -### 3. Publish the blueprint +| Component | File | Port | What it does | +|---|---|---|---| +| **Resource server** | `resource-server.js` | 3000 | Paid `/weather` (direct) + `/generate` (upto). Self-verifies via `verifier.js`. | +| **Facilitator** (optional) | `facilitator.js` | 8402 | Thin HTTP wrapper around the verifier. No wallet, no seeds, no nano contracts. | +| **Verifier** | `verifier.js` | — | Single source of truth for "is this payment claim valid?" | +| **Dedup store** | `dedupStore.js` + SQLite | — | Atomic `(txId, outputIndex)` ledger + payer blocklist. | +| **requestId** | `requestId.js` | — | Stateless HMAC challenge token (binds payment ↔ request). | +| **Void watcher** | `voidWatcher.js` | — | Background detection of double-spent payments → blocklist. | +| **Refund issuer** | `refundIssuer.js` | — | Calls the seller's wallet-headless to issue upto refunds. | +| **CLI client** | `client.js` | — | Buyer-side smoke test using `@hathor/wallet-lib`. | +| **dApp** | `dapp/` | 3000 | Browser client (Next.js + WalletConnect/Reown + MetaMask Snap). | +| **MCP example** | `examples/mcp-server/` | stdio | Paid MCP tool gated by `hathor-direct`. | + +## Quick start ```bash -hathor-forge publish-blueprint facilitator --code blueprint/x402_escrow.py -# Note the returned blueprint_id -``` - -### 4. Configure and run +# 0. Fund a Hathor address on testnet (faucet) — that's the seller address. +# Generate a seed for the seller wallet (only needed for the upto scheme). -```bash cp .env.example .env -# Edit .env with your wallet addresses and blueprint_id - -npm install - -# Terminal 1: Facilitator -node facilitator.js - -# Terminal 2: Resource server -node resource-server.js - -# Terminal 3: Client -node client.js -``` +$EDITOR .env # set SELLER_ADDRESS, SELLER_SEED, SERVER_SECRET -### 5. Or use the dApp +docker compose up --build +# -> wallet-headless on :8000 (seller wallet) +# -> resource-server on :3000 (paid /weather, /generate) +# -> dapp on :4020 -```bash -cd dapp -npm install -npm run dev -# Open http://localhost:3000, connect wallet, fetch a paid URL -``` - -## Project Structure - -``` -x402-poc/ -├── blueprint/ -│ └── x402_escrow.py # Escrow nano contract (Python 3.11) -├── facilitator.js # Verify + settle service (:8402) -├── resource-server.js # Example paid API (:3000) -├── client.js # Programmatic x402 client -├── config.js # Shared config (env vars) -├── helpers.js # HTTP helpers -├── dapp/ # Browser-based x402 client (Next.js) -│ ├── app/ # Pages (dashboard, escrow detail) -│ ├── components/ # X402Fetch, EscrowList, EscrowDetail -│ ├── contexts/ # Wallet, Hathor, WalletConnect providers -│ └── lib/ # Config, API, escrow store -├── Dockerfile -├── .env.example -└── package.json +# Browser: http://localhost:4020 — connect WalletConnect, fetch the paid URL. +# CLI: BUYER_SEED='...' node client.js --route weather ``` -## What's next - -This is a POC. A production implementation would add: +## What this PoC is NOT -- **`@hathor/x402-client`** — npm package wrapping `fetch()` to handle 402 automatically ([RFC](https://github.com/HathorNetwork/rfcs/blob/feat/x402-support/projects/x402/0002-x402-client-sdk.md)) -- **`@hathor/x402-server`** — Express middleware to add x402 to any API in 3 lines ([RFC](https://github.com/HathorNetwork/rfcs/blob/feat/x402-support/projects/x402/0003-x402-server-middleware.md)) -- **Facilitator as headless plugin** — runs inside `hathor-wallet-headless`, not as a separate server -- **Hosted public facilitator** — so sellers don't need to run their own -- **Mempool-aware verification** — verify escrow before block confirmation (~1s instead of ~10s) -- **Payment channels** — pre-funded escrows for repeat clients (eliminates per-request latency) +- **Not production-ready.** Idempotent retry response caching, blocklist + sharing, structured logging, metrics, key rotation for `SERVER_SECRET` + are all deferred. +- **Not confidential-transaction-enabled.** Hathor's shielded outputs are + alpha and out of mainnet — the design is *compatible* with future CT but + this PoC doesn't exercise it. +- **No protocol-level refund** beyond the upto remainder. If the server takes + the payment and doesn't deliver, there is no on-chain recovery — same trust + model as EVM `exact`. Reputation + small amounts + amount caps is the + bounding mechanism. ## References -- [x402 Protocol Specification](https://www.x402.org/) -- [RFC: x402 Support for Hathor Network](https://github.com/HathorNetwork/rfcs/blob/feat/x402-support/projects/x402/0001-x402-support.md) -- [RFC: x402 Client SDK](https://github.com/HathorNetwork/rfcs/blob/feat/x402-support/projects/x402/0002-x402-client-sdk.md) -- [RFC: x402 Server Middleware](https://github.com/HathorNetwork/rfcs/blob/feat/x402-support/projects/x402/0003-x402-server-middleware.md) -- [Hathor Nano Contracts](https://hathor.network/resources/nano-contracts/) -- [Hathor Forge](https://github.com/HathorNetwork/hathor-forge) — Local development environment -- [create-hathor-dapp](https://github.com/HathorNetwork/create-hathor-dapp) — dApp scaffolding template +- Design proposal: [`../x402-hathor-no-nc-proposal.md`](../x402-hathor-no-nc-proposal.md) +- x402 specification: +- x402 v1 → v2 migration: +- Hathor wallet-lib `signMessage`/`verifyMessage`: + `hathor-wallet-lib/src/utils/crypto.ts` +- Hathor RPC methods (`htr_sendTransaction`, `htr_signWithAddress`): + `hathor-rpc-lib/packages/hathor-rpc-handler/src/types/rpcRequest.ts` ## License diff --git a/blueprint/x402_channel.py b/blueprint/x402_channel.py deleted file mode 100644 index 670c6c2..0000000 --- a/blueprint/x402_channel.py +++ /dev/null @@ -1,95 +0,0 @@ -from hathor import ( - Address, Amount, Blueprint, Context, NCDepositAction, NCFail, - NCWithdrawalAction, Timestamp, TokenUid, export, public, view -) - -PHASE_OPEN = 'OPEN' -PHASE_CLOSED = 'CLOSED' - - -@export -class X402Channel(Blueprint): - buyer: Address - facilitator: Address - token_uid: TokenUid - total_deposited: Amount - total_spent: Amount - phase: str - deadline: Timestamp - - @public(allow_deposit=True) - def initialize( - self, - ctx: Context, - facilitator: Address, - token_uid: TokenUid, - deadline: Timestamp, - ) -> None: - action = ctx.get_single_action(token_uid) - if not isinstance(action, NCDepositAction): - raise NCFail("Must include a deposit action") - - self.buyer = ctx.get_caller_address() - self.facilitator = facilitator - self.token_uid = token_uid - self.total_deposited = action.amount - self.total_spent = 0 - self.phase = PHASE_OPEN - self.deadline = deadline - - @public(allow_withdrawal=True) - def spend(self, ctx: Context, amount: Amount, seller: Address) -> None: - caller = ctx.get_caller_address() - if caller != self.facilitator: - raise NCFail("Only the facilitator can spend") - if self.phase != PHASE_OPEN: - raise NCFail("Channel is not open") - if self.total_spent + amount > self.total_deposited: - raise NCFail("Insufficient channel balance") - - action = ctx.get_single_action(self.token_uid) - if not isinstance(action, NCWithdrawalAction): - raise NCFail("Must include a withdrawal action") - if action.amount != amount: - raise NCFail("Withdrawal amount must match spend amount") - - self.total_spent = self.total_spent + amount - - @public(allow_deposit=True) - def top_up(self, ctx: Context) -> None: - caller = ctx.get_caller_address() - if caller != self.buyer: - raise NCFail("Only the buyer can top up") - if self.phase != PHASE_OPEN: - raise NCFail("Channel is not open") - - action = ctx.get_single_action(self.token_uid) - if not isinstance(action, NCDepositAction): - raise NCFail("Must include a deposit action") - - self.total_deposited = self.total_deposited + action.amount - - @public(allow_withdrawal=True) - def close(self, ctx: Context) -> None: - caller = ctx.get_caller_address() - - if self.phase != PHASE_OPEN: - raise NCFail("Channel is already closed") - - if caller != self.buyer and caller != self.facilitator: - if ctx.block.timestamp < self.deadline: - raise NCFail("Only buyer or facilitator can close before deadline") - - remaining = self.total_deposited - self.total_spent - if remaining > 0: - action = ctx.get_single_action(self.token_uid) - if not isinstance(action, NCWithdrawalAction): - raise NCFail("Must include a withdrawal action") - if action.amount != remaining: - raise NCFail("Must withdraw exact remaining balance") - - self.phase = PHASE_CLOSED - - @view - def get_remaining(self) -> Amount: - return self.total_deposited - self.total_spent diff --git a/blueprint/x402_escrow.py b/blueprint/x402_escrow.py deleted file mode 100644 index 5563afc..0000000 --- a/blueprint/x402_escrow.py +++ /dev/null @@ -1,117 +0,0 @@ -from hathor import ( - Address, Amount, Blueprint, Context, NCDepositAction, NCFail, - NCWithdrawalAction, Timestamp, TokenUid, export, public, view -) - -PHASE_LOCKED = 'LOCKED' -PHASE_RELEASED = 'RELEASED' -PHASE_REFUNDED = 'REFUNDED' - - -@export -class X402Escrow(Blueprint): - buyer: Address - seller: Address - facilitator: Address - token_uid: TokenUid - amount: Amount - phase: str - deadline: Timestamp - resource_url: str - request_hash: str - - @public(allow_deposit=True) - def initialize( - self, - ctx: Context, - seller: Address, - facilitator: Address, - token_uid: TokenUid, - deadline: Timestamp, - resource_url: str, - request_hash: str, - ) -> None: - action = ctx.get_single_action(token_uid) - if not isinstance(action, NCDepositAction): - raise NCFail("Must include a deposit action") - - self.buyer = ctx.get_caller_address() - self.seller = seller - self.facilitator = facilitator - self.token_uid = token_uid - self.amount = action.amount - self.phase = PHASE_LOCKED - self.deadline = deadline - self.resource_url = resource_url - self.request_hash = request_hash - - @public(allow_withdrawal=True) - def release(self, ctx: Context) -> None: - # Exact release: withdraw the entire escrow amount to the seller. - # Used by the "hathor-escrow" (exact) scheme. - caller = ctx.get_caller_address() - if caller != self.facilitator: - raise NCFail("Only the facilitator can release funds") - if self.phase != PHASE_LOCKED: - raise NCFail("Escrow is not locked") - - action = ctx.get_single_action(self.token_uid) - if not isinstance(action, NCWithdrawalAction): - raise NCFail("Must include a withdrawal action") - if action.amount != self.amount: - raise NCFail("Withdrawal amount must equal escrow amount") - - self.phase = PHASE_RELEASED - - @public(allow_withdrawal=True) - def release_upto(self, ctx: Context, charged_amount: Amount) -> None: - # Partial release: withdraw `charged_amount` to the seller and leave the - # remainder locked so the buyer (or facilitator) can claim it back via - # refund(). Used by the "hathor-escrow-upto" scheme. - # - # After this call, self.amount becomes the remainder. If the remainder - # is zero, the phase transitions to RELEASED. Otherwise the phase stays - # LOCKED and the remaining amount can be refunded to the buyer using - # the existing refund() flow. - caller = ctx.get_caller_address() - if caller != self.facilitator: - raise NCFail("Only the facilitator can release funds") - if self.phase != PHASE_LOCKED: - raise NCFail("Escrow is not locked") - if charged_amount <= 0: - raise NCFail("charged_amount must be positive") - if charged_amount > self.amount: - raise NCFail("charged_amount exceeds escrow amount") - - action = ctx.get_single_action(self.token_uid) - if not isinstance(action, NCWithdrawalAction): - raise NCFail("Must include a withdrawal action") - if action.amount != charged_amount: - raise NCFail("Withdrawal amount must equal charged_amount") - - self.amount = self.amount - charged_amount - if self.amount == 0: - self.phase = PHASE_RELEASED - - @public(allow_withdrawal=True) - def refund(self, ctx: Context) -> None: - caller = ctx.get_caller_address() - - if self.phase != PHASE_LOCKED: - raise NCFail("Escrow is not locked") - - if caller != self.buyer and caller != self.facilitator: - if ctx.block.timestamp < self.deadline: - raise NCFail("Only buyer or facilitator can refund before deadline") - - action = ctx.get_single_action(self.token_uid) - if not isinstance(action, NCWithdrawalAction): - raise NCFail("Must include a withdrawal action") - if action.amount != self.amount: - raise NCFail("Withdrawal amount must equal escrow amount") - - self.phase = PHASE_REFUNDED - - @view - def get_phase(self) -> str: - return self.phase diff --git a/client.js b/client.js index 0915341..2d73316 100644 --- a/client.js +++ b/client.js @@ -1,152 +1,176 @@ -// x402 Client (Buyer / AI Agent) -// Demonstrates the full x402 payment flow: -// 1. Request resource -> get 402 -// 2. Pick a payment option from the accepts array -// 3. Create escrow nano contract (deposit funds) -// 4. Retry request with payment proof -// 5. Receive resource +// x402 buyer CLI — non-browser smoke test for the hathor-direct flow. +// +// Uses @hathor/wallet-lib directly (no wallet-headless dependency) because: +// 1. We need wallet.signMessageWithAddress(), which the headless HTTP API +// doesn't expose today. +// 2. A single-process CLI is the simplest "agent making a paid request". // // Usage: -// node client.js # pay with first accepted token (HTR) -// node client.js --token htr # pay with HTR explicitly -// node client.js --token custom # pay with the custom token (e.g. hUSDC) +// BUYER_SEED='abandon abandon ...' node client.js [--route weather|generate] +// BUYER_SEED='...' node client.js --url http://localhost:3000/weather +// +// Requires the buyer wallet to be funded on the configured network (testnet +// faucet is sufficient). + +'use strict'; -const fetch = require('node-fetch'); const config = require('./config'); -const { walletRequest, waitForTxConfirmation, log } = require('./helpers'); +const { log } = require('./helpers'); -// Parse --token arg -const tokenArg = process.argv.find(a => a.startsWith('--token='))?.split('=')[1] - || (process.argv.includes('--token') ? process.argv[process.argv.indexOf('--token') + 1] : null); +const hathorLib = require('@hathor/wallet-lib'); +const { HathorWallet, Network } = hathorLib; -function pickPaymentOption(accepts) { - if (tokenArg === 'custom' && config.customTokenUid) { - const match = accepts.find(a => a.asset === config.customTokenUid); - if (match) return match; - log('CLIENT', `Custom token ${config.customTokenUid} not accepted, falling back`); - } - if (tokenArg === 'htr') { - const match = accepts.find(a => a.asset === '00'); - if (match) return match; +// --- args ------------------------------------------------------------------- + +function parseArgs(argv) { + const out = { route: 'weather', url: null }; + for (let i = 2; i < argv.length; i++) { + const a = argv[i]; + if (a === '--route') out.route = argv[++i]; + else if (a.startsWith('--route=')) out.route = a.split('=')[1]; + else if (a === '--url') out.url = argv[++i]; + else if (a.startsWith('--url=')) out.url = a.split('=')[1]; } - // Default: pick first option - return accepts[0]; + return out; } -async function main() { - log('CLIENT', '=== x402 Payment Flow Demo ==='); - log('CLIENT', `Buyer address: ${config.buyerAddress}`); - log('CLIENT', ''); +const args = parseArgs(process.argv); +const url = args.url || `http://localhost:${config.resourceServerPort}/${args.route}`; - // Step 1: Request the paid resource (expect 402) - log('CLIENT', 'Step 1: Requesting weather data...'); - const initialResp = await fetch(`http://localhost:${config.resourceServerPort}/weather`); +if (!process.env.BUYER_SEED) { + log('CLIENT', 'BUYER_SEED is required. Export a 24-word seed.'); + process.exit(1); +} - if (initialResp.status !== 402) { - log('CLIENT', `Expected 402 but got ${initialResp.status}`); - process.exit(1); - } +// --- wallet bootstrap ------------------------------------------------------- - const paymentRequired = await initialResp.json(); - log('CLIENT', `Got 402 Payment Required`); - log('CLIENT', ` ${paymentRequired.accepts.length} payment option(s) available:`); - for (const opt of paymentRequired.accepts) { - log('CLIENT', ` - ${opt.description} (asset: ${opt.asset}, price: ${opt.price})`); - } - log('CLIENT', ''); - - // Step 2: Pick a payment option - const chosen = pickPaymentOption(paymentRequired.accepts); - log('CLIENT', `Step 2: Chose payment option: ${chosen.description}`); - log('CLIENT', ` Asset: ${chosen.asset}`); - log('CLIENT', ` Price: ${chosen.price}`); - log('CLIENT', ` Pay to: ${chosen.payTo}`); - log('CLIENT', ` Facilitator: ${chosen.extra.facilitatorAddress}`); - log('CLIENT', ''); - - // Step 3: Create escrow nano contract (deposit funds) - log('CLIENT', 'Step 3: Creating escrow nano contract...'); - - const deadline = Math.floor(Date.now() / 1000) + chosen.extra.deadlineSeconds; - const amount = parseInt(chosen.price); - - const createResult = await walletRequest('POST', '/wallet/nano-contracts/create', { - blueprint_id: chosen.extra.blueprintId, - address: config.buyerAddress, - data: { - args: [ - chosen.payTo, // seller - chosen.extra.facilitatorAddress, // facilitator - chosen.asset, // token_uid - deadline, // deadline - chosen.resource, // resource_url - 'poc-request-hash', // request_hash - ], - actions: [{ - type: 'deposit', - token: chosen.asset, - amount: amount, - }], - }, - }, config.buyerWalletId); +async function startWallet() { + log('CLIENT', `Starting wallet on ${config.network} (this can take a moment to sync)...`); + + const network = new Network(config.network); + const wallet = new HathorWallet({ + seed: process.env.BUYER_SEED, + server: `${config.fullnodeUrl}/v1a/`, + network, + pinCode: '000000', // local-only POC PIN + password: 'x402-poc', // protects in-memory key material + }); - if (!createResult.success) { - log('CLIENT', `Failed to create escrow: ${JSON.stringify(createResult)}`); - process.exit(1); + await wallet.start({ pinCode: '000000', password: 'x402-poc' }); + + // Wait until READY (state 3). The lib polls history; on a quiet wallet this + // is sub-second, on a heavily used one it can take longer. + const start = Date.now(); + while (true) { + const ready = wallet.isReady?.() ?? (wallet.state === 3); + if (ready) break; + if (Date.now() - start > 120_000) throw new Error('wallet failed to reach READY in 120s'); + await new Promise((r) => setTimeout(r, 500)); } - const ncId = createResult.hash; - log('CLIENT', `Escrow created! ncId=${ncId}`); - log('CLIENT', 'Waiting for tx confirmation...'); + log('CLIENT', 'Wallet READY.'); + return wallet; +} - await waitForTxConfirmation(ncId); - log('CLIENT', 'Escrow tx confirmed on-chain'); - log('CLIENT', ''); +// --- 402 + payment flow ----------------------------------------------------- - // Step 4: Retry request with payment proof - log('CLIENT', 'Step 4: Retrying request with payment proof...'); +async function fetch402() { + const resp = await fetch(url); + if (resp.status !== 402) { + throw new Error(`expected 402, got ${resp.status}`); + } + const body = await resp.json(); + if (!body.accepts || !body.accepts.length) throw new Error('no accepts in 402 body'); + return body.accepts[0]; +} - const paymentPayload = { +async function pay(wallet, accept) { + const buyer = await wallet.getCurrentAddress({ markAsUsed: false }); + log('CLIENT', `Buyer address: ${buyer.address} (index ${buyer.index})`); + + log('CLIENT', `Paying ${(parseInt(accept.amount, 10) / 100).toFixed(2)} ${accept.asset === '00' ? 'HTR' : accept.asset} → ${accept.payTo}`); + + const sendTx = await wallet.sendManyOutputsSendTransaction( + [ + { + address: accept.payTo, + value: parseInt(accept.amount, 10), + token: accept.asset || '00', + }, + ], + { + changeAddress: buyer.address, + pinCode: '000000', + } + ); + const tx = await sendTx.run(); + const txId = tx?.hash || tx?.txId; + if (!txId) throw new Error('no txId returned from sendTransaction'); + log('CLIENT', `Broadcast tx ${txId}`); + + log('CLIENT', `Signing requestId with address index ${buyer.index} ...`); + const signature = await wallet.signMessageWithAddress( + accept.extra.requestId, + buyer.index, + '000000' + ); + + return { txId, payerAddress: buyer.address, signature }; +} + +async function retry(accept, { txId, payerAddress, signature }) { + const payload = { x402Version: 2, - scheme: 'hathor-escrow', - network: `hathor:${config.network}`, + scheme: accept.scheme, + network: accept.network, payload: { - ncId: ncId, - depositTxId: ncId, - buyerAddress: config.buyerAddress, + txId, + payerAddress, + signature, + requestId: accept.extra.requestId, }, }; + const headerB64 = Buffer.from(JSON.stringify(payload)).toString('base64'); - const paidResp = await fetch(`http://localhost:${config.resourceServerPort}/weather`, { - headers: { - 'PAYMENT-SIGNATURE': Buffer.from(JSON.stringify(paymentPayload)).toString('base64'), - }, - }); - - if (paidResp.status !== 200) { - const err = await paidResp.json(); - log('CLIENT', `Payment rejected: ${JSON.stringify(err)}`); - process.exit(1); + log('CLIENT', 'Retrying GET with PAYMENT-SIGNATURE ...'); + const resp = await fetch(url, { headers: { 'PAYMENT-SIGNATURE': headerB64 } }); + const body = await resp.json(); + if (!resp.ok) { + throw new Error(`server rejected payment: ${JSON.stringify(body)}`); } + return body; +} - const result = await paidResp.json(); - log('CLIENT', ''); - log('CLIENT', '=== Resource Received! ==='); - log('CLIENT', JSON.stringify(result.data, null, 2)); - log('CLIENT', ''); - log('CLIENT', `Payment ncId: ${result.payment.ncId}`); - log('CLIENT', ''); - log('CLIENT', 'Waiting a few seconds for settlement to complete...'); - - // Give the async settlement time to complete - await new Promise(r => setTimeout(r, 15000)); +// --- main ------------------------------------------------------------------- - log('CLIENT', ''); - log('CLIENT', '=== x402 Payment Flow Complete ==='); +async function main() { + log('CLIENT', `=== x402 hathor-direct demo — route=${args.route} ===`); + log('CLIENT', `Target URL: ${url}`); + + const wallet = await startWallet(); + try { + const accept = await fetch402(); + log('CLIENT', `402 received — scheme=${accept.scheme} amount=${accept.amount}`); + + const proof = await pay(wallet, accept); + const result = await retry(accept, proof); + + log('CLIENT', ''); + log('CLIENT', '=== resource ==='); + log('CLIENT', JSON.stringify(result.data, null, 2)); + log('CLIENT', ''); + if (result.payment) { + log('CLIENT', '=== payment ==='); + log('CLIENT', JSON.stringify(result.payment, null, 2)); + } + } finally { + try { await wallet.stop(); } catch (_) { /* ignore */ } + } } -main().catch(err => { - log('CLIENT', `Error: ${err.message}`); +main().catch((err) => { + log('CLIENT', `ERROR: ${err.message}`); + // eslint-disable-next-line no-console console.error(err); process.exit(1); }); diff --git a/config.js b/config.js index 1dda4c6..8c414bc 100644 --- a/config.js +++ b/config.js @@ -1,43 +1,55 @@ -// x402 POC Configuration -// Override any value with environment variables +// x402 PoC Configuration (hathor-direct scheme — no nano contracts). +// All knobs are overrideable via environment variables. + +'use strict'; const env = process.env; +const int = (v, dflt) => { + const n = parseInt(v, 10); + return Number.isFinite(n) ? n : dflt; +}; + module.exports = { - // Hathor services - fullnodeUrl: env.FULLNODE_URL || 'http://127.0.0.1:8080', - walletHeadlessUrl: env.WALLET_HEADLESS_URL || 'http://localhost:8000', + // Hathor fullnode (read-only) — used by the verifier and the dApp. + fullnodeUrl: env.FULLNODE_URL || 'https://node1.testnet.hathor.network', + network: env.HATHOR_NETWORK || 'testnet', + htrTokenUid: '00', - // Blueprints published on-chain - blueprintId: env.BLUEPRINT_ID || '', - channelBlueprintId: env.CHANNEL_BLUEPRINT_ID || '', + // Resource server + resourceServerPort: int(env.RESOURCE_SERVER_PORT, 3000), + resourceServerPublicUrl: env.RESOURCE_SERVER_PUBLIC_URL || 'http://localhost:3000', - // Wallet IDs (must be pre-created in wallet-headless) - buyerWalletId: env.BUYER_WALLET_ID || 'buyer', - facilitatorWalletId: env.FACILITATOR_WALLET_ID || 'facilitator', - sellerWalletId: env.SELLER_WALLET_ID || 'seller', + // Standalone facilitator (optional in compose — only used when VERIFY_MODE=facilitator) + facilitatorPort: int(env.FACILITATOR_PORT, 8402), + facilitatorUrl: env.FACILITATOR_URL || `http://localhost:${int(env.FACILITATOR_PORT, 8402)}`, - // Addresses (first address of each wallet) - buyerAddress: env.BUYER_ADDRESS || '', - facilitatorAddress: env.FACILITATOR_ADDRESS || '', + // The seller's receiving address. Static config — the resource server never + // touches a wallet for the exact scheme. For the upto scheme, a seller-side + // wallet-headless issues the refund tx (see refundIssuer.js). sellerAddress: env.SELLER_ADDRESS || '', - // Token UIDs - htrTokenUid: '00', - customTokenUid: env.CUSTOM_TOKEN_UID || '', - - // Service URLs and ports - facilitatorUrl: env.FACILITATOR_URL || `http://localhost:${env.FACILITATOR_PORT || '8402'}`, - facilitatorPublicUrl: env.FACILITATOR_PUBLIC_URL || env.FACILITATOR_URL || `http://localhost:${env.FACILITATOR_PORT || '8402'}`, - resourceServerPublicUrl: env.RESOURCE_SERVER_PUBLIC_URL || `http://localhost:${env.RESOURCE_SERVER_PORT || '3000'}`, - network: env.HATHOR_NETWORK || 'privatenet', - facilitatorPort: parseInt(env.FACILITATOR_PORT || '8402'), - resourceServerPort: parseInt(env.RESOURCE_SERVER_PORT || '3000'), - - // Escrow settings - escrowDeadlineSeconds: parseInt(env.ESCROW_DEADLINE_SECONDS || '300'), - - // Payment amounts (in smallest unit — 1 HTR = 100, 1 hUSDC = 100) - htrPaymentAmount: parseInt(env.HTR_PAYMENT_AMOUNT || '100'), - customTokenPaymentAmount: parseInt(env.CUSTOM_TOKEN_PAYMENT_AMOUNT || '1000'), + // Seller wallet-headless (only used by the upto scheme to issue refunds). + sellerWalletUrl: env.SELLER_WALLET_URL || 'http://wallet-headless:8000', + sellerWalletId: env.SELLER_WALLET_ID || 'seller', + + // Server secret used to HMAC requestIds. Falls back to an ephemeral random + // value with a warning at startup if unset — fine for local dev, not for prod. + serverSecret: env.SERVER_SECRET || '', + requestIdTtlSeconds: int(env.REQUEST_ID_TTL_SECONDS, 120), + + // Dedup + blocklist store (better-sqlite3 file). + dedupDbPath: env.DEDUP_DB_PATH || './data/payments.sqlite', + + // Zero-conf safety threshold: amounts above this require meta.first_block. + // Default is "no cap" so all amounts use zero-conf; set lower in prod. + zeroConfMaxAmount: int(env.ZERO_CONF_MAX_AMOUNT, Number.MAX_SAFE_INTEGER), + + // Verify path: 'self' (resource-server imports verifier directly) or + // 'facilitator' (resource-server calls /x402/verify over HTTP). + verifyMode: env.VERIFY_MODE === 'facilitator' ? 'facilitator' : 'self', + + // Default per-route prices (atomic units; 1 HTR = 100). + htrPaymentAmount: int(env.HTR_PAYMENT_AMOUNT, 100), + generateMaxPrice: int(env.GENERATE_MAX_PRICE, 500), }; diff --git a/dapp/.env.example b/dapp/.env.example index 0a77d09..a0fa718 100644 --- a/dapp/.env.example +++ b/dapp/.env.example @@ -1,43 +1,35 @@ # =========================================== -# Hathor dApp Configuration +# x402 Hathor dApp Configuration # =========================================== -# WalletConnect Project ID (Required) -# Get your project ID from https://cloud.walletconnect.com/ +# WalletConnect / Reown Project ID (Required) +# Get yours from https://cloud.walletconnect.com/ NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=your_project_id_here # =========================================== -# Network Configuration +# Network # =========================================== # Default network: 'testnet' or 'mainnet' NEXT_PUBLIC_DEFAULT_NETWORK=testnet -# Enable mock wallet for development (no real wallet needed) +# Enable mock wallet for UI development (no real wallet needed) NEXT_PUBLIC_USE_MOCK_WALLET=false -# Hathor Node URLs (optional - uses defaults if not set) +# Hathor fullnode URLs (per network) NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET=https://node1.testnet.hathor.network/v1a NEXT_PUBLIC_HATHOR_NODE_URL_MAINNET=https://node1.mainnet.hathor.network/v1a # =========================================== -# Contract Configuration +# x402 resource server # =========================================== -# Contract IDs for each network (JSON array format) -# Add your nano contract IDs here -NEXT_PUBLIC_CONTRACT_IDS_TESTNET=[] -NEXT_PUBLIC_CONTRACT_IDS_MAINNET=[] - -# Legacy format (still supported) -# NEXT_PUBLIC_CONTRACT_IDS=["your_contract_id_here"] +# Where the dApp will fetch paid resources from. The URL input box is seeded +# with `${NEXT_PUBLIC_RESOURCE_SERVER_URL}/weather` by default. +NEXT_PUBLIC_RESOURCE_SERVER_URL=http://localhost:3000 # =========================================== -# App Metadata (Optional) +# App metadata (shown in WalletConnect modals) # =========================================== - -# App name displayed in WalletConnect -NEXT_PUBLIC_APP_NAME=Hathor dApp - -# App description for WalletConnect -NEXT_PUBLIC_APP_DESCRIPTION=Decentralized application on Hathor Network +NEXT_PUBLIC_APP_NAME=x402 Client +NEXT_PUBLIC_APP_DESCRIPTION=x402 hathor-direct payment client (no nano contracts) diff --git a/dapp/.env.local.example b/dapp/.env.local.example index 5a2f7b8..b2a62a4 100644 --- a/dapp/.env.local.example +++ b/dapp/.env.local.example @@ -1,16 +1,12 @@ -# Wallet Configuration -# Set to true to use mock wallet for development/testing +# Local dev quick-start — uses the mock wallet so you don't need a real wallet. NEXT_PUBLIC_USE_MOCK_WALLET=true -# Network Configuration -# Options: 'india-testnet' or 'mainnet' -NEXT_PUBLIC_DEFAULT_NETWORK=india-testnet +# Network +NEXT_PUBLIC_DEFAULT_NETWORK=testnet -# Hathor Node URLs -NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET=https://node1.india-testnet.hathor.network/v1a +# Hathor node URLs +NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET=https://node1.testnet.hathor.network/v1a NEXT_PUBLIC_HATHOR_NODE_URL_MAINNET=https://node1.mainnet.hathor.network/v1a -# Contract IDs -# Add your deployed contract IDs as a JSON array -# Example: ["0abc123...", "def456..."] -NEXT_PUBLIC_CONTRACT_IDS=[] +# Where /weather, /generate live (the local resource-server) +NEXT_PUBLIC_RESOURCE_SERVER_URL=http://localhost:3000 diff --git a/dapp/AGENTS.md b/dapp/AGENTS.md index 3da84aa..f660af8 100644 --- a/dapp/AGENTS.md +++ b/dapp/AGENTS.md @@ -1,439 +1,124 @@ -# AGENTS.md — LLM Instructions for Hathor dApp +# AGENTS.md — LLM instructions for the x402 Hathor dApp -This document is the single source of truth for AI agents building dApps from this template. Follow it step by step. +Source of truth for AI agents (LLMs/IDEs) extending or fixing this dApp. -## Quick Reference +## Snapshot -| What | Where | -|------|-------| +| Concept | Where | +|---|---| | WalletConnect Project ID | `.env.local` → `NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID` | -| Contract IDs (testnet) | `.env.local` → `NEXT_PUBLIC_CONTRACT_IDS_TESTNET` | -| Contract IDs (mainnet) | `.env.local` → `NEXT_PUBLIC_CONTRACT_IDS_MAINNET` | -| App name & description | `.env.local` → `NEXT_PUBLIC_APP_NAME` / `NEXT_PUBLIC_APP_DESCRIPTION` | | Default network | `.env.local` → `NEXT_PUBLIC_DEFAULT_NETWORK` | -| Mock mode (no wallet) | `.env.local` → `NEXT_PUBLIC_USE_MOCK_WALLET=true` | +| Mock wallet | `.env.local` → `NEXT_PUBLIC_USE_MOCK_WALLET=true` | +| Resource server URL | `.env.local` → `NEXT_PUBLIC_RESOURCE_SERVER_URL` | | Main page | `app/page.tsx` | -| Add new pages | `app/your-page/page.tsx` | -| Add components | `components/` | -| Contract state types | `types/hathor.ts` → `ContractState` | -| Contract state fields | `lib/hathorCoreAPI.ts` → `getContractState()` | -| Page title & metadata | `app/layout.tsx` → `metadata` | -| Header app name | `app/page.tsx` → `
` | -| WalletConnect metadata | `lib/walletConnectConfig.ts` | -| App icon | `public/images/icon.png` | -| Favicon | `public/favicon.png` | +| Payment detail | `app/payment/[txId]/page.tsx` | +| The whole flow | `components/X402Fetch.tsx` | +| RPC wrappers | `lib/hathorRPC.ts` (`sendTransaction`, `signWithAddress`, `getAddress`, `getBalance`) | +| Wallet ctx | `contexts/WalletContext.tsx` | +| Hathor ctx | `contexts/HathorContext.tsx` | +| Local history | `lib/paymentHistory.ts` | -## Step 1: Configure Environment +## Available wallet RPC methods -The `.env.local` file controls all runtime configuration. Edit it directly — do not modify `lib/config.ts` unless adding new env vars. +All implemented today across the wallet stack (desktop / mobile / MetaMask +snap). Use them via the typed wrappers in `lib/hathorRPC.ts` and exposed +through `useWallet()` in `contexts/WalletContext.tsx`. -```env -# REQUIRED: Get from https://cloud.walletconnect.com/ -# Create a project → copy the Project ID -NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=your_project_id_here +| RPC | Wrapper | When to call | +|---|---|---| +| `htr_getAddress` | `getAddress({network, type})` | Before sending/signing, to get an empty address + index | +| `htr_sendTransaction` | `sendTransaction({network, outputs, push_tx, changeAddress?})` | Pay the seller for a 402 | +| `htr_signWithAddress` | `signWithAddress({network, message, addressIndex})` | Sign the server's `requestId` | +| `htr_getBalance` | `getBalance({network, tokens})` | Show the balance card | +| `htr_getConnectedNetwork` | `getConnectedNetwork()` | Connection diagnostics | -# Network: 'testnet' or 'mainnet' -NEXT_PUBLIC_DEFAULT_NETWORK=testnet +## The x402 flow (single source of truth) -# Set to true during development to skip real wallet connection -NEXT_PUBLIC_USE_MOCK_WALLET=true +```ts +// 1. Fetch the URL. +const r = await fetch(url, { mode: 'cors' }); +if (r.status !== 402) return r; -# Your deployed nano contract IDs (JSON array) -NEXT_PUBLIC_CONTRACT_IDS_TESTNET=["000001a2b3c4d5e6..."] -NEXT_PUBLIC_CONTRACT_IDS_MAINNET=[] +// 2. Pick the first accept option. +const accept = (await r.json()).accepts[0]; -# App metadata shown in WalletConnect modal -NEXT_PUBLIC_APP_NAME=My dApp Name -NEXT_PUBLIC_APP_DESCRIPTION=Description of my dApp +// 3. Grab an empty address + index. We use it as changeAddress so it appears +// in the tx (the verifier accepts the signing address in either inputs or +// outputs), and as addressIndex when signing. +const buyer = await getAddress({ network, type: 'first_empty' }); -# Custom node URLs (optional — defaults work for most cases) -# NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET=https://node1.testnet.hathor.network/v1a -# NEXT_PUBLIC_HATHOR_NODE_URL_MAINNET=https://node1.mainnet.hathor.network/v1a -``` - -**Important**: Mock mode (`NEXT_PUBLIC_USE_MOCK_WALLET=true`) lets you develop and test the UI without a real wallet. It simulates connections, balances, and transactions. Set to `false` when ready for real wallet testing. - -## Step 2: Set App Identity +// 4. Send the payment. +const sendResp = await sendTransaction({ + network, + outputs: [{ address: accept.payTo, value: parseInt(accept.amount, 10), + token: accept.asset === '00' ? undefined : accept.asset }], + changeAddress: buyer.address, + push_tx: true, +}); +const txId = HathorRPCService.extractTxId(sendResp); -Update these files to brand the dApp: +// 5. Wait for the fullnode to see the tx (~1–2s, no first_block required). +await pollMempool(nodeUrl, txId); -**`app/layout.tsx`** — Page title and SEO: -```typescript -export const metadata: Metadata = { - title: 'Your App Name', - description: 'Your app description', -}; -``` +// 6. Sign the requestId. +const signed = await signWithAddress({ + network, message: accept.extra.requestId, addressIndex: buyer.index, +}); -**`app/page.tsx`** — Header display name: -```tsx -
+// 7. Retry with the proof. +const headerB64 = btoa(JSON.stringify({ + x402Version: 2, scheme: accept.scheme, network: accept.network, + payload: { + txId, payerAddress: signed.address.address, + signature: signed.signature, requestId: accept.extra.requestId, + }, +})); +const r2 = await fetch(url, { mode: 'cors', headers: { 'PAYMENT-SIGNATURE': headerB64 }}); ``` -**`public/images/icon.png`** — Replace with your app icon (used in WalletConnect modal). +## Mock mode -**`public/favicon.png`** — Replace with your favicon. +Set `NEXT_PUBLIC_USE_MOCK_WALLET=true` and `HathorRPCService` will return +deterministic fakes for `htr_getBalance`, `htr_getAddress`, +`htr_sendTransaction`, and `htr_signWithAddress`. Useful for UI work without +a real wallet. The `addressIndex` flows through correctly so the signing / +sending UI states all render. -## Step 3: Build Your UI +## Adding new pages -### Architecture Overview +Standard Next.js App Router. Add `app//page.tsx`. All providers are +already mounted in `app/layout.tsx`: ``` -app/layout.tsx ← Provider tree (do NOT reorder providers) - └─ ToastProvider - └─ WalletConnectProvider - └─ MetaMaskProvider - └─ UnifiedWalletProvider - └─ WalletProvider - └─ HathorProvider - └─ {children} ← Your pages render here -``` - -All pages automatically have access to wallet and contract state through React contexts. - -### The Main Page (`app/page.tsx`) - -This is the template's example page. **Replace its contents entirely** with your dApp UI. Keep the imports and hooks pattern: - -```tsx -'use client'; - -import { useWallet } from '@/contexts/WalletContext'; -import { useHathor } from '@/contexts/HathorContext'; -import Header from '@/components/Header'; - -export default function Home() { - const { balance, address, refreshBalance, sendNanoContractTx } = useWallet(); - const { network, isConnected, getContractStateForToken, getContractIdForToken } = useHathor(); - - return ( -
-
{}} /> -
- {/* Your UI here */} -
-
- ); -} -``` - -### Adding New Pages - -Create files in `app/` following Next.js App Router conventions: - -``` -app/ -├── page.tsx ← / (home) -├── dashboard/page.tsx ← /dashboard -├── history/page.tsx ← /history -└── settings/page.tsx ← /settings -``` - -Every page must be `'use client'` if it uses wallet hooks. All contexts are available automatically — no extra wrapping needed. - -### Creating Components - -Place new components in `components/`. Use existing UI primitives from `components/ui/`: - -- `Button` — `components/ui/button.tsx` -- `Card` / `CardHeader` / `CardContent` — `components/ui/card.tsx` -- `Dialog` — `components/ui/dialog.tsx` -- `Select` — `components/ui/select.tsx` - -### Styling - -This project uses **Tailwind CSS**. The color scheme is based on `slate` tones with an orange accent (`rgb(255, 166, 0)` to `rgb(255, 115, 0)` gradient). Global styles are in `app/globals.css`. - -## Step 4: Interact with Nano Contracts - -### Available Hooks - -**`useHathor()`** — Network, connection, and contract state: -```typescript -const { - isConnected, // boolean — is a wallet connected? - address, // string | null — connected wallet address - network, // 'testnet' | 'mainnet' - contractStates, // Record — keyed by token symbol - getContractStateForToken, // (token: string) => ContractState | null - getContractIdForToken, // (token: string) => string | null - coreAPI, // HathorCoreAPI instance for direct node queries - connectWallet, // () => Promise - disconnectWallet, // () => Promise - switchNetwork, // (network: Network) => Promise - refreshContractStates,// () => Promise - allTransactions, // ContractTransaction[] — history from all contracts - isLoadingHistory, // boolean - refreshHistory, // () => Promise -} = useHathor(); -``` - -**`useWallet()`** — Balance and transactions: -```typescript -const { - balance, // bigint — balance in cents (100 = 1.00 token) - address, // string | null - balanceVerified, // boolean — has balance been fetched? - isLoadingBalance, // boolean - refreshBalance, // (tokenUid?: string, network?: Network) => Promise - sendNanoContractTx, // (params) => Promise — send a transaction - setBalance, // React.Dispatch — for resetting balance on token switch -} = useWallet(); -``` - -**`useUnifiedWallet()`** — Low-level wallet adapter info: -```typescript -const { walletType, adapter } = useUnifiedWallet(); -// walletType: 'walletconnect' | 'metamask' | null -``` - -### Sending a Transaction - -```typescript -const { sendNanoContractTx } = useWallet(); -const { network, getContractIdForToken, getContractStateForToken } = useHathor(); - -const handleAction = async () => { - const contractId = getContractIdForToken('HTR'); - const contractState = getContractStateForToken('HTR'); - const tokenUid = contractState?.token_uid || '00'; - - const result = await sendNanoContractTx({ - network, - nc_id: contractId, - method: 'your_method', // The nano contract method name - args: [arg1, arg2], // Method arguments - actions: [ - { - type: 'deposit', // 'deposit' or 'withdrawal' - amount: '1000', // Amount in cents (1000 = 10.00 tokens) - token: tokenUid, // Token UID ('00' for HTR) - }, - ], - push_tx: true, - }); - - console.log('TX Hash:', result.response?.hash); -}; -``` - -### Reading Contract State - -Contract state is automatically fetched and cached in `HathorContext`. Access it via hooks: - -```typescript -const { getContractStateForToken } = useHathor(); -const state = getContractStateForToken('HTR'); -// state.token_uid, state.available_tokens (bigint), state.total_liquidity_provided (bigint) +ToastProvider → WalletConnectProvider → MetaMaskProvider → +UnifiedWalletProvider → WalletProvider → HathorProvider ``` -For direct API calls (not cached): -```typescript -const { coreAPI } = useHathor(); - -// Fetch state with specific fields -const state = await coreAPI.getContractState(contractId, ['field1', 'field2']); - -// Fetch transaction history -const history = await coreAPI.getContractHistory(contractId, 100); - -// Call a view function (read-only, no wallet needed) -const result = await coreAPI.callViewFunction(contractId, 'method_name', [args]); - -// Get blueprint info -const blueprint = await coreAPI.getBlueprintInfo(blueprintId); -``` - -### Adding Custom Contract State Fields - -If your nano contract has custom state fields beyond the defaults (`token_uid`, `available_tokens`, `total_liquidity_provided`): - -1. **Update the type** in `types/hathor.ts`: -```typescript -export interface ContractState { - token_uid: string; - available_tokens: bigint; - total_liquidity_provided: bigint; - // Add your fields: - your_custom_field: number; - another_field: string; - [key: string]: any; -} -``` - -2. **Update the field list** in `lib/hathorCoreAPI.ts` → `getContractState()`: -```typescript -async getContractState( - contractId: string, - fields: string[] = ['token_uid', 'available_tokens', 'total_liquidity_provided', 'your_custom_field', 'another_field'] -): Promise { -``` - -3. **Use in components**: -```typescript -const state = getContractStateForToken('HTR'); -console.log(state?.your_custom_field); -``` - -### Toast Notifications - -```typescript -import { toast } from '@/lib/toast'; - -toast.success('Transaction confirmed!'); -toast.error('Something went wrong'); -toast.info('Please confirm in your wallet...'); -``` - -## Step 5: Adding Env Vars - -If you need new environment variables: - -1. Add to `.env.local` with `NEXT_PUBLIC_` prefix (for client-side access) -2. Add to `.env.example` with documentation -3. Read in `lib/config.ts`: -```typescript -export const config = { - // ... existing config - yourNewVar: process.env.NEXT_PUBLIC_YOUR_VAR || 'default', -}; -``` - -**Important**: Next.js requires `NEXT_PUBLIC_` env vars to be referenced as literal strings (not via dynamic key access) because they are replaced at build time. - -## Project Structure - -``` -├── app/ # Next.js App Router pages -│ ├── layout.tsx # Root layout — provider tree (DO NOT reorder) -│ ├── page.tsx # Home page — REPLACE WITH YOUR UI -│ └── globals.css # Global styles (Tailwind) -├── components/ # React components -│ ├── Header.tsx # App header with wallet connect button -│ ├── BalanceCard.tsx # Wallet balance display -│ ├── ContractInfoPanel.tsx # Contract state display -│ ├── NetworkSelector.tsx # Testnet/Mainnet dropdown -│ ├── TokenSelector.tsx # Token picker (when multiple contracts) -│ ├── WalletConnectionModal.tsx # Wallet connection dialog -│ ├── HelpIcon.tsx # Tooltip help icon -│ └── ui/ # Base UI primitives (button, card, dialog, select) -├── contexts/ # React Context providers -│ ├── HathorContext.tsx # Main context: network, contracts, connection -│ ├── WalletContext.tsx # Balance management, sendNanoContractTx -│ ├── UnifiedWalletContext.tsx # Unified adapter over MetaMask/WalletConnect -│ ├── MetaMaskContext.tsx # MetaMask Snaps integration -│ └── WalletConnectContext.tsx # WalletConnect/Reown integration -├── lib/ # Core utilities -│ ├── config.ts # Env var parsing — ADD NEW VARS HERE -│ ├── hathorRPC.ts # RPC service (wallet communication) -│ ├── hathorCoreAPI.ts # Blockchain node API (read contract state) -│ ├── walletConnectConfig.ts # WalletConnect metadata -│ ├── walletConnectClient.ts # WalletConnect client singleton -│ ├── utils.ts # Formatting helpers -│ ├── toast.tsx # Toast notification system -│ └── version.ts # App version constant -├── types/ # TypeScript definitions -│ ├── hathor.ts # ContractState, BlueprintInfo, RPC types -│ ├── wallet.ts # WalletAdapter interface -│ ├── index.ts # Re-exports -│ └── metamask.d.ts # MetaMask window types -├── __tests__/ # Tests -│ ├── unit/ # Unit tests (vitest) -│ └── integration/ # Integration tests (vitest) -├── __mocks__/ # Test mocks -├── e2e/ # E2E tests (Playwright) -├── public/ # Static assets -│ ├── favicon.png # Favicon — REPLACE -│ └── images/icon.png # App icon — REPLACE -├── .env.example # Full env var documentation -├── .env.local.example # Quick-start env (mock mode enabled) -├── .env.local # Your actual config (gitignored) -└── scripts/deploy.sh # Deployment script -``` - -## Development Commands - -```bash -npm run dev # Start dev server at http://localhost:3000 -npm run build # Production build -npm run lint # ESLint -npm run test # Unit tests (watch mode) -npm run test:run # Unit tests (single run) -npm run test:coverage # Tests with coverage report -npm run test:e2e # Playwright E2E tests -``` - -## Testing - -- Unit tests: `__tests__/unit/` — test utilities, API clients, RPC service -- Integration tests: `__tests__/integration/` — test context providers with mocked wallets -- E2E tests: `e2e/` — test full page flows with Playwright -- Mocks: `__mocks__/` — mock implementations for wallet APIs -- Coverage thresholds: 80% lines/statements/functions, 70% branches - -When adding features, add corresponding tests. Use mocks from `__mocks__/` for wallet interactions. - -## Key Concepts - -### Wallet Connection Flow - -1. User clicks "Connect Wallet" → `WalletConnectionModal` opens -2. User picks MetaMask Snaps or Reown (WalletConnect) -3. Provider's `connect()` is called → `UnifiedWalletContext` wraps it in a unified `WalletAdapter` -4. `HathorContext` detects connection → syncs address and network from wallet -5. `WalletContext` begins balance fetching via `HathorRPCService` - -### How Contract IDs Map to Tokens - -Each contract ID in `NEXT_PUBLIC_CONTRACT_IDS_TESTNET` is fetched for its state. The `token_uid` field in the state determines which token symbol it maps to (looked up via the node API). This means: -- One contract per token -- Token symbol is resolved automatically -- Access state by token symbol: `getContractStateForToken('HTR')` - -### Network Switching - -- Stored in localStorage (`hathor_selected_network`) -- Changing network **disconnects** the wallet (Hathor wallets require this) -- Contract states are re-fetched for the new network -- `HathorCoreAPI` automatically uses the correct node URL - -### Mock Mode +Don't reorder; later providers depend on earlier ones. -When `NEXT_PUBLIC_USE_MOCK_WALLET=true`: -- `HathorRPCService` returns simulated responses -- Wallet connects instantly with a fake address -- Balance returns 1250.50 HTR -- Transactions return mock hashes -- Contract states use hardcoded defaults +## What this dApp is NOT -Use mock mode for UI development, then switch to `false` for real wallet integration testing. +- Not a nano-contract dApp. There is no `htr_sendNanoContractTx`, no contract + state polling, no blueprints. The old escrow / channel / contract UI was + removed when the project switched to `hathor-direct`. +- Not a wallet-management dApp. There is no key custody, no on-chain + history beyond a localStorage list of payments this browser has made. -## Files You Should NOT Modify (Unless Necessary) +## Tests -These files contain core infrastructure. Modifying them incorrectly will break wallet connectivity: +- `__tests__/unit/` — vitest unit tests +- `__tests__/integration/` — vitest integration (mocked wallets) +- `e2e/` — Playwright -- `contexts/WalletConnectContext.tsx` — WalletConnect session management -- `contexts/MetaMaskContext.tsx` — MetaMask Snaps integration -- `contexts/UnifiedWalletContext.tsx` — Wallet adapter unification -- `lib/hathorRPC.ts` — RPC protocol implementation -- `lib/walletConnectClient.ts` — WalletConnect client singleton -- `app/layout.tsx` — Provider ordering (changing order breaks context dependencies) +`npm run lint` · `npm run test:run` · `npm run test:e2e` -## Files You SHOULD Modify +## Files you should NOT modify casually -- `app/page.tsx` — **Replace entirely** with your dApp UI -- `app/` — Add new pages -- `components/` — Add new components -- `.env.local` — Configure WalletConnect ID, contract IDs, app name -- `types/hathor.ts` — Add custom contract state fields -- `lib/hathorCoreAPI.ts` — Add custom state fields to `getContractState()` defaults -- `lib/config.ts` — Add new env vars -- `public/` — Replace icon and favicon +- `contexts/WalletConnectContext.tsx`, `contexts/MetaMaskContext.tsx`, + `contexts/UnifiedWalletContext.tsx` — adapter unification. Tricky. +- `lib/walletConnectClient.ts` — Reown client singleton. +- `app/layout.tsx` — provider ordering. -## Resources +## License -- [Hathor Documentation](https://docs.hathor.network) -- [Nano Contracts Guide](https://docs.hathor.network/guides/nano-contracts/) -- [Hathor Wallet API](https://docs.hathor.network/guides/headless-wallet/http-api/) -- [WalletConnect Cloud](https://cloud.walletconnect.com/) — Get your Project ID -- [Hathor Discord](https://discord.gg/hathor) +MIT diff --git a/dapp/Dockerfile b/dapp/Dockerfile index b3ea3a9..c25d581 100644 --- a/dapp/Dockerfile +++ b/dapp/Dockerfile @@ -1,86 +1,57 @@ -# Frontend Dockerfile - Multi-stage build for Next.js SSR -FROM node:18-alpine AS builder +# dApp Dockerfile — multi-stage Next.js standalone build. +FROM node:22-alpine AS builder -# Set working directory WORKDIR /app -# Copy package files COPY package.json package-lock.json* ./ - -# Install dependencies RUN npm ci -# Copy source code COPY . . -# Build arguments for configurable API URL -ARG NEXT_PUBLIC_API_URL -ENV NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL:-/} - -# x402 build-time env vars (can be overridden at build time via --build-arg) +# x402 build-time env vars. NEXT_PUBLIC_* are baked into the bundle. ARG NEXT_PUBLIC_USE_MOCK_WALLET=false ARG NEXT_PUBLIC_DEFAULT_NETWORK=testnet -ARG NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET=https://node1.playground.testnet.hathor.network/v1a +ARG NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET=https://node1.testnet.hathor.network/v1a +ARG NEXT_PUBLIC_HATHOR_NODE_URL_MAINNET=https://node1.mainnet.hathor.network/v1a ARG NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=8264fff563181da658ce64ee80e80458 -ARG NEXT_PUBLIC_BLUEPRINT_ID -ARG NEXT_PUBLIC_CHANNEL_BLUEPRINT_ID -ARG NEXT_PUBLIC_FACILITATOR_ADDRESS -ARG NEXT_PUBLIC_SELLER_ADDRESS +ARG NEXT_PUBLIC_RESOURCE_SERVER_URL=http://localhost:3000 + ENV NEXT_PUBLIC_USE_MOCK_WALLET=${NEXT_PUBLIC_USE_MOCK_WALLET} ENV NEXT_PUBLIC_DEFAULT_NETWORK=${NEXT_PUBLIC_DEFAULT_NETWORK} ENV NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET=${NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET} +ENV NEXT_PUBLIC_HATHOR_NODE_URL_MAINNET=${NEXT_PUBLIC_HATHOR_NODE_URL_MAINNET} ENV NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=${NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID} -ENV NEXT_PUBLIC_BLUEPRINT_ID=${NEXT_PUBLIC_BLUEPRINT_ID} -ENV NEXT_PUBLIC_CHANNEL_BLUEPRINT_ID=${NEXT_PUBLIC_CHANNEL_BLUEPRINT_ID} -ENV NEXT_PUBLIC_FACILITATOR_ADDRESS=${NEXT_PUBLIC_FACILITATOR_ADDRESS} -ENV NEXT_PUBLIC_SELLER_ADDRESS=${NEXT_PUBLIC_SELLER_ADDRESS} +ENV NEXT_PUBLIC_RESOURCE_SERVER_URL=${NEXT_PUBLIC_RESOURCE_SERVER_URL} -# Set environment for production build ENV NEXT_TELEMETRY_DISABLED=1 -# Build the application RUN npm run build -# Production stage -FROM node:18-alpine AS runner +# --- Runtime stage --------------------------------------------------------- +FROM node:22-alpine AS runner -# Install curl for health checks and other utilities RUN apk add --no-cache curl -# Set working directory WORKDIR /app -# Build arguments for runtime configuration -ARG NEXT_PUBLIC_API_URL - -# Set environment ENV NODE_ENV=production ENV NEXT_TELEMETRY_DISABLED=1 -ENV NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL:-/} -# Copy built application COPY --from=builder /app/.next/standalone ./ COPY --from=builder /app/.next/static ./.next/static -# Copy public directory (includes hathor-modules.json.gz) COPY --from=builder /app/public ./public -# Create non-root user RUN addgroup -g 1001 -S nodejs && \ adduser -S nextjs -G nodejs && \ chown -R nextjs:nodejs /app -# Switch to non-root user USER nextjs -# Expose port EXPOSE 3000 -# Health check HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ CMD curl -f http://localhost:3000/ || exit 1 -# Set hostname to 0.0.0.0 to accept connections from outside the container ENV HOSTNAME=0.0.0.0 -# Start Next.js CMD ["node", "server.js"] diff --git a/dapp/README.md b/dapp/README.md index 3a42c16..22a012b 100644 --- a/dapp/README.md +++ b/dapp/README.md @@ -1,330 +1,80 @@ -# create-hathor-dapp +# x402 Hathor dApp -A template for building decentralized applications on the Hathor Network using Nano Contracts. This template provides wallet integration with MetaMask Snaps and Reown (WalletConnect), network switching, and all the infrastructure you need to build your dApp. +A browser-based x402 payment client for Hathor Network's **`hathor-direct`** +scheme — regular UTXO payments, no nano contracts. -## Features +Built on Next.js 14 + React 18 + Tailwind. Wallet integration is +WalletConnect/Reown (desktop wallet, mobile wallet) and MetaMask Snaps via a +unified adapter. -- **Wallet Integration**: Connect via Reown (WalletConnect) or MetaMask Snaps -- **Network Support**: Testnet and Mainnet support with easy switching -- **Nano Contract Support**: Ready-to-use infrastructure for interacting with nano contracts -- **Contract State Viewing**: Display and refresh contract state data -- **Balance Management**: View wallet balances with authorization -- **Mock Mode**: Test the UI without connecting a real wallet -- **Modern Stack**: Next.js 14, React 18, TypeScript, Tailwind CSS -- **Testing**: Unit tests with Vitest, E2E tests with Playwright +## What it does -## Quick Start +1. Connect a Hathor wallet (WalletConnect / Reown / MetaMask Snap). +2. Enter an x402-enabled URL. +3. On 402, the dApp shows the payment requirement. +4. Click **Pay & Access** — the wallet signs a regular send-tx + a message + signature over the server's `requestId`. +5. The dApp retries the request with the proof header; the resource appears + and a row is recorded in the local payment history. +6. Click any row to open `/payment/[txId]` for an on-chain detail view. -### Prerequisites +## Setup -- Node.js 18+ and npm -- A Hathor wallet (Hathor Wallet or MetaMask with Hathor Snap) - -### Installation - -1. Clone the repository: -```bash -git clone -cd create-hathor-dapp -``` - -2. Install dependencies: ```bash npm install -``` - -3. Configure environment: -```bash cp .env.example .env.local -``` - -4. Edit `.env.local` with your configuration: - - Get a WalletConnect Project ID from https://cloud.walletconnect.com/ - - Add your nano contract IDs - - Set your preferred default network - -5. Run development server: -```bash +$EDITOR .env.local # set NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID npm run dev ``` -6. Open [http://localhost:3000](http://localhost:3000) +Then open and connect a wallet that supports +`htr_sendTransaction` and `htr_signWithAddress` (desktop, mobile, MetaMask snap +— all of these do as of the rpc-handler version pinned in this repo). -## Environment Configuration +## Environment ```env -# WalletConnect Project ID (Required) -NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=your_project_id_here - -# Network Configuration +NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=... # https://cloud.walletconnect.com/ NEXT_PUBLIC_DEFAULT_NETWORK=testnet -NEXT_PUBLIC_USE_MOCK_WALLET=false - -# Contract IDs (JSON array format) -NEXT_PUBLIC_CONTRACT_IDS_TESTNET=["your_contract_id"] -NEXT_PUBLIC_CONTRACT_IDS_MAINNET=[] - -# App Metadata -NEXT_PUBLIC_APP_NAME=Your dApp Name -NEXT_PUBLIC_APP_DESCRIPTION=Your dApp description -``` - -## Architecture - -### Core Infrastructure - -1. **Hathor RPC Service** (`lib/hathorRPC.ts`) - - Implements the Hathor wallet-to-DApp RPC API - - Supports mock mode, MetaMask Snaps, and WalletConnect - - Methods: `htr_getConnectedNetwork`, `htr_getBalance`, `htr_getAddress`, `htr_sendNanoContractTx` - -2. **Hathor Core API** (`lib/hathorCoreAPI.ts`) - - Fetches blockchain data from Hathor nodes - - Methods: `getBlueprintInfo`, `getContractState`, `getContractHistory`, `getTransaction`, `callViewFunction` - -3. **Context Providers** - - `MetaMaskContext`: MetaMask Snaps integration - - `WalletConnectContext`: Reown/WalletConnect integration - - `UnifiedWalletContext`: Unified wallet adapter pattern - - `WalletContext`: Balance and transaction management - - `HathorContext`: Contract state and network management - -### Project Structure - -``` -create-hathor-dapp/ -├── app/ -│ ├── layout.tsx # Root layout with providers -│ ├── page.tsx # Main page -│ └── globals.css # Global styles -├── components/ -│ ├── Header.tsx # Header with wallet connection -│ ├── BalanceCard.tsx # Balance display -│ ├── ContractInfoPanel.tsx # Contract state display -│ ├── NetworkSelector.tsx # Network switching -│ ├── TokenSelector.tsx # Token selection -│ ├── WalletConnectionModal.tsx # Wallet connection -│ └── ui/ # Reusable UI components -├── contexts/ -│ ├── HathorContext.tsx # Hathor network & contract state -│ ├── WalletContext.tsx # Wallet state management -│ ├── MetaMaskContext.tsx # MetaMask Snaps integration -│ ├── WalletConnectContext.tsx # WalletConnect integration -│ └── UnifiedWalletContext.tsx # Unified wallet adapter -├── lib/ -│ ├── config.ts # Environment configuration -│ ├── hathorRPC.ts # RPC service -│ ├── hathorCoreAPI.ts # Core API service -│ ├── utils.ts # Utility functions -│ ├── toast.tsx # Toast notifications -│ └── walletConnectConfig.ts # WalletConnect setup -├── types/ -│ ├── hathor.ts # Hathor types -│ ├── wallet.ts # Wallet adapter types -│ └── index.ts # Common types -├── __tests__/ # Unit and integration tests -├── e2e/ # End-to-end tests -└── __mocks__/ # Test mocks -``` - -## Using the Template - -### Sending Nano Contract Transactions - -```typescript -import { useWallet } from '@/contexts/WalletContext'; -import { useHathor } from '@/contexts/HathorContext'; - -function YourComponent() { - const { sendNanoContractTx } = useWallet(); - const { network, getContractIdForToken, getContractStateForToken } = useHathor(); - - const handleTransaction = async () => { - const contractId = getContractIdForToken('HTR'); - const contractState = getContractStateForToken('HTR'); - const tokenUid = contractState?.token_uid || '00'; - - const result = await sendNanoContractTx({ - network, - nc_id: contractId, - method: 'your_method_name', - args: [arg1, arg2], - actions: [ - { - type: 'deposit', - amount: '1000', // in cents - token: tokenUid, - }, - ], - push_tx: true, - }); - - console.log('Transaction hash:', result.response.hash); - }; - - return ; -} -``` - -### Reading Contract State - -```typescript -import { useHathor } from '@/contexts/HathorContext'; - -function ContractStateDisplay() { - const { getContractStateForToken, coreAPI } = useHathor(); - - const contractState = getContractStateForToken('HTR'); - - // Or fetch directly from API - const fetchState = async () => { - const state = await coreAPI.getContractState('your-contract-id'); - console.log(state); - }; - - return ( -
-

Available Tokens: {contractState?.available_tokens.toString()}

-
- ); -} -``` - -### Adding New Pages - -Create new pages in the `app/` directory following Next.js App Router conventions: - -```typescript -// app/your-page/page.tsx -'use client'; - -import { useHathor } from '@/contexts/HathorContext'; -import Header from '@/components/Header'; - -export default function YourPage() { - const { isConnected } = useHathor(); - - return ( -
-
{}} /> -
- {/* Your page content */} -
-
- ); -} +NEXT_PUBLIC_USE_MOCK_WALLET=false # true = simulate the wallet (no real RPC) +NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET=https://node1.testnet.hathor.network/v1a +NEXT_PUBLIC_HATHOR_NODE_URL_MAINNET=https://node1.mainnet.hathor.network/v1a +NEXT_PUBLIC_RESOURCE_SERVER_URL=http://localhost:3000 # where /weather, /generate live ``` -## Development - -### Mock Mode - -For testing without a wallet: -```env -NEXT_PUBLIC_USE_MOCK_WALLET=true -``` +## Architecture (short) -Mock mode simulates: -- Wallet connection -- Balance queries -- Transaction submissions -- Network information +- `lib/hathorRPC.ts` — typed wrappers around `htr_sendTransaction` and + `htr_signWithAddress` (plus `htr_getAddress`, `htr_getBalance`, + `htr_getConnectedNetwork`). The mock branch lets you exercise the UI without + a real wallet. +- `contexts/WalletContext.tsx` — exposes `sendTransaction`, `signWithAddress`, + `getAddress`, plus balance helpers. +- `contexts/HathorContext.tsx` — connection state, network, fullnode read API. +- `components/X402Fetch.tsx` — the entire user flow (fetch → 402 → pay → sign + → retry → show data). One state machine. +- `lib/paymentHistory.ts` — localStorage-backed list of past payments. +- `app/payment/[txId]/page.tsx` — fetches the tx from the fullnode and + highlights the paying output / shows void/confirm status. -### Running Tests +## Testing ```bash -# Unit tests -npm test - -# Unit tests with UI -npm run test:ui - -# Unit tests with coverage -npm run test:coverage - -# E2E tests -npm run test:e2e - -# E2E tests with UI -npm run test:e2e:ui +npm run lint +npm run test:run # vitest unit + integration +npm run test:e2e # Playwright (mock-wallet mode) ``` -### Building for Production +## Production build ```bash npm run build npm start ``` -### Linting - -```bash -npm run lint -``` - -## API Reference - -### Hathor RPC Methods - -| Method | Description | -|--------|-------------| -| `htr_getConnectedNetwork()` | Get the network the wallet is connected to | -| `htr_getBalance(params)` | Get balance for specified tokens | -| `htr_getAddress(params)` | Get wallet address | -| `htr_sendNanoContractTx(params)` | Send a nano contract transaction | - -### Hathor Core API Methods - -| Method | Description | -|--------|-------------| -| `getBlueprintInfo(blueprintId)` | Fetch blueprint information | -| `getContractState(contractId)` | Fetch current contract state | -| `getContractHistory(contractId, limit)` | Fetch contract transaction history | -| `getTransaction(txId)` | Fetch transaction details | -| `callViewFunction(contractId, method, args)` | Call a view function | -| `getClaimableBalance(contractId, address)` | Get claimable balance for an address | - -## Troubleshooting - -### Wallet Not Connecting - -1. Ensure you're on the correct network (testnet/mainnet) -2. Check that your wallet extension is installed and unlocked -3. Try refreshing the page -4. Check browser console for errors - -### Contract State Not Loading - -1. Check network configuration in `.env.local` -2. Verify contract ID is correct -3. Ensure node URL is accessible -4. Check browser console for API errors - -### Transaction Failing - -1. Verify sufficient balance -2. Check transaction parameters -3. Ensure contract has sufficient liquidity -4. Verify network connection - -## Resources - -- [Hathor Documentation](https://docs.hathor.network) -- [Wallet API Reference](https://docs.hathor.network/guides/headless-wallet/http-api/) -- [Nano Contracts Guide](https://docs.hathor.network/guides/nano-contracts/) -- [Hathor Discord](https://discord.gg/hathor) - -## Contributing - -1. Fork the repository -2. Create a feature branch -3. Make your changes -4. Submit a pull request +For the static-export S3+CloudFront deploy used by `https://x402.hathor.dev`, +see `scripts/deploy.sh` and `.github/workflows/deploy.yml`. ## License -MIT License - see LICENSE file for details - ---- - -Built with Hathor Network +MIT diff --git a/dapp/app/escrow/[id]/page.tsx b/dapp/app/escrow/[id]/page.tsx deleted file mode 100644 index 91f7239..0000000 --- a/dapp/app/escrow/[id]/page.tsx +++ /dev/null @@ -1,76 +0,0 @@ -'use client'; - -import { useState, useEffect, use } from 'react'; -import Link from 'next/link'; -import { useHathor } from '@/contexts/HathorContext'; -import { EscrowDetail } from '@/components/EscrowDetail'; -import { EscrowState } from '@/types/hathor'; -import Header from '@/components/Header'; - -export default function EscrowPage({ params }: { params: Promise<{ id: string }> }) { - const { id } = use(params); - const { fetchEscrowState, escrows } = useHathor(); - const [escrow, setEscrow] = useState(null); - const [isLoading, setIsLoading] = useState(true); - const [error, setError] = useState(null); - - useEffect(() => { - // Try from cache first - if (escrows[id]) { - setEscrow(escrows[id]); - setIsLoading(false); - return; - } - - // Fetch from fullnode - fetchEscrowState(id) - .then(state => { - if (state) { - setEscrow(state); - } else { - setError('Escrow not found'); - } - }) - .catch(err => setError(err.message)) - .finally(() => setIsLoading(false)); - }, [id, fetchEscrowState, escrows]); - - const handleRefresh = async () => { - setIsLoading(true); - const state = await fetchEscrowState(id); - if (state) setEscrow(state); - setIsLoading(false); - }; - - return ( -
-
{}} /> - -
-
- - ← Back to Dashboard - - -
- - {isLoading && ( -
-

Loading escrow...

-
- )} - - {error && ( -
-

{error}

-

{id}

-
- )} - - {escrow && } -
-
- ); -} diff --git a/dapp/app/layout.tsx b/dapp/app/layout.tsx index f368bcf..d2d3741 100644 --- a/dapp/app/layout.tsx +++ b/dapp/app/layout.tsx @@ -8,8 +8,8 @@ import { ToastProvider, Toaster } from '@/lib/toast'; import './globals.css'; export const metadata: Metadata = { - title: 'x402 Escrow Manager', - description: 'Manage x402 payment escrows on Hathor Network', + title: 'x402 Client — Hathor', + description: 'x402 hathor-direct payment client (regular UTXO payments, no nano contracts)', icons: { icon: '/images/icon.png', }, diff --git a/dapp/app/page.tsx b/dapp/app/page.tsx index ba14303..604b746 100644 --- a/dapp/app/page.tsx +++ b/dapp/app/page.tsx @@ -16,14 +16,14 @@ export default function Home() { return (
-
{}} /> +
{/* Hero */}

x402 Payment Client

- Access paid HTTP APIs on Hathor Network. Enter a URL, pay with your wallet, get the data. + Access paid HTTP APIs on Hathor Network — regular UTXO payments, no nano contracts.

@@ -39,7 +39,7 @@ export default function Home() { ({network})
- + ) : ( <> @@ -50,7 +50,11 @@ export default function Home() { @@ -58,21 +62,23 @@ export default function Home() { )}
- {/* x402 Fetch Flow */} + {/* Main flow */} {/* How it works */}
-

How x402 Works

+

How x402 hathor-direct works

{[ { step: '1', title: 'Fetch', desc: 'Request a paid API endpoint' }, { step: '2', title: '402', desc: 'Server responds with payment requirements' }, - { step: '3', title: 'Pay', desc: 'Deposit funds into an escrow contract' }, - { step: '4', title: 'Access', desc: 'Retry with proof — get the data' }, + { step: '3', title: 'Pay + Sign', desc: 'Send tx + sign the request id with your key' }, + { step: '4', title: 'Access', desc: 'Retry with the proof — get the data' }, ].map(({ step, title, desc }) => (
-
{step}
+
+ {step} +

{title}

{desc}

@@ -81,10 +87,7 @@ export default function Home() {
- +
); } diff --git a/dapp/app/payment/[txId]/page.tsx b/dapp/app/payment/[txId]/page.tsx new file mode 100644 index 0000000..1af7d29 --- /dev/null +++ b/dapp/app/payment/[txId]/page.tsx @@ -0,0 +1,253 @@ +'use client'; + +import { useEffect, useState } from 'react'; +import { useHathor } from '@/contexts/HathorContext'; +import Header from '@/components/Header'; +import { formatAddress } from '@/lib/utils'; +import { getPayment, markVoided, PaymentRecord } from '@/lib/paymentHistory'; + +interface PageProps { + params: { txId: string }; +} + +function describeAmount(atomicStr?: string) { + if (!atomicStr) return ''; + const n = parseInt(atomicStr, 10); + if (!Number.isFinite(n)) return atomicStr; + return `${(n / 100).toFixed(2)} HTR`; +} + +export default function PaymentDetailPage({ params }: PageProps) { + const { txId } = params; + const { coreAPI } = useHathor(); + const [record, setRecord] = useState(() => getPayment(txId)); + const [tx, setTx] = useState(null); + const [meta, setMeta] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + let cancelled = false; + setLoading(true); + coreAPI + .getTransaction(txId) + .then((data) => { + if (cancelled) return; + if (!data?.success) { + setError('Transaction not found at fullnode'); + setLoading(false); + return; + } + setTx(data.tx); + setMeta(data.meta || null); + + // If the chain reports the tx voided, update local record so the + // history badge reflects reality. + if (Array.isArray(data.meta?.voided_by) && data.meta.voided_by.length > 0) { + markVoided(txId); + setRecord(getPayment(txId)); + } + setLoading(false); + }) + .catch((err) => { + if (cancelled) return; + setError(err.message || 'Failed to load transaction'); + setLoading(false); + }); + return () => { + cancelled = true; + }; + }, [coreAPI, txId]); + + const payOutputIndex = (() => { + if (!tx?.outputs || !record) return -1; + return tx.outputs.findIndex( + (o: any) => + o.decoded?.address === record.payTo && + BigInt(o.value) >= BigInt(parseInt(record.amount, 10) || 0) + ); + })(); + + const voided = Array.isArray(meta?.voided_by) && meta.voided_by.length > 0; + const conflicted = Array.isArray(meta?.conflict_with) && meta.conflict_with.length > 0; + + return ( +
+
+ +
+ + ← back + + +

Payment

+

{txId}

+ + {loading &&
Loading...
} + + {error && ( +
+ {error} +
+ )} + + {!loading && tx && ( + <> + {/* Local record */} + {record && ( +
+

Local record

+
+
+ URL:{' '} + {record.url} +
+
+ Scheme:{' '} + {record.scheme} +
+
+ Pay to:{' '} + {formatAddress(record.payTo)} +
+
+ Payer:{' '} + + {formatAddress(record.payerAddress)} + +
+
+ Amount paid:{' '} + {describeAmount(record.amount)} +
+ {record.chargedAmount != null && ( +
+ Charged:{' '} + + {describeAmount(record.chargedAmount)} + +
+ )} + {record.refundAmount != null && parseInt(record.refundAmount, 10) > 0 && ( +
+ Refunded:{' '} + + {describeAmount(record.refundAmount)} + +
+ )} + {record.refundTxId && ( +
+ Refund tx:{' '} + + {formatAddress(record.refundTxId)} + +
+ )} +
+ Status:{' '} + + {record.status} + +
+
+
+ )} + + {/* On-chain status */} +
+

On-chain status

+
+
+ first_block:{' '} + {meta?.first_block ? ( + + {formatAddress(meta.first_block)} + + ) : ( + unconfirmed (mempool) + )} +
+
+ voided_by:{' '} + {voided ? ( + {meta.voided_by.length} tx(s) + ) : ( + none + )} +
+
+ conflict_with:{' '} + {conflicted ? ( + {meta.conflict_with.length} tx(s) + ) : ( + none + )} +
+
+ accumulated_weight:{' '} + + {meta?.accumulated_weight ?? '—'} + +
+
+
+ + {/* Outputs */} +
+

Outputs

+
+ {tx.outputs?.map((o: any, i: number) => ( +
+ #{i} + {o.value} cents + {o.decoded?.address && ( + → {formatAddress(o.decoded.address)} + )} + {i === payOutputIndex && ( + [paying output] + )} +
+ ))} +
+
+ + {/* Inputs */} +
+

Inputs

+
+ {tx.inputs?.map((inp: any, i: number) => ( +
+ #{i} + + {formatAddress(inp.tx_id || '')}:{inp.index} + + {inp.decoded?.address && ( + + ({formatAddress(inp.decoded.address)}) + + )} +
+ ))} +
+
+ + )} +
+
+ ); +} diff --git a/dapp/components/BalanceCard.tsx b/dapp/components/BalanceCard.tsx index 5532134..2640c46 100644 --- a/dapp/components/BalanceCard.tsx +++ b/dapp/components/BalanceCard.tsx @@ -6,30 +6,23 @@ import { useUnifiedWallet } from '@/contexts/UnifiedWalletContext'; import { formatBalanceWithCommas } from '@/lib/utils'; import { toast } from '@/lib/toast'; -interface BalanceCardProps { - selectedToken: string; -} - -export default function BalanceCard({ selectedToken }: BalanceCardProps) { - const { balance, walletBalance, balanceVerified, isLoadingBalance, refreshBalance } = useWallet(); - const { isConnected, getContractStateForToken, network } = useHathor(); +export default function BalanceCard() { + const { balance, balanceVerified, isLoadingBalance, refreshBalance } = useWallet(); + const { isConnected, network } = useHathor(); const { walletType } = useUnifiedWallet(); const handleLoadBalance = () => { - // Only show confirmation toast for WalletConnect (not MetaMask Snap) if (walletType !== 'metamask') { toast.info('Please confirm the operation in your wallet...'); } - const tokenUid = getContractStateForToken(selectedToken)?.token_uid || '00'; - refreshBalance(tokenUid, network); + // x402 hathor-direct flow only uses HTR for now. + refreshBalance('00', network); }; if (!isConnected) { return (
-
- YOUR BALANCE -
+
YOUR BALANCE

Connect your wallet to view balance

); @@ -37,24 +30,23 @@ export default function BalanceCard({ selectedToken }: BalanceCardProps) { return (
-
- YOUR BALANCE -
- +
YOUR BALANCE
Wallet Balance: {balanceVerified && balance > 0n ? ( - - {formatBalanceWithCommas(balance)} {selectedToken} - + {formatBalanceWithCommas(balance)} HTR ) : isLoadingBalance ? ( Loading... ) : ( diff --git a/dapp/components/ContractInfoPanel.tsx b/dapp/components/ContractInfoPanel.tsx deleted file mode 100644 index e6271b9..0000000 --- a/dapp/components/ContractInfoPanel.tsx +++ /dev/null @@ -1,77 +0,0 @@ -'use client'; - -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; -import { ContractState } from '@/types/hathor'; -import { formatTokenAmount, formatNumber } from '@/lib/utils'; - -interface ContractInfoPanelProps { - contractState: ContractState | null; - loading?: boolean; - token?: string; - title?: string; - description?: string; -} - -export function ContractInfoPanel({ - contractState, - loading, - token = 'HTR', - title = 'Contract Information', - description = 'Current state of the nano contract' -}: ContractInfoPanelProps) { - if (loading) { - return ( - - - - ℹ️ - {title} - - Loading contract state... - - - ); - } - - if (!contractState) { - return ( - - - - ℹ️ - {title} - - No contract data available. Configure contract IDs in your environment variables. - - - ); - } - - return ( - - - - ℹ️ - {title} - - {description} - - -
-
-

Available Tokens

-

{formatTokenAmount(contractState.available_tokens)} {token}

-
-
-

Total Liquidity

-

{formatTokenAmount(contractState.total_liquidity_provided)} {token}

-
-
-

Token UID

-

{contractState.token_uid}

-
-
-
-
- ); -} diff --git a/dapp/components/CreateEscrowForm.tsx b/dapp/components/CreateEscrowForm.tsx deleted file mode 100644 index c3f8035..0000000 --- a/dapp/components/CreateEscrowForm.tsx +++ /dev/null @@ -1,173 +0,0 @@ -'use client'; - -import { useState } from 'react'; -import { useWallet } from '@/contexts/WalletContext'; -import { useHathor } from '@/contexts/HathorContext'; -import { config } from '@/lib/config'; -import { toast } from '@/lib/toast'; - -interface CreateEscrowFormProps { - onCreated?: (ncId: string) => void; -} - -export function CreateEscrowForm({ onCreated }: CreateEscrowFormProps) { - const { sendNanoContractTx, address } = useWallet(); - const { network, addEscrow, isConnected } = useHathor(); - - const [sellerAddress, setSellerAddress] = useState(config.sellerAddress); - const [amount, setAmount] = useState('100'); - const [resourceUrl, setResourceUrl] = useState('http://localhost:3000/weather'); - const [deadlineMinutes, setDeadlineMinutes] = useState('5'); - const [isSubmitting, setIsSubmitting] = useState(false); - const [showForm, setShowForm] = useState(false); - - const handleSubmit = async (e: React.FormEvent) => { - e.preventDefault(); - if (!isConnected || !address) { - toast.error('Connect your wallet first'); - return; - } - - if (!config.blueprintId) { - toast.error('Blueprint ID not configured'); - return; - } - - setIsSubmitting(true); - const deadline = Math.floor(Date.now() / 1000) + parseInt(deadlineMinutes) * 60; - const amountCents = parseInt(amount); - - try { - toast.info('Please confirm the transaction in your wallet...'); - - const result = await sendNanoContractTx({ - network, - blueprint_id: config.blueprintId, - method: 'initialize', - args: [ - sellerAddress, - config.facilitatorAddress, - '00', // HTR token - deadline, - resourceUrl, - 'dapp-escrow', - ], - actions: [{ - type: 'deposit', - amount: String(amountCents), - token: '00', - }], - push_tx: true, - }); - - // Extract ncId from response (varies by wallet type) - const ncId = result?.response?.hash || result?.hash || result?.response?.response?.hash; - if (ncId) { - await addEscrow(ncId); - toast.success(`Escrow created! ID: ${ncId.slice(0, 12)}...`); - setShowForm(false); - onCreated?.(ncId); - } else { - toast.success('Transaction sent! Refresh to see the escrow.'); - console.log('Full result:', result); - } - } catch (error: any) { - toast.error(error.message || 'Failed to create escrow'); - } finally { - setIsSubmitting(false); - } - }; - - if (!showForm) { - return ( - - ); - } - - return ( -
-
-

Create Escrow

- -
- -
-
- - setSellerAddress(e.target.value)} - className="w-full bg-slate-700 border border-slate-600 rounded-lg px-3 py-2 text-white text-sm font-mono" - required - /> -
- -
-
- - setAmount(e.target.value)} - min="1" - className="w-full bg-slate-700 border border-slate-600 rounded-lg px-3 py-2 text-white text-sm" - required - /> -

{(parseInt(amount || '0') / 100).toFixed(2)} HTR

-
- -
- - -
-
- -
- - setResourceUrl(e.target.value)} - className="w-full bg-slate-700 border border-slate-600 rounded-lg px-3 py-2 text-white text-sm" - required - /> -
- -
- -
-
-
- ); -} diff --git a/dapp/components/EscrowDetail.tsx b/dapp/components/EscrowDetail.tsx deleted file mode 100644 index 30e5a43..0000000 --- a/dapp/components/EscrowDetail.tsx +++ /dev/null @@ -1,121 +0,0 @@ -'use client'; - -import { useState } from 'react'; -import { EscrowState } from '@/types/hathor'; -import { EscrowStatusBadge } from './EscrowStatusBadge'; -import { useWallet } from '@/contexts/WalletContext'; -import { useHathor } from '@/contexts/HathorContext'; -import { formatAddress } from '@/lib/utils'; -import { toast } from '@/lib/toast'; - -interface EscrowDetailProps { - escrow: EscrowState; - onRefund?: () => void; -} - -export function EscrowDetail({ escrow, onRefund }: EscrowDetailProps) { - const { sendNanoContractTx, address } = useWallet(); - const { network, isConnected, refreshEscrows } = useHathor(); - const [isRefunding, setIsRefunding] = useState(false); - - const deadlineDate = new Date(escrow.deadline * 1000); - const isExpired = escrow.deadline < Math.floor(Date.now() / 1000); - const canRefund = escrow.phase === 'LOCKED' && isConnected; - const amountDisplay = (escrow.amount / 100).toFixed(2); - const tokenLabel = escrow.token_uid === '00' ? 'HTR' : escrow.token_uid.slice(0, 8) + '...'; - - const handleRefund = async () => { - if (!canRefund) return; - setIsRefunding(true); - - try { - toast.info('Please confirm the refund in your wallet...'); - - await sendNanoContractTx({ - network, - nc_id: escrow.ncId, - method: 'refund', - args: [], - actions: [{ - type: 'withdrawal', - amount: String(escrow.amount), - token: escrow.token_uid, - address: escrow.buyer, - }], - push_tx: true, - }); - - toast.success('Refund successful! Funds returned.'); - await refreshEscrows(); - onRefund?.(); - } catch (error: any) { - toast.error(error.message || 'Refund failed'); - } finally { - setIsRefunding(false); - } - }; - - const fields = [ - { label: 'Contract ID', value: escrow.ncId, mono: true }, - { label: 'Phase', value: escrow.phase, badge: true }, - { label: 'Amount', value: `${amountDisplay} ${tokenLabel}` }, - { label: 'Buyer', value: escrow.buyer, mono: true }, - { label: 'Seller', value: escrow.seller, mono: true }, - { label: 'Facilitator', value: escrow.facilitator, mono: true }, - { label: 'Token UID', value: escrow.token_uid, mono: true }, - { label: 'Deadline', value: `${deadlineDate.toLocaleString()}${isExpired ? ' (EXPIRED)' : ''}` }, - { label: 'Resource URL', value: escrow.resource_url }, - { label: 'Request Hash', value: escrow.request_hash, mono: true }, - ]; - - return ( -
-
-

Escrow Details

- -
- -
- {fields.map(({ label, value, mono, badge }) => ( -
- {label} - {badge ? ( - - ) : ( - - {value} - - )} -
- ))} -
- - {canRefund && ( -
- - {isExpired && ( -

Deadline expired — anyone can trigger this refund.

- )} -
- )} - - {escrow.phase === 'RELEASED' && ( -
-

Funds have been released to the seller.

-
- )} - - {escrow.phase === 'REFUNDED' && ( -
-

Funds have been refunded to the buyer.

-
- )} -
- ); -} diff --git a/dapp/components/EscrowList.tsx b/dapp/components/EscrowList.tsx deleted file mode 100644 index a4945f3..0000000 --- a/dapp/components/EscrowList.tsx +++ /dev/null @@ -1,81 +0,0 @@ -'use client'; - -import Link from 'next/link'; -import { useHathor } from '@/contexts/HathorContext'; -import { EscrowStatusBadge } from './EscrowStatusBadge'; -import { formatAddress } from '@/lib/utils'; - -export function EscrowList() { - const { escrows, isLoadingEscrows, refreshEscrows } = useHathor(); - - const escrowList = Object.values(escrows); - - if (isLoadingEscrows && escrowList.length === 0) { - return ( -
-

Loading escrows...

-
- ); - } - - if (escrowList.length === 0) { - return ( -
-

No escrows yet

-

Create your first escrow to get started

-
- ); - } - - return ( -
-
-

Your Escrows

- -
- - {escrowList.map((escrow) => { - const isExpired = escrow.deadline < Math.floor(Date.now() / 1000); - const deadlineDate = new Date(escrow.deadline * 1000); - const amountDisplay = (escrow.amount / 100).toFixed(2); - const tokenLabel = escrow.token_uid === '00' ? 'HTR' : escrow.token_uid.slice(0, 8) + '...'; - - return ( - -
-
- - {formatAddress(escrow.ncId)} -
- {amountDisplay} {tokenLabel} -
- -
- Seller: {formatAddress(escrow.seller)} - - {escrow.phase === 'LOCKED' ? ( - isExpired ? ( - Expired - ) : ( - `Deadline: ${deadlineDate.toLocaleString()}` - ) - ) : ( - escrow.phase === 'RELEASED' ? 'Funds released to seller' : 'Funds refunded' - )} - -
- - ); - })} -
- ); -} diff --git a/dapp/components/EscrowStatusBadge.tsx b/dapp/components/EscrowStatusBadge.tsx deleted file mode 100644 index b21e32a..0000000 --- a/dapp/components/EscrowStatusBadge.tsx +++ /dev/null @@ -1,16 +0,0 @@ -'use client'; - -const STATUS_STYLES: Record = { - LOCKED: 'bg-amber-500/20 text-amber-400 border-amber-500/30', - RELEASED: 'bg-green-500/20 text-green-400 border-green-500/30', - REFUNDED: 'bg-slate-500/20 text-slate-400 border-slate-500/30', -}; - -export function EscrowStatusBadge({ phase }: { phase: string }) { - const style = STATUS_STYLES[phase] || STATUS_STYLES.LOCKED; - return ( - - {phase} - - ); -} diff --git a/dapp/components/Header.tsx b/dapp/components/Header.tsx index 5c6a42c..38e35ac 100644 --- a/dapp/components/Header.tsx +++ b/dapp/components/Header.tsx @@ -5,15 +5,12 @@ import { useHathor } from '@/contexts/HathorContext'; import { formatAddress } from '@/lib/utils'; import { WalletConnectionModal } from './WalletConnectionModal'; import { NetworkSelector } from './NetworkSelector'; -import TokenSelector from './TokenSelector'; interface HeaderProps { - selectedToken: string; - onTokenChange: (token: string) => void; appName?: string; } -export default function Header({ selectedToken, onTokenChange, appName = 'Hathor dApp' }: HeaderProps) { +export default function Header({ appName = 'x402 Client' }: HeaderProps) { const { isConnected, address, disconnectWallet, network, switchNetwork } = useHathor(); const [showModal, setShowModal] = useState(false); const [showDisconnectMenu, setShowDisconnectMenu] = useState(false); @@ -22,7 +19,6 @@ export default function Header({ selectedToken, onTokenChange, appName = 'Hathor setShowModal(true); }; - // Handle network change - disconnect wallet first if connected const handleNetworkChange = (newNetwork: typeof network) => { if (isConnected) { disconnectWallet(); @@ -38,44 +34,42 @@ export default function Header({ selectedToken, onTokenChange, appName = 'Hathor
- + {isConnected ? ( - <> - -
- - {showDisconnectMenu && ( - <> -
setShowDisconnectMenu(false)} /> -
- -
- - )} -
- +
+ + {showDisconnectMenu && ( + <> +
setShowDisconnectMenu(false)} /> +
+ +
+ + )} +
) : ( @@ -83,10 +77,7 @@ export default function Header({ selectedToken, onTokenChange, appName = 'Hathor
- + ); } diff --git a/dapp/components/TokenSelector.tsx b/dapp/components/TokenSelector.tsx deleted file mode 100644 index bfb3b7b..0000000 --- a/dapp/components/TokenSelector.tsx +++ /dev/null @@ -1,32 +0,0 @@ -'use client'; - -import { useHathor } from '@/contexts/HathorContext'; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; - -interface TokenSelectorProps { - selectedToken: string; - onTokenChange: (token: string) => void; -} - -export default function TokenSelector({ selectedToken, onTokenChange }: TokenSelectorProps) { - const { contractStates } = useHathor(); - - // Get available tokens from contract states - const availableTokens = Object.keys(contractStates); - const isDisabled = availableTokens.length === 0; - - return ( - - ); -} diff --git a/dapp/components/X402Fetch.tsx b/dapp/components/X402Fetch.tsx index 67adec2..74b1a04 100644 --- a/dapp/components/X402Fetch.tsx +++ b/dapp/components/X402Fetch.tsx @@ -4,220 +4,268 @@ import { useState } from 'react'; import { useWallet } from '@/contexts/WalletContext'; import { useHathor } from '@/contexts/HathorContext'; import { config } from '@/lib/config'; +import { HathorRPCService } from '@/lib/hathorRPC'; import { toast } from '@/lib/toast'; import { formatAddress } from '@/lib/utils'; +import { addPayment, getPayments, PaymentRecord } from '@/lib/paymentHistory'; + +// --- types ----------------------------------------------------------------- interface PaymentOption { - scheme: string; + scheme: 'hathor-direct' | 'hathor-direct-upto' | string; network: string; asset: string; - price: string; - description: string; + amount: string; + description?: string; resource: string; payTo: string; + maxTimeoutSeconds?: number; extra: { - facilitatorUrl: string; - facilitatorAddress: string; - blueprintId?: string; - channelBlueprintId?: string; - deadlineSeconds: number; - pricing?: 'exact' | 'upto'; + requestId: string; + facilitatorUrl?: string; }; } -interface PaymentHistory { - id: string; - url: string; - scheme: string; - contractId: string; - amount: string; - chargedAmount?: string; - refundAmount?: string; - timestamp: Date; +type Step = + | 'idle' + | 'fetching' + | 'got402' + | 'confirming_send' + | 'waiting_mempool' + | 'signing' + | 'retrying' + | 'done' + | 'error'; + +// --- helpers --------------------------------------------------------------- + +async function pollMempool(nodeUrl: string, txId: string, maxAttempts = 30): Promise { + for (let i = 0; i < maxAttempts; i++) { + try { + const resp = await fetch(`${nodeUrl}/transaction?id=${encodeURIComponent(txId)}`); + const data = await resp.json(); + if (data?.success) return data; + } catch { + /* retry */ + } + await new Promise((r) => setTimeout(r, 1000)); + } + throw new Error('Transaction not visible at fullnode after 30s'); } -type Step = 'idle' | 'fetching' | 'got402' | 'creating' | 'waiting_confirmation' | 'retrying' | 'done' | 'error'; - -const CHANNEL_STORAGE_KEY = 'x402_active_channel'; - -function getStoredChannel(): string | null { - if (typeof window === 'undefined') return null; - return localStorage.getItem(CHANNEL_STORAGE_KEY); +function getInputAddresses(tx: any): Set { + const addrs = new Set(); + for (const inp of tx?.inputs || []) { + const a = inp?.decoded?.address; + if (a) addrs.add(a); + } + return addrs; } -function storeChannel(channelId: string) { - localStorage.setItem(CHANNEL_STORAGE_KEY, channelId); +function describeAmount(atomicStr: string) { + const n = parseInt(atomicStr, 10); + if (!Number.isFinite(n)) return atomicStr; + return `${(n / 100).toFixed(2)} HTR`; } -function clearStoredChannel() { - localStorage.removeItem(CHANNEL_STORAGE_KEY); +function describeScheme(scheme: string) { + if (scheme === 'hathor-direct-upto') return 'upto'; + if (scheme === 'hathor-direct') return 'direct'; + return scheme; } +// --- component ------------------------------------------------------------- + export function X402Fetch() { - const { sendNanoContractTx, address, refreshBalance } = useWallet(); - const { network, isConnected, addEscrow } = useHathor(); + const { sendTransaction, signWithAddress, getUtxos, address, refreshBalance } = useWallet(); + const { network, isConnected } = useHathor(); - const [url, setUrl] = useState('https://api.x402.hathor.dev/weather'); + const [url, setUrl] = useState(config.defaultDemoUrl); const [step, setStep] = useState('idle'); - const [paymentOptions, setPaymentOptions] = useState([]); - const [selectedOption, setSelectedOption] = useState(null); + const [accept, setAccept] = useState(null); const [resourceData, setResourceData] = useState(null); + const [paymentInfo, setPaymentInfo] = useState(null); const [error, setError] = useState(null); - const [contractId, setContractId] = useState(null); - const [history, setHistory] = useState([]); - const [activeChannel, setActiveChannel] = useState(getStoredChannel()); + const [txId, setTxId] = useState(null); + const [history, setHistory] = useState(() => getPayments()); const reset = () => { setStep('idle'); - setPaymentOptions([]); - setSelectedOption(null); + setAccept(null); setResourceData(null); + setPaymentInfo(null); setError(null); - setContractId(null); - }; - - const addToHistory = (scheme: string, id: string, amount: string, chargedAmount?: string, refundAmount?: string) => { - setHistory(prev => [{ id: Date.now().toString(), url, scheme, contractId: id, amount, chargedAmount, refundAmount, timestamp: new Date() }, ...prev]); + setTxId(null); }; - // Try to pay with an existing channel (instant — no wallet interaction) - const payWithChannel = async (channelId: string): Promise => { - const paymentPayload = { - x402Version: 2, - scheme: 'hathor-channel', - network: `hathor:${network}`, - payload: { channelId, buyerAddress: address }, - }; - - const resp = await fetch(url, { mode: 'cors', headers: { 'PAYMENT-SIGNATURE': btoa(JSON.stringify(paymentPayload)) } }); - if (!resp.ok) return false; - - const data = await resp.json(); - setResourceData(data); - setContractId(channelId); - setStep('done'); - addToHistory('hathor-channel', channelId, '100'); - refreshBalance('00', network); - return true; - }; - - // Step 1: Fetch the URL + // Step 1: GET → expect 402 const handleFetch = async () => { reset(); - - // If we have an active channel, try instant payment first - if (activeChannel) { - setStep('retrying'); - const ok = await payWithChannel(activeChannel).catch(() => false); - if (ok) { - toast.success('Paid via channel (instant!)'); - return; - } - // Channel failed — clear it and fall through to normal 402 flow - clearStoredChannel(); - setActiveChannel(null); - toast.info('Channel exhausted. Fetching payment options...'); - } - setStep('fetching'); - try { - const resp = await fetch(url, { mode: 'cors' }); - - if (resp.ok) { - setResourceData(await resp.json()); + const r = await fetch(url, { mode: 'cors' }); + if (r.ok) { + setResourceData(await r.json()); setStep('done'); toast.success('Resource is free!'); return; } - - if (resp.status !== 402) throw new Error(`Unexpected status: ${resp.status}`); - - const body = await resp.json(); - if (!body.accepts?.length) throw new Error('No payment options in 402'); - - setPaymentOptions(body.accepts); - setSelectedOption(body.accepts[0]); + if (r.status !== 402) throw new Error(`Unexpected status ${r.status}`); + const body = await r.json(); + if (!body?.accepts?.length) throw new Error('No accepts in 402 body'); + setAccept(body.accepts[0]); setStep('got402'); } catch (err: any) { - setError(err.message || 'Failed to fetch'); + setError(err.message); setStep('error'); } }; - // Step 2: Pay (escrow, channel, or upto escrow) + // Step 2: send tx, sign requestId, retry const handlePay = async () => { - if (!selectedOption || !isConnected || !address) return; - const opt = selectedOption; - const isChannel = opt.scheme === 'hathor-channel'; - const isUpto = opt.scheme === 'hathor-escrow-upto'; + if (!accept || !isConnected || !address) return; + const opt = accept; try { - setStep('creating'); - let id: string; - - if (isChannel) { - // Create a new channel with 10x the per-request amount - const deadline = Math.floor(Date.now() / 1000) + 3600; - const deposit = parseInt(opt.price) * 10; - toast.info('Confirm the channel deposit in your wallet...'); - - const result = await sendNanoContractTx({ - network, blueprint_id: opt.extra.channelBlueprintId, method: 'initialize', - args: [opt.extra.facilitatorAddress, opt.asset, deadline], - actions: [{ type: 'deposit', amount: String(deposit), token: opt.asset }], - push_tx: true, - }); - id = result?.response?.hash || result?.hash || result?.response?.response?.hash; - if (!id) throw new Error('No tx hash'); - storeChannel(id); - setActiveChannel(id); - toast.success(`Channel created: ${id.slice(0, 12)}...`); - } else { - // Create a one-shot escrow (same initialize() for both exact and upto — - // the difference is how the facilitator settles it: release() vs release_upto()). - const deadline = Math.floor(Date.now() / 1000) + opt.extra.deadlineSeconds; - toast.info(isUpto - ? `Confirm the escrow deposit (max ${(parseInt(opt.price) / 100).toFixed(2)} HTR) in your wallet...` - : 'Confirm the escrow deposit in your wallet...'); - - const result = await sendNanoContractTx({ - network, blueprint_id: opt.extra.blueprintId, method: 'initialize', - args: [opt.payTo, opt.extra.facilitatorAddress, opt.asset, deadline, opt.resource, 'dapp-x402'], - actions: [{ type: 'deposit', amount: opt.price, token: opt.asset }], - push_tx: true, - }); - id = result?.response?.hash || result?.hash || result?.response?.response?.hash; - if (!id) throw new Error('No tx hash'); - await addEscrow(id); - toast.success(`Escrow created: ${id.slice(0, 12)}...`); + // We assume the wallet shared address-0 (its first address) at connect + // time — true for WalletConnect/Reown's session approval flow (see + // hathor-wallet/src/sagas/reown.js:184). To make the on-chain tx's + // input(s) provably belong to address-0, we explicitly fetch UTXOs + // filtered to that address and hand them to htr_sendTransaction as + // `inputs`. The wallet then *must* use only those UTXOs, so every + // input address in the resulting tx is address-0, and signing with + // addressIndex: 0 produces a signature the verifier accepts. + const PAYER_INDEX = 0; + const payerAddress = address!; + const amount = parseInt(String(opt.amount).replace(/[^0-9]/g, ''), 10); + + // Step 1: list the connected address's UTXOs (asset-filtered). + setStep('confirming_send'); + toast.info('Listing your UTXOs at address-0...'); + const utxoDetails = await getUtxos({ + network, + filterAddress: payerAddress, + token: opt.asset || '00', + onlyAvailableUtxos: true, + maxUtxos: 255, + }); + const available = (utxoDetails?.utxos || []) + .filter((u) => !u.locked) + .map((u) => ({ ...u, _amt: Number(u.amount) })) + .sort((a, b) => b._amt - a._amt); // largest first → fewer inputs + + // Greedy-pick enough UTXOs to cover the payment. + const chosen: typeof available = []; + let total = 0; + for (const u of available) { + chosen.push(u); + total += u._amt; + if (total >= amount) break; + } + if (total < amount) { + throw new Error( + `Address-0 (${payerAddress.slice(0, 8)}...) has ${(total / 100).toFixed(2)} HTR available — need ${(amount / 100).toFixed(2)} HTR. Move funds to this address and retry.` + ); } - setContractId(id); - - // Wait for confirmation - setStep('waiting_confirmation'); - await waitForConfirmation(id); + toast.info('Confirm the payment in your wallet...'); + const sendOutput: any = { + address: opt.payTo, + // The wallet RPC validates `value` as a digit string (not a number). + value: String(amount), + }; + if (opt.asset && opt.asset !== '00') sendOutput.token = opt.asset; + + const sendResp = await sendTransaction({ + network, + outputs: [sendOutput], + inputs: chosen.map((u) => ({ txId: u.tx_id, index: u.index })), + changeAddress: payerAddress, // consolidate change back to address-0 + push_tx: true, + }); + const sentTxId = HathorRPCService.extractTxId(sendResp); + if (!sentTxId) throw new Error('Wallet did not return a transaction hash'); + setTxId(sentTxId); + toast.success(`Payment broadcast — ${sentTxId.slice(0, 10)}...`); + + // Wait until our fullnode sees the tx — no need for first_block. Capture + // the response so we can validate against the actual on-chain inputs. + setStep('waiting_mempool'); + const mempoolResp = await pollMempool(config.hathorNodeUrls[network], sentTxId); + const inputAddrs = getInputAddresses(mempoolResp?.tx); + + // Sign the server-issued requestId with address-0's key. + setStep('signing'); + toast.info('Confirm the signature in your wallet...'); + const signed = await signWithAddress({ + network, + message: opt.extra.requestId, + addressIndex: PAYER_INDEX, + }); + + // Sanity check — with explicit UTXO selection all inputs *should* be + // from address-0. If something else slipped in (wallet implementation + // quirk), surface a precise error matching what the verifier will say. + if (!inputAddrs.has(signed.address.address)) { + throw new Error( + `Signed address (${signed.address.address.slice(0, 8)}...) is not among this tx's input addresses ` + + `[${[...inputAddrs].map((a) => a.slice(0, 8) + '...').join(', ')}]. ` + + `Unexpected — the wallet didn't honour the explicit input list.` + ); + } - // Retry with payment proof — scheme in the payload must match the 402 accept + // Retry the original GET with the proof header. setStep('retrying'); - const paymentPayload = isChannel - ? { x402Version: 2, scheme: 'hathor-channel', network: `hathor:${network}`, payload: { channelId: id, buyerAddress: address } } - : { x402Version: 2, scheme: opt.scheme, network: `hathor:${network}`, payload: { ncId: id, depositTxId: id, buyerAddress: address } }; - - const paidResp = await fetch(url, { mode: 'cors', headers: { 'PAYMENT-SIGNATURE': btoa(JSON.stringify(paymentPayload)) } }); + const payload = { + x402Version: 2, + scheme: opt.scheme, + network: opt.network, + payload: { + txId: sentTxId, + payerAddress: signed.address.address, + signature: signed.signature, + requestId: opt.extra.requestId, + }, + }; + const headerB64 = + typeof window !== 'undefined' && typeof window.btoa === 'function' + ? window.btoa(JSON.stringify(payload)) + : Buffer.from(JSON.stringify(payload)).toString('base64'); + + const paidResp = await fetch(url, { + mode: 'cors', + headers: { 'PAYMENT-SIGNATURE': headerB64 }, + }); if (!paidResp.ok) { const errBody = await paidResp.json().catch(() => ({})); throw new Error(errBody.reason || errBody.error || `Rejected: ${paidResp.status}`); } - const data = await paidResp.json(); - setResourceData(data); + setResourceData(data?.data ?? data); + setPaymentInfo(data?.payment ?? null); + + // Record locally for the history panel + /payment/[txId] page. + const record: PaymentRecord = { + txId: sentTxId, + url, + route: opt.resource, + scheme: (opt.scheme as PaymentRecord['scheme']) || 'hathor-direct', + amount: opt.amount, + chargedAmount: data?.payment?.chargedAmount, + refundAmount: data?.payment?.refundAmount, + refundTxId: data?.payment?.refundTxId, + asset: opt.asset, + payTo: opt.payTo, + payerAddress: signed.address.address, + network: opt.network, + status: 'served', + ts: Date.now(), + }; + addPayment(record); + setHistory(getPayments()); + setStep('done'); toast.success('Resource received!'); - const charged = data?.payment?.chargedAmount != null ? String(data.payment.chargedAmount) : undefined; - const refund = data?.payment?.refundAmount != null ? String(data.payment.refundAmount) : undefined; - addToHistory(opt.scheme, id, opt.price, charged, refund); refreshBalance('00', network); } catch (err: any) { setError(err.message); @@ -226,79 +274,56 @@ export function X402Fetch() { } }; - const waitForConfirmation = async (txId: string) => { - const nodeUrl = config.hathorNodeUrls[network]; - for (let i = 0; i < 60; i++) { - try { - const resp = await fetch(`${nodeUrl}/transaction?id=${txId}`); - const data = await resp.json(); - if (data.success && data.meta?.first_block) return; - } catch { /* retry */ } - await new Promise(r => setTimeout(r, 1000)); - } - throw new Error('Confirmation timeout (60s)'); - }; - - const amountDisplay = selectedOption ? `${(parseInt(selectedOption.price) / 100).toFixed(2)} HTR` : ''; - const isChannel = selectedOption?.scheme === 'hathor-channel'; - const isUpto = selectedOption?.scheme === 'hathor-escrow-upto'; + const isUpto = accept?.scheme === 'hathor-direct-upto'; + const amountLabel = accept ? describeAmount(accept.amount) : ''; return (
- {/* Active Channel Banner */} - {activeChannel && ( -
-
- Active Payment Channel -

{formatAddress(activeChannel)}

-

Requests will be paid instantly — no wallet confirmation needed

-
- -
- )} - - {/* URL Input */} + {/* URL input + presets */}
-

Access a Paid Resource

+

Access a paid resource

- {activeChannel - ? 'Your channel will pay instantly — no wallet popup.' - : 'Enter an x402-enabled URL. Choose escrow (per-request) or channel (pre-funded).'} + Enter an x402-enabled URL. Click Fetch to load it. + On 402, your wallet will sign a payment.

setUrl(e.target.value)} + type="text" + value={url} + onChange={(e) => setUrl(e.target.value)} className="flex-1 bg-slate-700 border border-slate-600 rounded-lg px-4 py-3 text-white font-mono text-sm" disabled={step !== 'idle' && step !== 'error' && step !== 'done'} />
- {/* Preset URLs */}
Try:
)} - {/* Got 402 — payment options */} - {step === 'got402' && selectedOption && ( + {/* Got 402 */} + {step === 'got402' && accept && (
💰

402 — Payment Required

-

Choose how to pay

+

+ Scheme: {describeScheme(accept.scheme)} +

- {/* Option selector */} -
- {paymentOptions.map((opt, i) => { - const isCh = opt.scheme === 'hathor-channel'; - const isUp = opt.scheme === 'hathor-escrow-upto'; - const label = isCh ? '⚡ Channel' : isUp ? '📊 Upto' : '🔒 Escrow'; - const sub = isCh ? 'Instant after setup' : isUp ? 'Usage-billed' : 'One-shot per request'; - return ( - - ); - })} -
- - {/* Details */}
- {isUpto ? 'Max authorized' : 'Per request'} - {isUpto ? `up to ${amountDisplay}` : amountDisplay} + {isUpto ? 'Max authorized' : 'Pay'} + + {isUpto ? `up to ${amountLabel}` : amountLabel} +
- {isChannel && ( -
- Channel deposit (10 requests) - {(parseInt(selectedOption.price) * 10 / 100).toFixed(2)} HTR -
- )}
Seller - {formatAddress(selectedOption.payTo)} + {formatAddress(accept.payTo)}
- After this - - {isChannel ? 'Next 9 requests are instant' - : isUpto ? 'Server settles actual usage, remainder refunded' - : 'Each request needs a new escrow'} - + Network + {accept.network}
+ {accept.description && ( +
+ Description + {accept.description} +
+ )} + {isUpto && ( +
+ After + + Server charges actual usage, remainder refunded + +
+ )}
- + -
)} - {/* Creating */} - {step === 'creating' && ( + {/* In-flight steps */} + {step === 'confirming_send' && (
-
{isChannel ? 'Creating channel...' : 'Creating escrow...'}
-

Confirm the deposit in your wallet

+
Awaiting wallet confirmation...
+

Approve the payment in your wallet

)} - {/* Waiting confirmation */} - {step === 'waiting_confirmation' && ( + {step === 'waiting_mempool' && (
-
Waiting for on-chain confirmation...
-

{contractId?.slice(0, 20)}...

-

~8-16 seconds

+
Waiting for the fullnode to see the tx...
+ {txId &&

{txId.slice(0, 24)}...

} +

~1–2 seconds

+
+ )} + + {step === 'signing' && ( +
+
Awaiting signature...
+

Approve the message signature in your wallet

)} - {/* Retrying */} {step === 'retrying' && (
-
Payment verified! Fetching resource...
+
Submitting payment proof...
)} @@ -414,45 +446,70 @@ export function X402Fetch() {
- {/* Upto billing summary */} - {resourceData?.payment?.scheme === 'hathor-escrow-upto' && resourceData?.payment?.chargedAmount != null && ( -
-
📊 Usage-Based Settlement
-
-
- Max authorized - {(parseInt(selectedOption?.price || '0') / 100).toFixed(2)} HTR -
-
- Actually charged - {(parseInt(resourceData.payment.chargedAmount) / 100).toFixed(2)} HTR -
- {resourceData.payment.refundAmount > 0 && ( + {paymentInfo?.scheme === 'hathor-direct-upto' && + paymentInfo?.chargedAmount != null && ( +
+
📊 Upto settlement
+
- Refunded to you - {(parseInt(resourceData.payment.refundAmount) / 100).toFixed(2)} HTR + Max authorized + {describeAmount(paymentInfo.amount)}
- )} - {resourceData.payment.refundTxId && ( -
- Refund tx - {formatAddress(resourceData.payment.refundTxId)} +
+ Charged + + {describeAmount(paymentInfo.chargedAmount)} +
- )} + {paymentInfo.refundAmount && parseInt(paymentInfo.refundAmount, 10) > 0 && ( +
+ Refunded + + {describeAmount(paymentInfo.refundAmount)} + +
+ )} + {paymentInfo.refundTxId && ( +
+ Refund tx + + {formatAddress(paymentInfo.refundTxId)} + +
+ )} + {paymentInfo.refundError && ( +
+ Refund error + {paymentInfo.refundError} +
+ )} +
-
- )} + )}
-            {JSON.stringify(resourceData.data || resourceData, null, 2)}
+            {JSON.stringify(resourceData, null, 2)}
           
-
)} @@ -462,38 +519,48 @@ export function X402Fetch() {

Error

{error}

- +
)} {/* History */} {history.length > 0 && (
-

Payment History

+

Payment history

{history.map((e) => { - const badgeClass = e.scheme === 'hathor-channel' ? 'bg-green-500/20 text-green-400' - : e.scheme === 'hathor-escrow-upto' ? 'bg-blue-500/20 text-blue-400' - : 'bg-amber-500/20 text-amber-400'; - const badgeLabel = e.scheme === 'hathor-channel' ? 'channel' - : e.scheme === 'hathor-escrow-upto' ? 'upto' - : 'escrow'; + const badgeClass = + e.scheme === 'hathor-direct-upto' + ? 'bg-blue-500/20 text-blue-400' + : 'bg-amber-500/20 text-amber-400'; + const badgeLabel = describeScheme(e.scheme); + const ts = new Date(e.ts); return ( - diff --git a/dapp/contexts/HathorContext.tsx b/dapp/contexts/HathorContext.tsx index c4abd14..de7f483 100644 --- a/dapp/contexts/HathorContext.tsx +++ b/dapp/contexts/HathorContext.tsx @@ -1,15 +1,11 @@ 'use client'; -import React, { createContext, useContext, useState, useEffect, useCallback, ReactNode } from 'react'; +import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react'; import { HathorCoreAPI } from '@/lib/hathorCoreAPI'; -import { EscrowState, ContractState } from '@/types/hathor'; import { config, Network } from '@/lib/config'; import { useWalletConnect } from './WalletConnectContext'; import { useMetaMask } from './MetaMaskContext'; import { useWallet } from './WalletContext'; -import { getEscrowIds, addEscrowId } from '@/lib/escrowStore'; - -const ESCROW_FIELDS = ['buyer', 'seller', 'facilitator', 'token_uid', 'amount', 'phase', 'deadline', 'resource_url', 'request_hash']; interface HathorContextType { isConnected: boolean; @@ -19,16 +15,6 @@ interface HathorContextType { connectWallet: () => Promise; disconnectWallet: () => Promise; switchNetwork: (network: Network) => Promise; - // Compat with template components - contractStates: Record; - getContractStateForToken: (token: string) => ContractState | null; - getContractIdForToken: (token: string) => string | null; - // Escrow state - escrows: Record; - isLoadingEscrows: boolean; - refreshEscrows: () => Promise; - addEscrow: (ncId: string) => Promise; - fetchEscrowState: (ncId: string) => Promise; } const HathorContext = createContext(undefined); @@ -50,8 +36,6 @@ export function HathorProvider({ children }: { children: ReactNode }) { const [address, setAddress] = useState(null); const [network, setNetwork] = useState(getInitialNetwork); const [coreAPI, setCoreAPI] = useState(() => new HathorCoreAPI(getInitialNetwork())); - const [escrows, setEscrows] = useState>({}); - const [isLoadingEscrows, setIsLoadingEscrows] = useState(false); const isConnected = walletConnect.isConnected || metaMask.isConnected; @@ -80,89 +64,8 @@ export function HathorProvider({ children }: { children: ReactNode }) { setAddress(null); wallet.setBalance(0n); } - }, [isConnected, walletConnect.isConnected, metaMask.isConnected, walletConnect, metaMask]); - - const fetchEscrowState = useCallback(async (ncId: string): Promise => { - const api = new HathorCoreAPI(network); - let state; - try { - state = await api.getContractState(ncId, ESCROW_FIELDS); - } catch { - return null; - } - if (!state || !state.phase) return null; - return { - ncId, - buyer: state.buyer || '', - seller: state.seller || '', - facilitator: state.facilitator || '', - token_uid: state.token_uid || '00', - amount: typeof state.amount === 'bigint' ? Number(state.amount) : (state.amount || 0), - phase: state.phase as EscrowState['phase'], - deadline: state.deadline || 0, - resource_url: state.resource_url || '', - request_hash: state.request_hash || '', - }; - }, [network]); - - const refreshEscrows = useCallback(async () => { - setIsLoadingEscrows(true); - const ids = getEscrowIds(); - const results: Record = {}; - - // Mock mode - if (config.useMockWallet && ids.length === 0) { - setEscrows({}); - setIsLoadingEscrows(false); - return; - } - - for (const ncId of ids) { - if (config.useMockWallet) { - results[ncId] = { - ncId, - buyer: 'WMockBuyerAddress1234567890abcdef', - seller: config.sellerAddress || 'WMockSellerAddr', - facilitator: config.facilitatorAddress || 'WMockFacAddr', - token_uid: '00', - amount: 100, - phase: 'LOCKED', - deadline: Math.floor(Date.now() / 1000) + 300, - resource_url: 'http://localhost:3001/weather', - request_hash: 'mock-hash', - }; - continue; - } - - try { - const state = await fetchEscrowState(ncId); - if (state) results[ncId] = state; - } catch (err) { - // Remove stale escrow IDs that no longer exist on-chain - console.warn(`Escrow ${ncId} not found, removing from tracker`); - const { removeEscrowId } = await import('@/lib/escrowStore'); - removeEscrowId(ncId); - } - } - - setEscrows(results); - setIsLoadingEscrows(false); - }, [fetchEscrowState]); - - const addEscrowAndRefresh = useCallback(async (ncId: string) => { - addEscrowId(ncId); - const state = await fetchEscrowState(ncId); - if (state) { - setEscrows(prev => ({ [ncId]: state, ...prev })); - } - }, [fetchEscrowState]); - - // Load escrows on mount and periodically - useEffect(() => { - refreshEscrows(); - const interval = setInterval(refreshEscrows, 15000); - return () => clearInterval(interval); - }, [refreshEscrows]); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isConnected, walletConnect.isConnected, metaMask.isConnected]); const connectWallet = async () => { await walletConnect.connect(network); @@ -192,14 +95,6 @@ export function HathorProvider({ children }: { children: ReactNode }) { connectWallet, disconnectWallet, switchNetwork, - contractStates: { 'HTR': { token_uid: '00', available_tokens: 0n, total_liquidity_provided: 0n } }, - getContractStateForToken: (token: string) => token === 'HTR' ? { token_uid: '00', available_tokens: 0n, total_liquidity_provided: 0n } : null, - getContractIdForToken: () => null, - escrows, - isLoadingEscrows, - refreshEscrows, - addEscrow: addEscrowAndRefresh, - fetchEscrowState, }} > {children} diff --git a/dapp/contexts/WalletConnectContext.tsx b/dapp/contexts/WalletConnectContext.tsx index 98dd18f..0b2be3b 100644 --- a/dapp/contexts/WalletConnectContext.tsx +++ b/dapp/contexts/WalletConnectContext.tsx @@ -185,9 +185,11 @@ export function WalletConnectProvider({ children }: { children: ReactNode | Reac methods: [ 'htr_getAddress', 'htr_getBalance', + 'htr_getConnectedNetwork', + 'htr_getWalletInformation', 'htr_getUtxos', 'htr_signWithAddress', - 'htr_sendNanoContractTx', + 'htr_sendTransaction', ], chains: [`hathor:${dappNetwork}`], events: [], diff --git a/dapp/contexts/WalletContext.tsx b/dapp/contexts/WalletContext.tsx index 3b98f57..c8db9e1 100644 --- a/dapp/contexts/WalletContext.tsx +++ b/dapp/contexts/WalletContext.tsx @@ -1,13 +1,26 @@ 'use client'; import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react'; -import { WalletState } from '@/types'; import { HathorRPCService } from '@/lib/hathorRPC'; import { useUnifiedWallet } from './UnifiedWalletContext'; import { config, Network } from '@/lib/config'; - -// Direct fullnode balance query — fallback when WalletConnect RPC fails -async function fetchBalanceFromFullnode(address: string, tokenUid: string, network: Network): Promise { +import type { + GetAddressParams, + GetUtxosParams, + UtxoDetails, + SendTransactionParams, + SendTransactionResponse, + SignWithAddressParams, + SignWithAddressResponse, +} from '@/types/hathor'; + +// Read-only balance fallback via the fullnode — used when WalletConnect RPC +// rejects htr_getBalance (e.g. on certain wallets / mock mode). +async function fetchBalanceFromFullnode( + address: string, + tokenUid: string, + network: Network +): Promise { const nodeUrl = config.hathorNodeUrls[network]; const resp = await fetch(`${nodeUrl}/thin_wallet/address_balance?address=${address}`); if (!resp.ok) throw new Error(`Fullnode balance query failed: ${resp.status}`); @@ -29,29 +42,21 @@ interface WalletContextType { disconnectWallet: () => void; setBalance: React.Dispatch>; refreshBalance: (tokenUid?: string, network?: Network) => Promise; - sendNanoContractTx: (params: { - network: Network; - nc_id?: string; - blueprint_id?: string; - method: string; - args: any[]; - actions: Array<{ - type: 'deposit' | 'withdrawal'; - amount: string; - token: string; - address?: string; - }>; - push_tx: boolean; - }) => Promise; + + // x402 hathor-direct primitives — the RPC methods we actually need. + getAddress: (params: GetAddressParams) => Promise<{ address: string; index: number; addressPath: string }>; + sendTransaction: (params: SendTransactionParams) => Promise; + signWithAddress: (params: SignWithAddressParams) => Promise; + getUtxos: (params: GetUtxosParams) => Promise; } const WalletContext = createContext(undefined); const BALANCE_CACHE_KEY = 'hathor_balance_cache'; -const BALANCE_CACHE_DURATION = 15 * 60 * 1000; // 15 minutes in milliseconds +const BALANCE_CACHE_DURATION = 15 * 60 * 1000; interface BalanceCache { - balance: string; // Store as string since bigint can't be JSON serialized + balance: string; timestamp: number; address: string; } @@ -65,46 +70,23 @@ export function WalletProvider({ children }: { children: ReactNode }) { const [isLoadingBalance, setIsLoadingBalance] = useState(false); const [rpcService] = useState(() => new HathorRPCService(config.useMockWallet)); - // Load cached balance from localStorage - const loadCachedBalance = (addr: string): bigint | null => { - try { - const cached = localStorage.getItem(BALANCE_CACHE_KEY); - if (!cached) return null; - - const cache: BalanceCache = JSON.parse(cached); - const now = Date.now(); - - // Check if cache is for the same address and is still valid (less than 15 minutes old) - if (cache.address === addr && (now - cache.timestamp) < BALANCE_CACHE_DURATION) { - return BigInt(cache.balance); - } - - return null; - } catch (error) { - console.error('Failed to load cached balance:', error); - return null; - } - }; - - // Save balance to cache const saveCachedBalance = (addr: string, bal: bigint) => { try { - const cache: BalanceCache = { - balance: bal.toString(), - timestamp: Date.now(), - address: addr, - }; + const cache: BalanceCache = { balance: bal.toString(), timestamp: Date.now(), address: addr }; localStorage.setItem(BALANCE_CACHE_KEY, JSON.stringify(cache)); } catch (error) { console.error('Failed to save cached balance:', error); } }; - // Define fetchBalance before it's used in useEffect - const fetchBalance = async (addr: string, forceRefresh: boolean = false, tokenUid: string = '00', network: Network = 'mainnet') => { + const fetchBalance = async ( + addr: string, + _forceRefresh: boolean = false, + tokenUid: string = '00', + network: Network = 'testnet' + ) => { if (!addr) return; - // Don't use cache - always fetch fresh balance to ensure authorization if (config.useMockWallet) { setBalance(100000n); setBalanceVerified(true); @@ -112,39 +94,33 @@ export function WalletProvider({ children }: { children: ReactNode }) { return; } - // Update RPC service network before making request rpcService.setNetwork(network); setIsLoadingBalance(true); - setBalanceVerified(false); // Reset verified state while fetching new balance + setBalanceVerified(false); try { const balanceInfo = await rpcService.getBalance({ network, tokens: [tokenUid], }); - console.log('Balance response:', balanceInfo); - - // Handle both direct response and nested response format (MetaMask Snap wraps response) const responseData = (balanceInfo as any)?.response?.response || balanceInfo?.response; const balanceData = responseData?.[0]?.balance?.unlocked; - // Convert to bigint - value is already in cents from API - const balanceValue = typeof balanceData === 'number' - ? BigInt(Math.floor(balanceData)) - : (typeof balanceData === 'bigint' ? balanceData : 0n); - - console.log('Parsed balance:', balanceValue.toString()); + const balanceValue = + typeof balanceData === 'number' + ? BigInt(Math.floor(balanceData)) + : typeof balanceData === 'bigint' + ? balanceData + : 0n; setBalance(balanceValue); setBalanceVerified(true); saveCachedBalance(addr, balanceValue); } catch (error: any) { - console.error('Balance fetch via wallet RPC failed, trying fullnode fallback:', error?.message); - // Fallback: query the fullnode directly (read-only, no wallet needed) + console.error('Balance fetch via wallet RPC failed; trying fullnode fallback:', error?.message); try { const balanceValue = await fetchBalanceFromFullnode(addr, tokenUid, network); - console.log('Fullnode fallback balance:', balanceValue.toString()); setBalance(balanceValue); setBalanceVerified(true); saveCachedBalance(addr, balanceValue); @@ -158,19 +134,9 @@ export function WalletProvider({ children }: { children: ReactNode }) { } }; - // Update rpcService and fetch balance when wallet connects useEffect(() => { - console.log('WalletContext useEffect - adapter state:', { - isConnected: adapter?.isConnected, - address: adapter?.address, - hasRequest: !!adapter?.request, - }); - if (adapter?.isConnected && adapter.address) { - // Update rpcService with adapter's request function - console.log('Updating rpcService with adapter.request'); rpcService.updateClientAndSession(undefined, undefined, adapter.request); - // Update address - balance fetch is handled by page.tsx with correct token setAddress(adapter.address); } else if (!adapter?.isConnected) { setAddress(null); @@ -178,13 +144,10 @@ export function WalletProvider({ children }: { children: ReactNode }) { } }, [adapter?.isConnected, adapter?.address, adapter?.request, rpcService]); - // Convert balance from cents (bigint) to token units (number) for backwards compatibility const walletBalance = typeof balance === 'bigint' ? Number(balance) / 100 : 0; const connectWallet = () => { setConnected(true); - setAddress('0x7a3f...9b2c'); - setBalance(100000n); }; const disconnectWallet = () => { @@ -195,60 +158,57 @@ export function WalletProvider({ children }: { children: ReactNode }) { setIsLoadingBalance(false); }; - // Generic method to send nano contract transactions - const sendNanoContractTx = async (params: { - network: Network; - nc_id?: string; - blueprint_id?: string; - method: string; - args: any[]; - actions: Array<{ - type: 'deposit' | 'withdrawal'; - amount: string; - token: string; - address?: string; - }>; - push_tx: boolean; - }) => { - if (!adapter?.isConnected || !address) { - throw new Error('Wallet not connected'); - } + const ensureConnected = () => { + if (!adapter?.isConnected) throw new Error('Wallet not connected'); + }; + + const getAddress: WalletContextType['getAddress'] = async (params) => { + ensureConnected(); + rpcService.setNetwork(params.network as Network); + return rpcService.getAddress(params); + }; - // Update RPC service network before making request - rpcService.setNetwork(params.network); + const sendTransaction: WalletContextType['sendTransaction'] = async (params) => { + ensureConnected(); + rpcService.setNetwork(params.network as Network); + return rpcService.sendTransaction(params); + }; - console.log('Sending nano contract tx with params:', params); + const signWithAddress: WalletContextType['signWithAddress'] = async (params) => { + ensureConnected(); + rpcService.setNetwork(params.network as Network); + return rpcService.signWithAddress(params); + }; - try { - const result = await rpcService.sendNanoContractTx(params); - console.log('Nano contract tx successful:', result); - return result; - } catch (error) { - console.error('Failed to send nano contract tx:', error); - throw error; - } + const getUtxos: WalletContextType['getUtxos'] = async (params) => { + ensureConnected(); + rpcService.setNetwork(params.network as Network); + return rpcService.getUtxos(params); }; - const refreshBalance = async (tokenUid: string = '00', network: Network = 'mainnet') => { - if (address) { - await fetchBalance(address, true, tokenUid, network); // Force refresh - } + const refreshBalance = async (tokenUid: string = '00', network: Network = 'testnet') => { + if (address) await fetchBalance(address, true, tokenUid, network); }; return ( - + {children} ); diff --git a/dapp/lib/config.ts b/dapp/lib/config.ts index 62e92dd..563e669 100644 --- a/dapp/lib/config.ts +++ b/dapp/lib/config.ts @@ -2,17 +2,25 @@ export type Network = 'mainnet' | 'testnet' | 'privatenet'; export const config = { useMockWallet: process.env.NEXT_PUBLIC_USE_MOCK_WALLET === 'true', - defaultNetwork: (process.env.NEXT_PUBLIC_DEFAULT_NETWORK || 'privatenet') as Network, + defaultNetwork: (process.env.NEXT_PUBLIC_DEFAULT_NETWORK || 'testnet') as Network, hathorNodeUrls: { - 'privatenet': process.env.NEXT_PUBLIC_HATHOR_NODE_URL_PRIVATENET || 'https://node1.playground.testnet.hathor.network/v1a', - 'testnet': process.env.NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET || 'https://node1.india.testnet.hathor.network/v1a', - 'mainnet': process.env.NEXT_PUBLIC_HATHOR_NODE_URL_MAINNET || 'https://node1.mainnet.hathor.network/v1a', + privatenet: + process.env.NEXT_PUBLIC_HATHOR_NODE_URL_PRIVATENET || + 'https://node1.playground.testnet.hathor.network/v1a', + testnet: + process.env.NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET || + 'https://node1.testnet.hathor.network/v1a', + mainnet: + process.env.NEXT_PUBLIC_HATHOR_NODE_URL_MAINNET || + 'https://node1.mainnet.hathor.network/v1a', }, - // x402 config - blueprintId: process.env.NEXT_PUBLIC_BLUEPRINT_ID || '', - channelBlueprintId: process.env.NEXT_PUBLIC_CHANNEL_BLUEPRINT_ID || '', - facilitatorAddress: process.env.NEXT_PUBLIC_FACILITATOR_ADDRESS || '', - sellerAddress: process.env.NEXT_PUBLIC_SELLER_ADDRESS || '', - escrowDeadlineSeconds: parseInt(process.env.NEXT_PUBLIC_ESCROW_DEADLINE_SECONDS || '300'), + // x402 resource-server URL (where /weather, /generate, etc. live). + resourceServerUrl: + process.env.NEXT_PUBLIC_RESOURCE_SERVER_URL || 'http://localhost:3000', + + // Default URL the X402Fetch input box is seeded with. + get defaultDemoUrl() { + return `${this.resourceServerUrl}/weather`; + }, }; diff --git a/dapp/lib/escrowStore.ts b/dapp/lib/escrowStore.ts deleted file mode 100644 index 9979bb0..0000000 --- a/dapp/lib/escrowStore.ts +++ /dev/null @@ -1,21 +0,0 @@ -const STORAGE_KEY = 'x402_escrows'; - -export function getEscrowIds(): string[] { - if (typeof window === 'undefined') return []; - const raw = localStorage.getItem(STORAGE_KEY); - if (!raw) return []; - return JSON.parse(raw); -} - -export function addEscrowId(ncId: string): void { - const ids = getEscrowIds(); - if (!ids.includes(ncId)) { - ids.unshift(ncId); // newest first - localStorage.setItem(STORAGE_KEY, JSON.stringify(ids)); - } -} - -export function removeEscrowId(ncId: string): void { - const ids = getEscrowIds().filter(id => id !== ncId); - localStorage.setItem(STORAGE_KEY, JSON.stringify(ids)); -} diff --git a/dapp/lib/hathorCoreAPI.ts b/dapp/lib/hathorCoreAPI.ts index 269055e..90c2654 100644 --- a/dapp/lib/hathorCoreAPI.ts +++ b/dapp/lib/hathorCoreAPI.ts @@ -1,5 +1,8 @@ import { Network, config } from './config'; -import { ContractState, BlueprintInfo, ContractHistory } from '@/types/hathor'; + +// Tiny read-only fullnode client. We only need what the hathor-direct flow +// needs: fetch a transaction (to render the payment detail page) and check a +// token balance. export class HathorCoreAPI { private baseUrl: string; @@ -8,145 +11,28 @@ export class HathorCoreAPI { this.baseUrl = config.hathorNodeUrls[network]; } - async getBlueprintInfo(blueprintId: string): Promise { - const response = await fetch(`${this.baseUrl}/nc_blueprint/${blueprintId}`); - if (!response.ok) { - throw new Error(`Failed to fetch blueprint info: ${response.statusText}`); - } - return response.json(); - } - - async getContractState(contractId: string, fields: string[] = ['token_uid', 'available_tokens', 'total_liquidity_provided']): Promise { - const queryString = fields.map(field => `fields[]=${field}`).join('&'); - const response = await fetch(`${this.baseUrl}/nano_contract/state?id=${contractId}&${queryString}`); - if (!response.ok) { - throw new Error(`Failed to fetch contract state: ${response.statusText}`); - } - const data = await response.json(); - - // Build state object from all returned fields - const state: ContractState = { - token_uid: data.fields?.token_uid?.value || '00', - available_tokens: BigInt(data.fields?.available_tokens?.value || 0), - total_liquidity_provided: BigInt(data.fields?.total_liquidity_provided?.value || 0), - }; - - // Add any additional fields that were returned - if (data.fields) { - for (const [key, fieldData] of Object.entries(data.fields)) { - if (!(key in state) && fieldData && typeof fieldData === 'object' && 'value' in fieldData) { - state[key] = (fieldData as any).value; - } - } - } - - return state; - } - - async getContractHistory(contractId: string, limit: number = 50, after?: string): Promise { - let url = `${this.baseUrl}/nano_contract/history?id=${contractId}&count=${limit}&include_nc_events=true`; - if (after) { - url += `&after=${after}`; - } - const response = await fetch(url); - if (!response.ok) { - throw new Error(`Failed to fetch contract history: ${response.statusText}`); - } - const data = await response.json(); - return { - transactions: data.history?.map((tx: any) => ({ - tx_id: tx.hash, - timestamp: tx.timestamp, - nc_method: tx.nc_method, - nc_caller: tx.nc_address, - first_block: tx.first_block, - is_voided: tx.is_voided, - nc_args_decoded: tx.nc_args_decoded, - nc_events: tx.nc_events, - })) || [], - total: data.history?.length || 0, - hasMore: data.has_more || false, - }; - } - + // GET /v1a/transaction?id= — returns { success, tx, meta: {voided_by, conflict_with, first_block, ...} } async getTransaction(txId: string): Promise { - const response = await fetch(`${this.baseUrl}/transaction?id=${txId}`); + const response = await fetch(`${this.baseUrl}/transaction?id=${encodeURIComponent(txId)}`); if (!response.ok) { throw new Error(`Failed to fetch transaction: ${response.statusText}`); } return response.json(); } - async callViewFunction(contractId: string, method: string, args: any[] = [], callerAddress?: string): Promise { - const body: any = { - id: contractId, - method, - args, - }; - - if (callerAddress) { - body.caller = callerAddress; - } - - // Construct query parameters properly - const params = new URLSearchParams(); - params.append('id', contractId); - params.append('calls[]', `${method}(${args.map(arg => JSON.stringify(arg)).join(', ')})`); - - const response = await fetch(`${this.baseUrl}/nano_contract/state?${params.toString()}`); - - if (!response.ok) { - throw new Error(`Failed to call view function: ${response.statusText}`); - } - - const data = await response.json(); - return data; - } - - async getMaximumLiquidityRemoval(contractId: string, callerAddress: string): Promise { - const result = await this.callViewFunction(contractId, 'calculate_address_maximum_liquidity_removal', [callerAddress], callerAddress); - // The result is in calls['calculate_address_maximum_liquidity_removal()'].value - if (result.calls) { - // Get the first (and should be only) call result - const callKey = Object.keys(result.calls)[0]; - if (callKey && result.calls[callKey]?.value !== undefined) { - return BigInt(result.calls[callKey].value); - } - } - return 0n; - } - - async getClaimableBalance(contractId: string, callerAddress: string): Promise { - const result = await this.callViewFunction(contractId, 'get_address_balance', [callerAddress], callerAddress); - // The result is in calls['get_address_balance("ADDRESS")'].value - if (result.calls) { - // Get the first (and should be only) call result - const callKey = Object.keys(result.calls)[0]; - if (callKey && result.calls[callKey]?.value !== undefined) { - return BigInt(result.calls[callKey].value); - } - } - return 0n; - } - async getTokenInfo(tokenUid: string): Promise<{ symbol: string; name: string } | null> { - // HTR native token if (tokenUid === '00' || /^0+$/.test(tokenUid)) { return { symbol: 'HTR', name: 'Hathor' }; } - try { - const response = await fetch(`${this.baseUrl}/thin_wallet/token?id=${tokenUid}`); - if (!response.ok) { - return null; - } + const response = await fetch(`${this.baseUrl}/thin_wallet/token?id=${encodeURIComponent(tokenUid)}`); + if (!response.ok) return null; const data = await response.json(); return { symbol: data.symbol || tokenUid.slice(0, 8), name: data.name || 'Unknown Token', }; - } catch (error) { - console.error('Failed to fetch token info:', error); + } catch { return null; } } diff --git a/dapp/lib/hathorRPC.ts b/dapp/lib/hathorRPC.ts index d4d9aba..d79d3d7 100644 --- a/dapp/lib/hathorRPC.ts +++ b/dapp/lib/hathorRPC.ts @@ -1,4 +1,13 @@ -import { HathorRPCRequest, HathorRPCResponse, GetBalanceParams, GetAddressParams, SendNanoContractTxParams } from '@/types/hathor'; +import { + GetBalanceParams, + GetAddressParams, + GetUtxosParams, + UtxoDetails, + SendTransactionParams, + SendTransactionResponse, + SignWithAddressParams, + SignWithAddressResponse, +} from '@/types/hathor'; import Client from '@walletconnect/sign-client'; import { SessionTypes } from '@walletconnect/types'; import { Network } from '@/lib/config'; @@ -12,7 +21,13 @@ export class HathorRPCService { private customRequest: RequestFunction | undefined; private network: Network; - constructor(useMock: boolean = false, client?: Client, session?: SessionTypes.Struct, customRequest?: RequestFunction, network: Network = 'mainnet') { + constructor( + useMock: boolean = false, + client?: Client, + session?: SessionTypes.Struct, + customRequest?: RequestFunction, + network: Network = 'testnet' + ) { this.useMock = useMock; this.client = client; this.session = session; @@ -20,7 +35,12 @@ export class HathorRPCService { this.network = network; } - updateClientAndSession(client?: Client, session?: SessionTypes.Struct, customRequest?: RequestFunction, network?: Network) { + updateClientAndSession( + client?: Client, + session?: SessionTypes.Struct, + customRequest?: RequestFunction, + network?: Network + ) { this.client = client; this.session = session; this.customRequest = customRequest; @@ -38,42 +58,45 @@ export class HathorRPCService { return this.mockRequest(method, params); } - // Use custom request function if provided (e.g., MetaMask) if (this.customRequest) { try { const result = await this.customRequest(method, params); + // eslint-disable-next-line no-console console.log(`RPC [${method}] response:`, result); return result; } catch (error: any) { + // eslint-disable-next-line no-console console.error(`RPC [${method}] failed via custom request:`, error); throw new Error(error?.message || 'RPC request failed'); } } - // Fall back to WalletConnect if (!this.client || !this.session) { throw new Error('Wallet not connected. Please connect your wallet.'); } try { - console.log(`RPC [${method}] requesting via WalletConnect (chain: hathor:${this.network}, topic: ${this.session.topic.slice(0, 8)}...)`); + // eslint-disable-next-line no-console + console.log( + `RPC [${method}] via WalletConnect (chain: hathor:${this.network}, topic: ${this.session.topic.slice(0, 8)}...)` + ); const result = await this.client.request({ chainId: `hathor:${this.network}`, topic: this.session.topic, - request: { - method, - params, - }, + request: { method, params }, }); - + // eslint-disable-next-line no-console console.log(`RPC [${method}] response:`, result); return result; } catch (error: any) { + // eslint-disable-next-line no-console console.error(`RPC [${method}] failed via WalletConnect:`, error); throw new Error(error?.message || 'RPC request failed'); } } + // --- typed wrappers -------------------------------------------------------- + async getConnectedNetwork(): Promise<{ network: string; genesisHash: string }> { return this.request('htr_getConnectedNetwork'); } @@ -82,20 +105,74 @@ export class HathorRPCService { return this.request('htr_getBalance', params); } - async getAddress(params: GetAddressParams): Promise<{ address: string; index: number; addressPath: string }> { - return this.request('htr_getAddress', params); + // Every rpc-handler method returns `{type, response: {...actual data...}}` + // (see hathor-rpc-lib/packages/hathor-rpc-handler/src/rpcMethods/*.ts). + // Unwrap so callers get the inner shape directly. Snap responses sometimes + // double-wrap (response.response.*), so fall back to that too. + private unwrap(raw: any): T { + if (raw && typeof raw === 'object') { + if (raw.response && typeof raw.response === 'object') { + const inner = raw.response; + if (inner.response && typeof inner.response === 'object') return inner.response as T; + return inner as T; + } + } + return raw as T; + } + + async getAddress( + params: GetAddressParams + ): Promise<{ address: string; index: number; addressPath: string }> { + const raw = await this.request('htr_getAddress', params); + return this.unwrap(raw); } async getWalletInformation(): Promise<{ address0: string; network: string }> { - return this.request('htr_getWalletInformation'); + const raw = await this.request('htr_getWalletInformation'); + return this.unwrap(raw); + } + + // Regular Hathor transaction send (no nano contracts). Implemented by the + // desktop wallet (hathor-wallet/src/sagas/reown.js:81), mobile wallet + // (hathor-wallet-mobile/src/sagas/reown.js:165), and the MetaMask snap + // (hathor-rpc-lib/packages/snap/src/index.tsx:81). + async sendTransaction(params: SendTransactionParams): Promise { + const raw = await this.request('htr_sendTransaction', params); + return this.unwrap(raw); + } + + // Sign an arbitrary message with the key of a specific wallet address. + // Returns a Bitcoin-compatible signed-message signature (bitcore.Message). + // We use this to bind a server-issued requestId to the payer. + async signWithAddress(params: SignWithAddressParams): Promise { + const raw = await this.request('htr_signWithAddress', params); + return this.unwrap(raw); + } + + // List the wallet's available UTXOs, optionally filtered to one address. + // We use this to pre-select UTXOs at address-0 so the resulting tx's inputs + // are guaranteed to come from there. + async getUtxos(params: GetUtxosParams): Promise { + const raw = await this.request('htr_getUtxos', params); + return this.unwrap(raw); } - async sendNanoContractTx(params: SendNanoContractTxParams): Promise { - return this.request('htr_sendNanoContractTx', params); + // --- helpers --------------------------------------------------------------- + + // Extract a txId from the various shapes the RPC response can take. + static extractTxId(resp: SendTransactionResponse): string | undefined { + return ( + resp?.hash || + resp?.txId || + resp?.response?.hash || + resp?.response?.response?.hash + ); } + // --- mock --- (development only) ------------------------------------------- + private async mockRequest(method: string, params?: any): Promise { - await new Promise(resolve => setTimeout(resolve, 500)); + await new Promise((resolve) => setTimeout(resolve, 500)); switch (method) { case 'htr_getConnectedNetwork': @@ -103,28 +180,70 @@ export class HathorRPCService { case 'htr_getBalance': return { - response: [{ - token: { id: '00', name: 'Hathor', symbol: 'HTR' }, - balance: { unlocked: 1250.50, locked: 0 }, - tokenAuthorities: { unlocked: { mint: false, melt: false }, locked: { mint: false, melt: false } }, - transactions: 42, - lockExpires: null, - }] + response: [ + { + token: { id: '00', name: 'Hathor', symbol: 'HTR' }, + balance: { unlocked: 1250.5, locked: 0 }, + tokenAuthorities: { + unlocked: { mint: false, melt: false }, + locked: { mint: false, melt: false }, + }, + transactions: 42, + lockExpires: null, + }, + ], } as T; - case 'htr_getAddress': - return { address: 'WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp', index: 0, addressPath: "m/44'/280'/0'/0/0" } as T; + case 'htr_getAddress': { + const index = params?.index ?? 0; + return { + address: 'WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp', + index, + addressPath: `m/44'/280'/0'/0/${index}`, + } as T; + } case 'htr_getWalletInformation': return { address0: 'WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp', network: 'testnet' } as T; - case 'htr_sendNanoContractTx': + case 'htr_sendTransaction': { + const fakeHash = + '00000000' + + Math.random().toString(36).substring(2, 15) + + Math.random().toString(36).substring(2, 15); + return { hash: fakeHash, success: true } as T; + } + + case 'htr_signWithAddress': { + const idx = params?.addressIndex ?? 0; + return { + message: params?.message ?? '', + signature: 'H' + Buffer.from(`mock-${idx}-${Date.now()}`).toString('base64'), + address: { + address: 'WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp', + index: idx, + addressPath: `m/44'/280'/0'/0/${idx}`, + }, + } as T; + } + + case 'htr_getUtxos': { return { - hash: '00000000' + Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15), - success: true, - timestamp: Date.now(), - nonce: Math.floor(Math.random() * 1000000), + total_amount_available: 100000, + total_utxos_available: 1, + total_amount_locked: 0, + total_utxos_locked: 0, + utxos: [ + { + address: 'WYBwT3xLpDnHNtYZiU52oanupVeDKhAvNp', + amount: 100000, + tx_id: '00mock' + Math.random().toString(36).substring(2, 15), + index: 0, + locked: false, + }, + ], } as T; + } default: throw new Error(`Mock not implemented for method: ${method}`); diff --git a/dapp/lib/paymentHistory.ts b/dapp/lib/paymentHistory.ts new file mode 100644 index 0000000..f23c008 --- /dev/null +++ b/dapp/lib/paymentHistory.ts @@ -0,0 +1,74 @@ +// localStorage-backed list of x402 payments this browser has made. Used by +// X402Fetch and the /payment/[txId] detail page. + +const STORAGE_KEY = 'x402_payments'; + +export type PaymentScheme = 'hathor-direct' | 'hathor-direct-upto'; +export type PaymentStatus = 'served' | 'voided'; + +export interface PaymentRecord { + txId: string; + url: string; + route: string; + scheme: PaymentScheme; + amount: string; // atomic units paid + chargedAmount?: string; // upto only + refundAmount?: string; // upto only + refundTxId?: string; // upto only + asset: string; + payTo: string; + payerAddress: string; + network: string; + status: PaymentStatus; + ts: number; +} + +function safeReadAll(): PaymentRecord[] { + if (typeof window === 'undefined') return []; + try { + const raw = window.localStorage.getItem(STORAGE_KEY); + if (!raw) return []; + const parsed = JSON.parse(raw); + return Array.isArray(parsed) ? parsed : []; + } catch { + return []; + } +} + +function safeWriteAll(records: PaymentRecord[]) { + if (typeof window === 'undefined') return; + try { + window.localStorage.setItem(STORAGE_KEY, JSON.stringify(records)); + } catch { + /* quota or private mode — ignore */ + } +} + +export function getPayments(): PaymentRecord[] { + return safeReadAll(); +} + +export function getPayment(txId: string): PaymentRecord | undefined { + return safeReadAll().find((p) => p.txId === txId); +} + +export function addPayment(record: PaymentRecord): void { + const existing = safeReadAll(); + const i = existing.findIndex((p) => p.txId === record.txId); + if (i >= 0) existing[i] = { ...existing[i], ...record }; + else existing.unshift(record); + safeWriteAll(existing); +} + +export function markVoided(txId: string): void { + const existing = safeReadAll(); + const i = existing.findIndex((p) => p.txId === txId); + if (i < 0) return; + existing[i] = { ...existing[i], status: 'voided' }; + safeWriteAll(existing); +} + +export function clearPayments(): void { + if (typeof window === 'undefined') return; + window.localStorage.removeItem(STORAGE_KEY); +} diff --git a/dapp/scripts/deploy.sh b/dapp/scripts/deploy.sh index 9be52b8..0c34f20 100755 --- a/dapp/scripts/deploy.sh +++ b/dapp/scripts/deploy.sh @@ -1,9 +1,9 @@ #!/bin/bash -# Deployment script for Hathor dApp +# Deployment script for the x402 Hathor dApp. # Usage: ./scripts/deploy.sh [aws_profile] # -# Sites: staging, production +# Sites: staging, production # Commands: build, sync, clear_cache if [ -z "$1" ] || [ -z "$2" ]; then @@ -21,15 +21,13 @@ site=$1 command=$2 aws_profile=$3 -# Define environment variables for each site -# NOTE: Update these values for your deployment +# Per-site env. Update before first deploy. case $site in staging) NEXT_PUBLIC_DEFAULT_NETWORK=testnet - NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET=https://node1.india.testnet.hathor.network/v1a + NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET=https://node1.testnet.hathor.network/v1a NEXT_PUBLIC_HATHOR_NODE_URL_MAINNET=https://node1.mainnet.hathor.network/v1a - NEXT_PUBLIC_CONTRACT_IDS_TESTNET='["your_staging_contract_id"]' - NEXT_PUBLIC_CONTRACT_IDS_MAINNET='[]' + NEXT_PUBLIC_RESOURCE_SERVER_URL=https://api.x402.hathor.dev NEXT_PUBLIC_USE_MOCK_WALLET=false NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=your_walletconnect_project_id S3_BUCKET=your-staging-bucket @@ -37,10 +35,9 @@ case $site in ;; production) NEXT_PUBLIC_DEFAULT_NETWORK=mainnet - NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET=https://node1.india.testnet.hathor.network/v1a + NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET=https://node1.testnet.hathor.network/v1a NEXT_PUBLIC_HATHOR_NODE_URL_MAINNET=https://node1.mainnet.hathor.network/v1a - NEXT_PUBLIC_CONTRACT_IDS_TESTNET='[]' - NEXT_PUBLIC_CONTRACT_IDS_MAINNET='["your_production_contract_id"]' + NEXT_PUBLIC_RESOURCE_SERVER_URL=https://api.x402.hathor.dev NEXT_PUBLIC_USE_MOCK_WALLET=false NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=your_walletconnect_project_id S3_BUCKET=your-production-bucket @@ -56,8 +53,7 @@ esac export NEXT_PUBLIC_DEFAULT_NETWORK export NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET export NEXT_PUBLIC_HATHOR_NODE_URL_MAINNET -export NEXT_PUBLIC_CONTRACT_IDS_TESTNET -export NEXT_PUBLIC_CONTRACT_IDS_MAINNET +export NEXT_PUBLIC_RESOURCE_SERVER_URL export NEXT_PUBLIC_USE_MOCK_WALLET export NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID export S3_BUCKET @@ -66,14 +62,12 @@ export CLOUDFRONT_ID case $command in build) echo "Building for site: $site" - echo "NEXT_PUBLIC_DEFAULT_NETWORK: $NEXT_PUBLIC_DEFAULT_NETWORK" - echo "NEXT_PUBLIC_USE_MOCK_WALLET: $NEXT_PUBLIC_USE_MOCK_WALLET" - # Use production config for static export + echo " NEXT_PUBLIC_DEFAULT_NETWORK: $NEXT_PUBLIC_DEFAULT_NETWORK" + echo " NEXT_PUBLIC_USE_MOCK_WALLET: $NEXT_PUBLIC_USE_MOCK_WALLET" + echo " NEXT_PUBLIC_RESOURCE_SERVER_URL: $NEXT_PUBLIC_RESOURCE_SERVER_URL" cp next.config.js next.config.js.bak cp next.config.production.js next.config.js - # Run the build command npm run build - # Restore original config mv next.config.js.bak next.config.js ;; sync) diff --git a/dapp/types/hathor.ts b/dapp/types/hathor.ts index df159f9..ca5ad3b 100644 --- a/dapp/types/hathor.ts +++ b/dapp/types/hathor.ts @@ -1,51 +1,5 @@ -export interface ContractState { - token_uid: string; - available_tokens: bigint; - total_liquidity_provided: bigint; - [key: string]: any; -} - -export interface EscrowState { - ncId: string; - buyer: string; - seller: string; - facilitator: string; - token_uid: string; - amount: number; - phase: 'LOCKED' | 'RELEASED' | 'REFUNDED'; - deadline: number; - resource_url: string; - request_hash: string; -} - -export interface BlueprintInfo { - id: string; - name: string; - public_methods: string[]; - attributes: Record; -} - -export interface ContractHistory { - transactions: ContractTransaction[]; - total: number; - hasMore: boolean; -} - -export interface NanoContractEvent { - data: string; -} - -export interface ContractTransaction { - tx_id: string; - timestamp: number; - nc_method: string; - nc_caller: string; - first_block: string | null; - is_voided: boolean; - nc_args_decoded?: number[]; - nc_events?: NanoContractEvent[]; - contractId?: string; -} +// dApp types for x402 hathor-direct flow. No nano-contract types — those went +// away with the blueprint redesign. export interface HathorRPCRequest { method: string; @@ -73,19 +27,91 @@ export interface GetAddressParams { index?: number; } -export interface SendNanoContractTxParams { - method: string; - blueprint_id?: string; - nc_id?: string; - actions: NanoContractAction[]; - args: any[]; - push_tx: boolean; -} +// --- htr_sendTransaction ----------------------------------------------------- -export interface NanoContractAction { - type: 'deposit' | 'withdrawal'; - amount: string; - token: string; +export interface SendTransactionOutput { address?: string; + // The RPC schema requires a digit string (z.string().regex(/^\d+$/)), + // not a number — see hathor-rpc-handler/src/rpcMethods/sendTransaction.ts:59. + value?: string; + token?: string; + timelock?: number; + // OP_RETURN-style data output (we don't use this for hathor-direct but the + // RPC supports it). + type?: 'data'; + data?: string; +} + +export interface SendTransactionInput { + txId: string; + index: number; +} + +export interface SendTransactionParams { + network: string; + outputs: SendTransactionOutput[]; + inputs?: SendTransactionInput[]; changeAddress?: string; + push_tx: boolean; +} + +// The RPC's response shape varies a bit across wallets (some return a flat +// `hash`, some wrap in `response: { hash }`). We type the union and the +// service helper picks the right field. +export interface SendTransactionResponse { + hash?: string; + txId?: string; + response?: { + hash?: string; + response?: { hash?: string }; + }; + success?: boolean; +} + +// --- htr_getUtxos ------------------------------------------------------------ + +export interface GetUtxosParams { + network: string; + maxUtxos?: number; + token?: string; + filterAddress?: string; + authorities?: number; + amountSmallerThan?: number; + amountBiggerThan?: number; + maximumAmount?: number; + onlyAvailableUtxos?: boolean; +} + +export interface UtxoInfo { + address: string; + amount: string | number | bigint; + tx_id: string; + index: number; + locked: boolean; +} + +export interface UtxoDetails { + total_amount_available: string | number | bigint; + total_utxos_available: string | number | bigint; + total_amount_locked: string | number | bigint; + total_utxos_locked: string | number | bigint; + utxos: UtxoInfo[]; +} + +// --- htr_signWithAddress ----------------------------------------------------- + +export interface SignWithAddressParams { + network: string; + message: string; + addressIndex: number; +} + +export interface SignWithAddressResponse { + message: string; + signature: string; + address: { + address: string; + index: number; + addressPath: string; + }; } diff --git a/data/payments.sqlite b/data/payments.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..db7a7459cf0d014b0dc2333abb5541c58c2d6ed1 GIT binary patch literal 4096 zcmWFz^vNtqRY=P(%1ta$FlG>7U}9o$P*7lCU|@t|AVoG{WYBBV;st3JAlr;ljiVtj n8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*O6ovo*g{}s{ literal 0 HcmV?d00001 diff --git a/data/payments.sqlite-shm b/data/payments.sqlite-shm new file mode 100644 index 0000000000000000000000000000000000000000..b8d9315068a52945fa611cfc2d5cd238d8dba084 GIT binary patch literal 32768 zcmeI)v2DUY6b9fkjspozN=qr}kXVWt5M`7S)@AwYlt0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UxEFyU&Y4Kl zC4@kJ0)z0BU(-4!&E2oNAZfB*pk t1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PI)Yz!iFWEiwQA literal 0 HcmV?d00001 diff --git a/data/payments.sqlite-wal b/data/payments.sqlite-wal new file mode 100644 index 0000000000000000000000000000000000000000..272113f331e7f5d357d5887863f99a3934dab423 GIT binary patch literal 45352 zcmeI*OKjV890zbGZPRU9R$fvkp{kY;(2hOqrb&}S5owyHZj-c4^DIcg_TO8am%G?` z^#EEoh7bpkfQjue1lLI%#({?>#0`lH2M|mIAS|-nr^Ks213*FwbI6M z{{GwlkE2Nb_xJmC>P5#Ub>fGk6!idQEWbW_{lXjX+;~58dDQmV^d+CZ$=1F7>(^4h zU%zsBZFMCqYZ850sg!t)cIkWD?bI_gt+%!7KYhkN?Zw!?-+G}xoBegY-fh)RoxFI= zIrJB0ciyC&H-|potr50C00Izz00bZa0SG_<0uX?}-3y#A+6IS5MrhTIZW3 zsjR8ivpoUYt{H252oXEbV>h7gu}<%ZIr6EUe&U4 znMe)24Hu0EL&4Y`%_`E_s-)`eTK(rT3@v16qcfb3PRjE=l`fj(|>m2k^tSe zl$s(FX*pt~z4XyOc?8{g14g_-_v?R@N6_c2nt25J6BY%_U>;-`*YFRV4A+O9laFol8Z&ySOrzPMrg2Jr&D^L2!gLI45~fB*y_ z009U<00IzzKu-(oh!=2|mtI*7fBXGD@dA!6F(VJ*uHyv;4sW*O1rBdIXS#aDDg+<^ z0SG_<0uX=z1R&5u0_Udt2Zu*TZJV4~Ax|hOVxcIjT4!ZoM~%GB=1!5kPQ5y-LS9#` zHmiJFMdDSZ+^Sl)Yw0_)+jdR4+pEECcT(gvy^W^V*)uw6m3(6d9K*rUy-L1yPB+VT zRvm~J*jd7GN2mkp4*t(|2M3HV8!KMm`QHXo3zz!0PG8b6NK@)S(i(4xdf3Vgmp7hZblTmUdhY*c*ZRWWYQ%_-YGBRWktgJq)CBs z>8&TF=0a0&C7HEV&cl^*44LIu$R@Bojmyi@5?xG-mliBPXy?HX8CZW1(1q zFRgh}$(cm5n3*v9OGh`>(kuGDoPI1$eb)lH&6UX)c$K zxznDr3tkd$dej78ug^9#x2GD4)#|auxM#J(q|QuLCK8KLX)2v3ixGZ#PAx36YwMF@ zBM_)ZBVm;=O#bMrALtj>s1MM|BY5lM=l;k%LVaq)3)qG}q4Wn92tWV=5P$##AOHaf zKmY;|fB*#UIf3ASKFf0O-%hUR!!l|HcJc@wd;Oz{} efB*y_009U<00Izz00bbgufXGdD+l)v8~7XGu7I5Y literal 0 HcmV?d00001 diff --git a/dedupStore.js b/dedupStore.js new file mode 100644 index 0000000..879c583 --- /dev/null +++ b/dedupStore.js @@ -0,0 +1,142 @@ +// Persistent dedup ledger + blocklist for the verifier. better-sqlite3 gives +// us an atomic `INSERT OR IGNORE` + `SELECT` cycle which is exactly what we +// need to distinguish first-redemption / idempotent retry / replay attempts. +// +// The same DB file is safe to share across the resource-server and the +// (optional) standalone facilitator thanks to WAL mode. + +'use strict'; + +const path = require('path'); +const fs = require('fs'); +const Database = require('better-sqlite3'); + +function openStore(dbPath) { + // Ensure the parent directory exists for first-run docker mounts. + const dir = path.dirname(dbPath); + if (dir && dir !== '.') fs.mkdirSync(dir, { recursive: true }); + + const db = new Database(dbPath); + db.pragma('journal_mode = WAL'); + db.pragma('synchronous = NORMAL'); + + db.exec(` + CREATE TABLE IF NOT EXISTS payments ( + tx_id TEXT NOT NULL, + output_index INTEGER NOT NULL, + request_id TEXT NOT NULL, + payer_address TEXT NOT NULL, + amount INTEGER NOT NULL, + charged_amount INTEGER, + refund_tx_id TEXT, + asset TEXT NOT NULL, + served_at INTEGER NOT NULL, + response_hash TEXT, + voided INTEGER NOT NULL DEFAULT 0, + PRIMARY KEY (tx_id, output_index) + ); + + CREATE INDEX IF NOT EXISTS idx_payments_payer ON payments(payer_address); + + CREATE TABLE IF NOT EXISTS blocklist ( + address TEXT PRIMARY KEY, + reason TEXT NOT NULL, + blocked_at INTEGER NOT NULL, + related_tx TEXT + ); + `); + + const stmts = { + insertIgnore: db.prepare(` + INSERT OR IGNORE INTO payments + (tx_id, output_index, request_id, payer_address, amount, asset, served_at) + VALUES (@txId, @outputIndex, @requestId, @payerAddress, @amount, @asset, @servedAt) + `), + selectByKey: db.prepare( + `SELECT * FROM payments WHERE tx_id = ? AND output_index = ?` + ), + markVoided: db.prepare( + `UPDATE payments SET voided = 1 WHERE tx_id = ? AND output_index = ?` + ), + setResponseHash: db.prepare( + `UPDATE payments SET response_hash = ? WHERE tx_id = ? AND output_index = ?` + ), + setUptoSettlement: db.prepare(` + UPDATE payments + SET charged_amount = ?, refund_tx_id = ? + WHERE tx_id = ? AND output_index = ? + `), + selectBlock: db.prepare(`SELECT 1 FROM blocklist WHERE address = ?`), + insertBlock: db.prepare(` + INSERT OR REPLACE INTO blocklist (address, reason, blocked_at, related_tx) + VALUES (?, ?, ?, ?) + `), + countPayments: db.prepare(`SELECT COUNT(*) AS n FROM payments`), + countBlocks: db.prepare(`SELECT COUNT(*) AS n FROM blocklist`), + }; + + // Atomic redemption. Returns: + // 'new' — first time we're seeing this (txId, outputIndex) + // 'idempotent' — already redeemed against the same requestId; safe replay + // 'conflict' — already redeemed against a DIFFERENT requestId; replay attempt + const markRedeemedIfFreeTx = db.transaction( + ({ txId, outputIndex, requestId, payerAddress, amount, asset }) => { + const info = stmts.insertIgnore.run({ + txId, + outputIndex, + requestId, + payerAddress, + amount: Number(amount), + asset, + servedAt: Math.floor(Date.now() / 1000), + }); + if (info.changes === 1) return { result: 'new' }; + + const existing = stmts.selectByKey.get(txId, outputIndex); + if (!existing) return { result: 'new' }; // shouldn't happen but be safe + if (existing.request_id === requestId) return { result: 'idempotent', existing }; + return { result: 'conflict', existing }; + } + ); + + return { + markRedeemedIfFree(key, fields) { + return markRedeemedIfFreeTx({ ...key, ...fields }); + }, + getRecord(txId, outputIndex) { + return stmts.selectByKey.get(txId, outputIndex) || null; + }, + markVoided(txId, outputIndex) { + stmts.markVoided.run(txId, outputIndex); + }, + attachResponseHash(txId, outputIndex, hash) { + stmts.setResponseHash.run(hash, txId, outputIndex); + }, + attachUptoSettlement(txId, outputIndex, chargedAmount, refundTxId) { + stmts.setUptoSettlement.run( + chargedAmount == null ? null : Number(chargedAmount), + refundTxId || null, + txId, + outputIndex + ); + }, + isBlocked(address) { + return Boolean(stmts.selectBlock.get(address)); + }, + addBlock(address, reason, relatedTx) { + stmts.insertBlock.run(address, String(reason || 'manual'), Math.floor(Date.now() / 1000), relatedTx || null); + }, + stats() { + return { + payments: stmts.countPayments.get().n, + blocked: stmts.countBlocks.get().n, + path: dbPath, + }; + }, + close() { + db.close(); + }, + }; +} + +module.exports = { openStore }; diff --git a/docker-compose.yml b/docker-compose.yml index 93cf9ce..b56bcb6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,14 +1,21 @@ services: + # The seller's wallet-headless. Used ONLY by the upto scheme to issue refund + # transactions; the exact scheme doesn't touch it. Fund this wallet with HTR + # before running upto demos. wallet-headless: image: hathornetwork/hathor-wallet-headless:latest pull_policy: always environment: HEADLESS_HTTP_BIND: "0.0.0.0" HEADLESS_HTTP_PORT: "8000" - HEADLESS_NETWORK: testnet - HEADLESS_SERVER: https://node1.playground.testnet.hathor.network/v1a/ + HEADLESS_NETWORK: ${HATHOR_NETWORK:-testnet} + HEADLESS_SERVER: ${FULLNODE_URL:-https://node1.testnet.hathor.network}/v1a/ + HEADLESS_TX_MINING_URL: ${TX_MINING_URL:-https://txmining.testnet.hathor.network/} + # wallet-headless refuses to boot without a default seed. We don't + # actually use the "default" wallet — init-seller-wallet.sh starts the + # "seller" wallet via POST /start with SELLER_SEED at runtime. This is + # the classic all-"abandon" test seed (publicly known, no funds). HEADLESS_SEED_DEFAULT: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" - HEADLESS_TX_MINING_URL: https://txmining.playground.testnet.hathor.network/ entrypoint: ["node", "dist/index.js"] healthcheck: test: ["CMD", "node", "-e", "require('http').get('http://localhost:8000/wallet/status',r=>{process.exit(r.statusCode<500?0:1)}).on('error',()=>process.exit(1))"] @@ -17,23 +24,32 @@ services: retries: 5 start_period: 15s - facilitator: + resource-server: build: . environment: - FULLNODE_URL: https://node1.playground.testnet.hathor.network - WALLET_HEADLESS_URL: http://wallet-headless:8000 - BLUEPRINT_ID: ${BLUEPRINT_ID:-} - CHANNEL_BLUEPRINT_ID: ${CHANNEL_BLUEPRINT_ID:-} - FACILITATOR_WALLET_ID: facilitator - FACILITATOR_ADDRESS: ${FACILITATOR_ADDRESS:-} + FULLNODE_URL: ${FULLNODE_URL:-https://node1.testnet.hathor.network} + HATHOR_NETWORK: ${HATHOR_NETWORK:-testnet} + RESOURCE_SERVER_PORT: "3000" + RESOURCE_SERVER_PUBLIC_URL: ${RESOURCE_SERVER_PUBLIC_URL:-http://localhost:3000} SELLER_ADDRESS: ${SELLER_ADDRESS:-} - FACILITATOR_SEED: ${FACILITATOR_SEED:-} + SELLER_WALLET_URL: http://wallet-headless:8000 + SELLER_WALLET_ID: ${SELLER_WALLET_ID:-seller} SELLER_SEED: ${SELLER_SEED:-} - command: ["sh", "init-wallets.sh", "node", "facilitator.js"] + SERVER_SECRET: ${SERVER_SECRET:-} + REQUEST_ID_TTL_SECONDS: ${REQUEST_ID_TTL_SECONDS:-120} + DEDUP_DB_PATH: /app/data/payments.sqlite + ZERO_CONF_MAX_AMOUNT: ${ZERO_CONF_MAX_AMOUNT:-9007199254740991} + HTR_PAYMENT_AMOUNT: ${HTR_PAYMENT_AMOUNT:-100} + GENERATE_MAX_PRICE: ${GENERATE_MAX_PRICE:-500} + VERIFY_MODE: ${VERIFY_MODE:-self} + FACILITATOR_URL: ${FACILITATOR_URL:-http://facilitator:8402} + command: ["sh", "init-seller-wallet.sh", "node", "resource-server.js"] ports: - - "8402:8402" + - "${RESOURCE_SERVER_HOST_PORT:-3000}:3000" + volumes: + - ./data:/app/data healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:8402/health"] + test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/health',r=>{process.exit(r.statusCode<500?0:1)}).on('error',()=>process.exit(1))"] interval: 10s timeout: 5s retries: 3 @@ -42,39 +58,41 @@ services: wallet-headless: condition: service_healthy - resource-server: + # Optional standalone facilitator. Off by default. Bring up with: + # docker compose --profile facilitator up + # and set VERIFY_MODE=facilitator on the resource-server. + facilitator: + profiles: ["facilitator"] build: . environment: - FULLNODE_URL: https://node1.playground.testnet.hathor.network - WALLET_HEADLESS_URL: http://wallet-headless:8000 - BLUEPRINT_ID: ${BLUEPRINT_ID:-} - CHANNEL_BLUEPRINT_ID: ${CHANNEL_BLUEPRINT_ID:-} - FACILITATOR_ADDRESS: ${FACILITATOR_ADDRESS:-} - SELLER_ADDRESS: ${SELLER_ADDRESS:-} - RESOURCE_SERVER_PORT: "3001" - FACILITATOR_URL: http://facilitator:8402 - FACILITATOR_PUBLIC_URL: https://facilitator.x402.hathor.dev - RESOURCE_SERVER_PUBLIC_URL: https://api.x402.hathor.dev - HATHOR_NETWORK: testnet - command: ["node", "resource-server.js"] + FULLNODE_URL: ${FULLNODE_URL:-https://node1.testnet.hathor.network} + HATHOR_NETWORK: ${HATHOR_NETWORK:-testnet} + FACILITATOR_PORT: "8402" + SERVER_SECRET: ${SERVER_SECRET:-} + DEDUP_DB_PATH: /app/data/payments.sqlite + ZERO_CONF_MAX_AMOUNT: ${ZERO_CONF_MAX_AMOUNT:-9007199254740991} + command: ["node", "facilitator.js"] + ports: + - "${FACILITATOR_HOST_PORT:-8402}:8402" + volumes: + - ./data:/app/data healthcheck: - test: ["CMD", "node", "-e", "require('http').get('http://localhost:3001/weather',r=>{process.exit(r.statusCode<500?0:1)}).on('error',()=>process.exit(1))"] + test: ["CMD", "curl", "-f", "http://localhost:8402/health"] interval: 10s timeout: 5s retries: 3 start_period: 10s - ports: - - "4021:3001" - depends_on: - wallet-headless: - condition: service_healthy - facilitator: - condition: service_healthy dapp: build: context: ./dapp dockerfile: Dockerfile + args: + NEXT_PUBLIC_USE_MOCK_WALLET: ${NEXT_PUBLIC_USE_MOCK_WALLET:-false} + NEXT_PUBLIC_DEFAULT_NETWORK: ${HATHOR_NETWORK:-testnet} + NEXT_PUBLIC_RESOURCE_SERVER_URL: ${NEXT_PUBLIC_RESOURCE_SERVER_URL:-http://localhost:3000} + NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID: ${NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID:-8264fff563181da658ce64ee80e80458} + NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET: ${NEXT_PUBLIC_HATHOR_NODE_URL_TESTNET:-https://node1.testnet.hathor.network/v1a} healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/"] interval: 10s @@ -82,7 +100,7 @@ services: retries: 3 start_period: 15s ports: - - "4020:3000" + - "${DAPP_HOST_PORT:-4020}:3000" depends_on: resource-server: condition: service_healthy diff --git a/examples/mcp-server/README.md b/examples/mcp-server/README.md index f10a095..6b0674d 100644 --- a/examples/mcp-server/README.md +++ b/examples/mcp-server/README.md @@ -1,13 +1,17 @@ # x402 Payment-Gated MCP Server -A minimal example of an MCP server with payment-gated tools using x402 on Hathor Network. +A minimal MCP server whose `get_weather` tool is gated by an x402 `hathor-direct` +payment. AI agents (Claude Code, etc.) call the tool, receive a 402-style +response with payment requirements, send a regular Hathor payment on-chain, +sign the server-issued `requestId` with the payer key, and re-call the tool +with the payment proof. -## What this demonstrates +No facilitator, no nano contracts, no escrow. -- **`get_weather`** tool: Costs 1.00 HTR per call via hathor-escrow -- **`get_price`** tool: Free — returns pricing info for any tool +## What this demonstrates -When an AI agent calls `get_weather` without payment, it receives a 402-style response with Hathor escrow payment requirements. The agent creates an escrow, includes the payment proof, and gets the data. +- `get_weather` — costs `PRICE_PER_CALL` atomic units (default 100 = 1.00 HTR). +- `get_price` — free; returns the current pricing + a fresh `requestId`. ## Setup @@ -16,31 +20,37 @@ cd examples/mcp-server npm install ``` +You'll need: + +- A Hathor address you control (the **seller** address) where payments land +- A 32-byte secret to HMAC `requestId`s with + ## Running ```bash -FACILITATOR_URL=https://facilitator.x402.hathor.dev \ -SELLER_ADDRESS=WZe3ty22... \ -FACILITATOR_ADDRESS=Wb6eLTZS... \ -BLUEPRINT_ID=0000121e... \ +FULLNODE_URL=https://node1.testnet.hathor.network \ +HATHOR_NETWORK=testnet \ +SELLER_ADDRESS=WZe3ty22...your_address... \ +SERVER_SECRET=$(openssl rand -hex 32) \ +PRICE_PER_CALL=100 \ node server.js ``` ## Using with Claude Code -Add to your Claude Code MCP config (`~/.claude/claude_desktop_config.json`): +Add to your MCP config (`~/.claude/claude_desktop_config.json`): ```json { "mcpServers": { "x402-weather": { "command": "node", - "args": ["/path/to/examples/mcp-server/server.js"], + "args": ["/abs/path/to/examples/mcp-server/server.js"], "env": { - "FACILITATOR_URL": "https://facilitator.x402.hathor.dev", + "FULLNODE_URL": "https://node1.testnet.hathor.network", + "HATHOR_NETWORK": "testnet", "SELLER_ADDRESS": "WZe3ty22...", - "FACILITATOR_ADDRESS": "Wb6eLTZS...", - "BLUEPRINT_ID": "0000121e..." + "SERVER_SECRET": "..." } } } @@ -50,17 +60,47 @@ Add to your Claude Code MCP config (`~/.claude/claude_desktop_config.json`): ## Payment flow ``` -Agent MCP Server Facilitator Hathor - | | | | - |-- get_weather(city) ---->| | | - |<---- 402 + accepts[] ----| | | - | | | | - |-- create escrow ---------|------------------------|----deposit---->| - | | | | - |-- get_weather(city, ---->| | | - | payment=proof) |-- verify ------------->| | - | |<--- valid: true -------| | - | |-- settle ------------->|--release()---->| - | |<--- txId --------------| | - |<---- weather data -------| | | +Agent MCP server Hathor fullnode + | | | + |-- get_weather(city) -------->| | + |<-- 402 + accepts[] ----------| | + | | | + |-- send_tokens(amount,payTo)----------send tx---------->| + | (regular Hathor payment; | + | no contract, no escrow) | + | | | + |-- sign(requestId) ---->[wallet] | + | | | + |-- get_weather(city, payment=base64(payload)) --------->| + | |-- fetch tx, check sig, | + | | dedup, zero-conf safety + | | | + |<-- weather data + payment ---| | +``` + +The `payment` argument is a base64-encoded JSON `PaymentPayload`: + +```jsonc +{ + "x402Version": 2, + "scheme": "hathor-direct", + "network": "hathor:testnet", + "payload": { + "txId": "000abc…", + "payerAddress": "WPo2…", + "signature": "BASE64…", // bitcore.Message signature of requestId + "requestId": "." + } +} ``` + +## Notes + +- Dedup ledger lives at `./data/payments.sqlite` by default. Override with + `DEDUP_DB_PATH`. +- Zero-confirmation is accepted (the verifier rejects voided/conflicting txs + at verify time; a real production deployment would also wire a post-serve + void watcher and a blocklist). +- This example reuses the top-level `verifier.js` / `dedupStore.js` / + `requestId.js` modules. Run `npm install` from the example directory to + pull `better-sqlite3` (needed by the dedup store). diff --git a/examples/mcp-server/package.json b/examples/mcp-server/package.json index 9531096..add0d6a 100644 --- a/examples/mcp-server/package.json +++ b/examples/mcp-server/package.json @@ -1,7 +1,7 @@ { "name": "x402-mcp-server-example", - "version": "0.1.0", - "description": "Example MCP server with x402 payment-gated tools on Hathor Network", + "version": "0.2.0", + "description": "Example MCP server with x402 hathor-direct payment-gated tools", "license": "MIT", "type": "module", "scripts": { @@ -9,9 +9,11 @@ }, "dependencies": { "@modelcontextprotocol/sdk": "^1.12.1", - "node-fetch": "^3.3.2" + "better-sqlite3": "^11.5.0", + "@hathor/wallet-lib": "^2.17.0", + "zod": "^3.23.8" }, "engines": { - "node": ">=18" + "node": ">=22" } } diff --git a/examples/mcp-server/server.js b/examples/mcp-server/server.js index 62b1cc7..cbde596 100644 --- a/examples/mcp-server/server.js +++ b/examples/mcp-server/server.js @@ -1,159 +1,166 @@ #!/usr/bin/env node -// x402 Payment-Gated MCP Server Example +// x402-gated MCP server — single-tool example. // -// Demonstrates how to build an MCP server where tool calls require x402 payment -// on Hathor Network. AI agents (Claude Code, etc.) can discover and pay for tools. +// `get_weather` returns weather data only if the caller includes a valid +// `payment` argument (base64-encoded x402 PaymentPayload pointing at an +// on-chain hathor-direct payment). The server verifies the payment locally +// via the shared verifier — no facilitator, no escrow, no nano contracts. // -// Flow: -// 1. Agent calls a tool (e.g., get_weather) -// 2. Server returns a 402-style error with payment requirements -// 3. Agent creates an escrow on Hathor, sends payment proof -// 4. Server verifies + settles via the facilitator, returns data +// Run: +// SELLER_ADDRESS=WZe3... SERVER_SECRET=... node server.js // -// Usage: -// FACILITATOR_URL=https://facilitator.x402.hathor.dev \ -// SELLER_ADDRESS=WZe3... \ -// BLUEPRINT_ID=0000121e... \ -// node server.js +// Use with Claude Code: see README. import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { z } from 'zod'; +import { createRequire } from 'module'; +import path from 'path'; +import { fileURLToPath } from 'url'; -// --------------------------------------------------------------------------- -// Configuration -// --------------------------------------------------------------------------- +const require = createRequire(import.meta.url); +const { openStore } = require('../../dedupStore.js'); +const { mintRequestId } = require('../../requestId.js'); +const { verifyDirectPayment } = require('../../verifier.js'); -const config = { - facilitatorUrl: process.env.FACILITATOR_URL || 'https://facilitator.x402.hathor.dev', - facilitatorAddress: process.env.FACILITATOR_ADDRESS || '', - sellerAddress: process.env.SELLER_ADDRESS || '', - blueprintId: process.env.BLUEPRINT_ID || '', +// --- config ---------------------------------------------------------------- + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const DEFAULT_DEDUP = path.join(__dirname, 'data', 'payments.sqlite'); + +const cfg = { + fullnodeUrl: process.env.FULLNODE_URL || 'https://node1.testnet.hathor.network', network: process.env.HATHOR_NETWORK || 'testnet', + sellerAddress: process.env.SELLER_ADDRESS || '', + serverSecret: process.env.SERVER_SECRET || '', + requestIdTtlSeconds: parseInt(process.env.REQUEST_ID_TTL_SECONDS || '120', 10), htrTokenUid: '00', - pricePerCall: 100, // 1.00 HTR in smallest units - deadlineSeconds: 300, + pricePerCall: parseInt(process.env.PRICE_PER_CALL || '100', 10), + dedupDbPath: process.env.DEDUP_DB_PATH || DEFAULT_DEDUP, + resourceBase: process.env.MCP_RESOURCE_BASE || 'mcp://x402-mcp-server', }; -// --------------------------------------------------------------------------- -// x402 helpers -// --------------------------------------------------------------------------- +if (!cfg.sellerAddress) { + // eslint-disable-next-line no-console + console.error('[x402-mcp] WARNING: SELLER_ADDRESS unset — 402 responses will be invalid'); +} +if (!cfg.serverSecret) { + // eslint-disable-next-line no-console + console.error('[x402-mcp] WARNING: SERVER_SECRET unset — requestId verification will reject everything'); +} + +const store = openStore(cfg.dedupDbPath); + +// --- 402 + verify helpers -------------------------------------------------- function buildPaymentRequired(toolName) { + const resource = `${cfg.resourceBase}/tool/${toolName}`; + const network = `hathor:${cfg.network}`; + const requestId = mintRequestId( + { + route: resource, + amount: String(cfg.pricePerCall), + payTo: cfg.sellerAddress, + asset: cfg.htrTokenUid, + network, + }, + cfg.serverSecret || 'dev-fallback-secret', + cfg.requestIdTtlSeconds + ); return { x402Version: 2, - accepts: [ - { - scheme: 'hathor-escrow', - network: `hathor:${config.network}`, - resource: `mcp://x402-mcp-server/tool/${toolName}`, - mimeType: 'application/json', - payTo: config.sellerAddress, - maxTimeoutSeconds: config.deadlineSeconds, - asset: config.htrTokenUid, - price: String(config.pricePerCall), - description: `Pay ${(config.pricePerCall / 100).toFixed(2)} HTR for ${toolName}`, - extra: { - facilitatorUrl: config.facilitatorUrl, - facilitatorAddress: config.facilitatorAddress, - blueprintId: config.blueprintId, - deadlineSeconds: config.deadlineSeconds, - }, - }, - ], + accepts: [{ + scheme: 'hathor-direct', + network, + resource, + amount: String(cfg.pricePerCall), + asset: cfg.htrTokenUid, + payTo: cfg.sellerAddress, + maxTimeoutSeconds: cfg.requestIdTtlSeconds, + description: `Pay ${(cfg.pricePerCall / 100).toFixed(2)} HTR for ${toolName}`, + extra: { requestId }, + }], }; } -async function verifyAndSettle(paymentProof) { - const paymentPayload = typeof paymentProof === 'string' - ? JSON.parse(Buffer.from(paymentProof, 'base64').toString('utf-8')) - : paymentProof; - - // Verify - const verifyResp = await fetch(`${config.facilitatorUrl}/x402/verify`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - paymentPayload, - paymentRequirements: [{ - scheme: 'hathor-escrow', - network: `hathor:${config.network}`, - maxAmountRequired: String(config.pricePerCall), - payTo: config.sellerAddress, - asset: config.htrTokenUid, - }], - }), - }); - const verification = await verifyResp.json(); - if (!verification.valid) { - throw new Error(`Payment invalid: ${verification.invalidReason}`); +async function verifyPayment(paymentArg, toolName) { + let payload; + try { + payload = typeof paymentArg === 'string' + ? JSON.parse(Buffer.from(paymentArg, 'base64').toString('utf-8')) + : paymentArg; + } catch (_) { + return { valid: false, invalidReason: 'invalid_payment_encoding' }; } - // Settle - const settleResp = await fetch(`${config.facilitatorUrl}/x402/settle`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ paymentPayload }), - }); - const settlement = await settleResp.json(); - if (!settlement.success) { - throw new Error(`Settlement failed: ${settlement.error}`); - } + const resource = `${cfg.resourceBase}/tool/${toolName}`; + const requirement = { + scheme: 'hathor-direct', + network: `hathor:${cfg.network}`, + amount: String(cfg.pricePerCall), + asset: cfg.htrTokenUid, + payTo: cfg.sellerAddress, + resource, + }; - return settlement; + return verifyDirectPayment({ + payload, + requirements: requirement, + fullnodeUrl: cfg.fullnodeUrl, + dedupStore: store, + serverSecret: cfg.serverSecret, + zeroConfMaxAmount: Number.MAX_SAFE_INTEGER, + }); } -// --------------------------------------------------------------------------- -// MCP Server -// --------------------------------------------------------------------------- +// --- MCP server ------------------------------------------------------------ const server = new McpServer({ name: 'x402-weather', - version: '0.1.0', + version: '0.2.0', }); -// Paid tool: get_weather server.tool( 'get_weather', - 'Get current weather for a city. Costs 1.00 HTR per call via x402 payment.', + 'Get current weather for a city. Costs 1.00 HTR per call via x402 hathor-direct payment.', { city: z.string().describe('City name (e.g., "Sao Paulo")'), - payment: z.string().optional().describe('Base64-encoded x402 PAYMENT-SIGNATURE (hathor-escrow proof)'), + payment: z.string().optional().describe('Base64-encoded x402 hathor-direct PaymentPayload (JSON)'), }, async ({ city, payment }) => { - // No payment? Return 402-style payment requirements if (!payment) { const requirements = buildPaymentRequired('get_weather'); return { - content: [ - { - type: 'text', - text: JSON.stringify({ - error: 'payment_required', - status: 402, - message: `This tool costs ${(config.pricePerCall / 100).toFixed(2)} HTR per call. Include a "payment" parameter with your x402 payment proof.`, - ...requirements, - }, null, 2), - }, - ], + content: [{ + type: 'text', + text: JSON.stringify({ + error: 'payment_required', + status: 402, + message: `This tool costs ${(cfg.pricePerCall / 100).toFixed(2)} HTR per call. Include a "payment" argument (base64 JSON) with a hathor-direct PaymentPayload.`, + ...requirements, + }, null, 2), + }], isError: true, }; } - // Verify and settle payment - let settlement; - try { - settlement = await verifyAndSettle(payment); - } catch (err) { + const verification = await verifyPayment(payment, 'get_weather'); + if (!verification.valid) { return { - content: [{ type: 'text', text: JSON.stringify({ error: 'payment_failed', message: err.message }) }], + content: [{ + type: 'text', + text: JSON.stringify({ + error: 'payment_invalid', + reason: verification.invalidReason, + ...buildPaymentRequired('get_weather'), + }, null, 2), + }], isError: true, }; } - // Payment confirmed — return the weather data - const weatherData = { + const data = { city, temperature: Math.round(20 + Math.random() * 15), humidity: Math.round(40 + Math.random() * 40), @@ -163,64 +170,64 @@ server.tool( }; return { - content: [ - { - type: 'text', - text: JSON.stringify({ - data: weatherData, - payment: { - x402Version: 2, - success: true, - scheme: 'hathor-escrow', - network: `hathor:${config.network}`, - settleTxId: settlement.txId, - }, - }, null, 2), - }, - ], + content: [{ + type: 'text', + text: JSON.stringify({ + data, + payment: { + x402Version: 2, + success: true, + scheme: 'hathor-direct', + network: `hathor:${cfg.network}`, + transaction: verification.txId, + payer: verification.payerAddress, + amount: String(verification.amount), + idempotent: !!verification.idempotent, + }, + }, null, 2), + }], }; }, ); -// Free tool: get_price (shows how to mix free and paid tools) +// Free tool: pricing/discovery. server.tool( 'get_price', - 'Get the current x402 price for a tool call. Free — no payment needed.', - { - tool_name: z.string().describe('Name of the tool to check pricing for'), - }, + 'Get the current x402 price + payment requirements for a tool. Free.', + { tool_name: z.string().describe('Tool name to check pricing for') }, async ({ tool_name }) => { const requirements = buildPaymentRequired(tool_name); return { - content: [ - { - type: 'text', - text: JSON.stringify({ - tool: tool_name, - price: `${(config.pricePerCall / 100).toFixed(2)} HTR`, - network: `hathor:${config.network}`, - paymentInfo: requirements, - }, null, 2), - }, - ], + content: [{ + type: 'text', + text: JSON.stringify({ + tool: tool_name, + price: `${(cfg.pricePerCall / 100).toFixed(2)} HTR`, + network: `hathor:${cfg.network}`, + paymentInfo: requirements, + }, null, 2), + }], }; }, ); -// --------------------------------------------------------------------------- -// Start -// --------------------------------------------------------------------------- +// --- Run ------------------------------------------------------------------- async function main() { const transport = new StdioServerTransport(); await server.connect(transport); - console.error('[x402-mcp-server] Running on stdio'); - console.error(`[x402-mcp-server] Seller: ${config.sellerAddress}`); - console.error(`[x402-mcp-server] Facilitator: ${config.facilitatorUrl}`); - console.error(`[x402-mcp-server] Price per call: ${(config.pricePerCall / 100).toFixed(2)} HTR`); + // eslint-disable-next-line no-console + console.error('[x402-mcp] Running on stdio'); + // eslint-disable-next-line no-console + console.error(`[x402-mcp] Seller: ${cfg.sellerAddress}`); + // eslint-disable-next-line no-console + console.error(`[x402-mcp] Network: ${cfg.network} via ${cfg.fullnodeUrl}`); + // eslint-disable-next-line no-console + console.error(`[x402-mcp] Dedup store: ${cfg.dedupDbPath}`); } -main().catch(err => { - console.error(`[x402-mcp-server] Fatal: ${err.message}`); +main().catch((err) => { + // eslint-disable-next-line no-console + console.error(`[x402-mcp] Fatal: ${err.message}`); process.exit(1); }); diff --git a/facilitator.js b/facilitator.js index d55d1fb..fd72954 100644 --- a/facilitator.js +++ b/facilitator.js @@ -1,362 +1,141 @@ -// x402 Facilitator Server -// Exposes /x402/verify and /x402/settle endpoints -// Supports both escrow (hathor-escrow) and channel (hathor-channel) schemes -// Talks to hathor-forge fullnode for state queries and wallet-headless for settlement +// x402 Facilitator — thin, read-only HTTP wrapper around verifier.js. +// +// This binary is optional in the new design. A resource server with a +// fullnode connection can self-verify (see resource-server.js, VERIFY_MODE). +// The facilitator exists for the case where multiple resource servers want +// to share a dedup/blocklist store, or where a seller wants to outsource the +// verification step. +// +// No wallet. No seed. No nano-contract knowledge. No on-chain settlement. + +'use strict'; const express = require('express'); const config = require('./config'); -const { walletRequest, getNanoContractState, waitForTxConfirmation, log } = require('./helpers'); +const { log } = require('./helpers'); +const { openStore } = require('./dedupStore'); +const { verifyDirectPayment } = require('./verifier'); -const app = express(); -app.use(express.json()); - -// ============================================================================ -// Settlement cache for Payment-Identifier idempotency (#8) -// Key: ncId or channelId+amount, Value: settlement result -// ============================================================================ -const settlementCache = new Map(); - -// ============================================================================ -// ESCROW verification/settlement (one contract per payment) -// ============================================================================ - -function validateEscrowAgainstRequirement(fields, req) { - const errors = []; - if (fields.phase.value !== 'LOCKED') errors.push(`phase is ${fields.phase.value}, expected LOCKED`); - if (fields.amount.value < parseInt(req.maxAmountRequired)) errors.push(`amount ${fields.amount.value} < required ${req.maxAmountRequired}`); - if (fields.seller.value !== req.payTo) errors.push(`seller ${fields.seller.value} != payTo ${req.payTo}`); - if (fields.facilitator.value !== config.facilitatorAddress) errors.push(`facilitator mismatch`); - if (req.asset && fields.token_uid.value !== req.asset) errors.push(`token_uid ${fields.token_uid.value} != asset ${req.asset}`); - return errors; -} - -async function verifyEscrow(ncId, requirements) { - const stateResp = await getNanoContractState(ncId); - if (!stateResp.success) return { x402Version: 2, valid: false, invalidReason: `Cannot query contract: ${stateResp.message}` }; - - const reqs = Array.isArray(requirements) ? requirements : [requirements]; - let lastErrors = []; - for (const req of reqs) { - const errors = validateEscrowAgainstRequirement(stateResp.fields, req); - if (errors.length === 0) return { x402Version: 2, valid: true }; - lastErrors = errors; - } - return { x402Version: 2, valid: false, invalidReason: lastErrors.join('; ') }; -} - -async function settleEscrow(ncId) { - const stateResp = await getNanoContractState(ncId); - if (!stateResp.success) return { x402Version: 2, success: false, error: `Cannot query contract` }; - - const fields = stateResp.fields; - if (fields.phase.value !== 'LOCKED') return { x402Version: 2, success: false, error: `Escrow not locked (phase=${fields.phase.value})` }; - - const amount = fields.amount.value; - const seller = fields.seller.value; - const tokenUid = fields.token_uid.value; - - log('FACILITATOR', `Escrow release() — ${amount} of ${tokenUid} to ${seller}`); - const result = await walletRequest('POST', '/wallet/nano-contracts/execute', { - nc_id: ncId, - method: 'release', - address: config.facilitatorAddress, - data: { args: [], actions: [{ type: 'withdrawal', token: tokenUid, amount, address: seller }] }, - }, config.facilitatorWalletId); - - if (!result.success) return { x402Version: 2, success: false, error: result.message || 'release() failed' }; - // Don't wait for block confirmation — tx is accepted by the node, it will confirm eventually - return { - x402Version: 2, - success: true, - scheme: 'hathor-escrow', - txId: result.hash, - chargedAmount: amount, - network: `hathor:${config.network || 'privatenet'}`, - }; +if (!config.serverSecret) { + log('FACILITATOR', 'WARNING: SERVER_SECRET not set — requestId verification will reject everything'); } -// "upto" scheme: release `chargedAmount` to seller, refund the remainder to buyer. -// Two on-chain calls: -// 1. release_upto(chargedAmount) -> withdraws chargedAmount to seller -// 2. refund() -> withdraws remainder to buyer (only if > 0) -async function settleEscrowUpto(ncId, chargedAmount) { - const stateResp = await getNanoContractState(ncId); - if (!stateResp.success) return { x402Version: 2, success: false, error: `Cannot query contract` }; - - const fields = stateResp.fields; - if (fields.phase.value !== 'LOCKED') return { x402Version: 2, success: false, error: `Escrow not locked (phase=${fields.phase.value})` }; - - const maxAmount = fields.amount.value; - const seller = fields.seller.value; - const buyer = fields.buyer.value; - const tokenUid = fields.token_uid.value; - - const charged = parseInt(chargedAmount); - if (!Number.isFinite(charged) || charged <= 0) { - return { x402Version: 2, success: false, error: `Invalid chargedAmount: ${chargedAmount}` }; - } - if (charged > maxAmount) { - return { x402Version: 2, success: false, error: `chargedAmount ${charged} exceeds escrow ${maxAmount}` }; - } - - const refund = maxAmount - charged; - - // Step 1: release_upto(charged) — withdraws charged to seller - log('FACILITATOR', `Escrow release_upto(${charged}) — to seller ${seller} (max ${maxAmount}, refund ${refund})`); - const releaseResult = await walletRequest('POST', '/wallet/nano-contracts/execute', { - nc_id: ncId, - method: 'release_upto', - address: config.facilitatorAddress, - data: { - args: [charged], - actions: [{ type: 'withdrawal', token: tokenUid, amount: charged, address: seller }], - }, - }, config.facilitatorWalletId); - - if (!releaseResult.success) { - return { x402Version: 2, success: false, error: releaseResult.message || 'release_upto() failed' }; - } - - // Step 2 (only if there is a remainder): refund() — withdraws remainder to buyer - let refundTxId = null; - if (refund > 0) { - log('FACILITATOR', `Escrow refund() — ${refund} of ${tokenUid} to buyer ${buyer}`); - const refundResult = await walletRequest('POST', '/wallet/nano-contracts/execute', { - nc_id: ncId, - method: 'refund', - address: config.facilitatorAddress, - data: { - args: [], - actions: [{ type: 'withdrawal', token: tokenUid, amount: refund, address: buyer }], - }, - }, config.facilitatorWalletId); - if (!refundResult.success) { - // The charge went through but the refund failed. Return partial success so the - // seller still gets paid and the buyer can retry the refund later. - return { - x402Version: 2, - success: true, - scheme: 'hathor-escrow-upto', - txId: releaseResult.hash, - chargedAmount: charged, - refundAmount: 0, - refundError: refundResult.message || 'refund() failed', - network: `hathor:${config.network || 'privatenet'}`, - }; - } - refundTxId = refundResult.hash; - } - - return { - x402Version: 2, - success: true, - scheme: 'hathor-escrow-upto', - txId: releaseResult.hash, - refundTxId, - chargedAmount: charged, - refundAmount: refund, - network: `hathor:${config.network || 'privatenet'}`, - }; -} - -// ============================================================================ -// CHANNEL verification/settlement (pre-funded, multiple payments) -// ============================================================================ - -const CHANNEL_FIELDS = ['buyer', 'facilitator', 'token_uid', 'total_deposited', 'total_spent', 'phase', 'deadline']; - -async function getChannelState(channelId) { - const queryString = CHANNEL_FIELDS.map(f => `fields[]=${f}`).join('&'); - const url = `${config.fullnodeUrl}/v1a/nano_contract/state?id=${channelId}&${queryString}`; - const resp = await require('node-fetch')(url); - return resp.json(); -} - -async function verifyChannel(channelId, requirements) { - const stateResp = await getChannelState(channelId); - if (!stateResp.success) return { x402Version: 2, valid: false, invalidReason: `Cannot query channel: ${stateResp.message}` }; - - const fields = stateResp.fields; - if (fields.phase.value !== 'OPEN') return { x402Version: 2, valid: false, invalidReason: `Channel not open (phase=${fields.phase.value})` }; - if (fields.facilitator.value !== config.facilitatorAddress) return { x402Version: 2, valid: false, invalidReason: 'Facilitator mismatch' }; - - const remaining = fields.total_deposited.value - fields.total_spent.value; - const reqs = Array.isArray(requirements) ? requirements : [requirements]; +const store = openStore(config.dedupDbPath); +const app = express(); +app.use(express.json({ limit: '32kb' })); + +// CORS — facilitator is called server-to-server, but allow browsers too for +// development tooling. +app.use((req, res, next) => { + res.header('Access-Control-Allow-Origin', '*'); + res.header('Access-Control-Allow-Headers', 'Content-Type'); + if (req.method === 'OPTIONS') return res.sendStatus(204); + next(); +}); - for (const req of reqs) { - const amount = parseInt(req.maxAmountRequired || req.price || req.amount); - if (remaining >= amount) { - if (req.asset && fields.token_uid.value !== req.asset) continue; - return { x402Version: 2, valid: true, remaining }; - } +function pickRequirement(requirements, scheme) { + if (Array.isArray(requirements)) { + const match = requirements.find((r) => r && r.scheme === scheme); + return match || requirements[0]; } - return { x402Version: 2, valid: false, invalidReason: `Insufficient channel balance (remaining: ${remaining})` }; -} - -async function settleChannel(channelId, amount, sellerAddress) { - const stateResp = await getChannelState(channelId); - if (!stateResp.success) return { x402Version: 2, success: false, error: 'Cannot query channel' }; - - const fields = stateResp.fields; - if (fields.phase.value !== 'OPEN') return { x402Version: 2, success: false, error: 'Channel not open' }; - - const tokenUid = fields.token_uid.value; - const remaining = fields.total_deposited.value - fields.total_spent.value; - if (remaining < amount) return { x402Version: 2, success: false, error: `Insufficient balance (${remaining} < ${amount})` }; - - log('FACILITATOR', `Channel spend() — ${amount} of ${tokenUid} to ${sellerAddress}`); - const result = await walletRequest('POST', '/wallet/nano-contracts/execute', { - nc_id: channelId, - method: 'spend', - address: config.facilitatorAddress, - data: { - args: [amount, sellerAddress], - actions: [{ type: 'withdrawal', token: tokenUid, amount, address: sellerAddress }], - }, - }, config.facilitatorWalletId); - - if (!result.success) return { x402Version: 2, success: false, error: result.message || 'spend() failed' }; - return { x402Version: 2, success: true, txId: result.hash, network: `hathor:${config.network || 'privatenet'}` }; + return requirements; } -// ============================================================================ -// HTTP Endpoints (scheme-agnostic) -// ============================================================================ - app.post('/x402/verify', async (req, res) => { - const { paymentPayload, paymentRequirements } = req.body; - const scheme = paymentPayload.scheme; - - if (scheme === 'hathor-channel') { - const { channelId } = paymentPayload.payload; - log('FACILITATOR', `Channel verify for channelId=${channelId}`); - const result = await verifyChannel(channelId, paymentRequirements); - log('FACILITATOR', `Channel verify ${result.valid ? 'PASSED' : 'FAILED'}: ${result.invalidReason || 'OK'}`); - return res.json(result); + const { paymentPayload, paymentRequirements } = req.body || {}; + if (!paymentPayload || !paymentRequirements) { + return res.status(400).json({ x402Version: 2, valid: false, invalidReason: 'missing_fields' }); } + const requirement = pickRequirement(paymentRequirements, paymentPayload.scheme); - // Default: escrow (both "hathor-escrow" exact and "hathor-escrow-upto" verify against the same contract state) - const { ncId } = paymentPayload.payload; - log('FACILITATOR', `Escrow verify for ncId=${ncId} (scheme=${scheme})`); - const result = await verifyEscrow(ncId, paymentRequirements); - log('FACILITATOR', `Escrow verify ${result.valid ? 'PASSED' : 'FAILED'}: ${result.invalidReason || 'OK'}`); - res.json(result); -}); - -app.post('/x402/settle', async (req, res) => { - const { paymentPayload } = req.body; - const scheme = paymentPayload.scheme; - - if (scheme === 'hathor-channel') { - const { channelId } = paymentPayload.payload; - const amount = req.body.amount || paymentPayload.payload.amount; - const sellerAddress = req.body.sellerAddress || paymentPayload.payload.sellerAddress; - // No idempotency cache for channels — same channelId is reused across requests - log('FACILITATOR', `Channel settle for channelId=${channelId}, amount=${amount}`); - const result = await settleChannel(channelId, amount, sellerAddress); - log('FACILITATOR', `Channel settle ${result.success ? 'SUCCESS' : 'FAILED'}: ${result.txId || result.error}`); - return res.json(result); - } - - // Escrow (exact or upto) - const { ncId } = paymentPayload.payload; - const isUpto = scheme === 'hathor-escrow-upto'; - // Cache key differs between schemes so an exact/upto mismatch can never collide - const cacheKey = isUpto ? `escrow-upto:${ncId}` : `escrow:${ncId}`; - - // Idempotency: return cached result if already settled - if (settlementCache.has(cacheKey)) { - log('FACILITATOR', `Escrow settle CACHED for ncId=${ncId} (scheme=${scheme})`); - return res.json(settlementCache.get(cacheKey)); - } - - let result; - if (isUpto) { - const chargedAmount = req.body.chargedAmount ?? paymentPayload.payload.chargedAmount; - if (chargedAmount == null) { - return res.json({ x402Version: 2, success: false, error: 'chargedAmount required for hathor-escrow-upto' }); - } - log('FACILITATOR', `Escrow-upto settle for ncId=${ncId}, chargedAmount=${chargedAmount}`); - result = await settleEscrowUpto(ncId, chargedAmount); - } else { - log('FACILITATOR', `Escrow settle for ncId=${ncId}`); - result = await settleEscrow(ncId); + try { + const result = await verifyDirectPayment({ + payload: paymentPayload, + requirements: requirement, + fullnodeUrl: config.fullnodeUrl, + dedupStore: store, + serverSecret: config.serverSecret, + zeroConfMaxAmount: config.zeroConfMaxAmount, + }); + log('FACILITATOR', `verify ${result.valid ? 'PASSED' : 'FAILED'}${result.invalidReason ? `: ${result.invalidReason}` : ''}${result.idempotent ? ' (idempotent)' : ''}`); + return res.json({ x402Version: 2, ...result }); + } catch (err) { + log('FACILITATOR', `verify error: ${err.message}`); + return res.status(500).json({ x402Version: 2, valid: false, invalidReason: 'verifier_error' }); } - log('FACILITATOR', `Escrow settle ${result.success ? 'SUCCESS' : 'FAILED'}: ${result.txId || result.error}`); - if (result.success) settlementCache.set(cacheKey, result); - res.json(result); }); -// ============================================================================ -// Health check & wallet auto-recovery (#12) -// ============================================================================ - -async function checkWalletStatus(walletId) { - try { - const result = await walletRequest('GET', '/wallet/status', null, walletId); - return result.statusCode === 3; // 3 = READY - } catch { - return false; +// Settle is a no-op for hathor-direct: the payment is already on-chain. We +// re-verify (which is idempotent thanks to the dedup row) and echo a v2-style +// settlement response. +app.post('/x402/settle', async (req, res) => { + const { paymentPayload, paymentRequirements } = req.body || {}; + if (!paymentPayload || !paymentRequirements) { + return res.status(400).json({ x402Version: 2, success: false, errorReason: 'missing_fields' }); } -} + const requirement = pickRequirement(paymentRequirements, paymentPayload.scheme); -async function restartWallet(walletId, seed) { try { - log('FACILITATOR', `Restarting wallet: ${walletId}`); - // Stop first (ignore errors if not started) - await walletRequest('POST', '/wallet/stop', {}, walletId).catch(() => {}); - // Start with seed - const result = await require('node-fetch')(`${config.walletHeadlessUrl}/start`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ 'wallet-id': walletId, seed }), - }).then(r => r.json()); - log('FACILITATOR', `Wallet ${walletId} restart result: ${JSON.stringify(result)}`); - return result.success !== false; + const result = await verifyDirectPayment({ + payload: paymentPayload, + requirements: requirement, + fullnodeUrl: config.fullnodeUrl, + dedupStore: store, + serverSecret: config.serverSecret, + zeroConfMaxAmount: config.zeroConfMaxAmount, + }); + if (!result.valid) { + return res.json({ + x402Version: 2, + success: false, + errorReason: result.invalidReason, + transaction: '', + network: requirement.network, + }); + } + return res.json({ + x402Version: 2, + success: true, + scheme: paymentPayload.scheme, + network: requirement.network, + transaction: result.txId, + amount: String(result.amount), + payer: result.payerAddress, + }); } catch (err) { - log('FACILITATOR', `Wallet ${walletId} restart failed: ${err.message}`); - return false; + return res.status(500).json({ + x402Version: 2, + success: false, + errorReason: 'verifier_error', + transaction: '', + network: requirement && requirement.network, + }); } -} - -async function ensureWalletsReady() { - const facilitatorOk = await checkWalletStatus(config.facilitatorWalletId); - const sellerOk = await checkWalletStatus(config.sellerWalletId); - - if (!facilitatorOk && process.env.FACILITATOR_SEED) { - await restartWallet(config.facilitatorWalletId, process.env.FACILITATOR_SEED); - } - if (!sellerOk && process.env.SELLER_SEED) { - await restartWallet(config.sellerWalletId, process.env.SELLER_SEED); - } -} - -// Periodic wallet health check (every 30 seconds) -setInterval(() => { - ensureWalletsReady().catch(err => log('FACILITATOR', `Wallet check error: ${err.message}`)); -}, 30000); +}); -app.get('/health', async (req, res) => { - const facilitatorOk = await checkWalletStatus(config.facilitatorWalletId); - const sellerOk = await checkWalletStatus(config.sellerWalletId); - const healthy = facilitatorOk && sellerOk; +// Discovery — advertise the scheme/network pairs we'll handle. +app.get('/supported', (_req, res) => { + res.json({ + x402Version: 2, + kinds: [ + { x402Version: 2, scheme: 'hathor-direct', network: `hathor:${config.network}` }, + { x402Version: 2, scheme: 'hathor-direct-upto', network: `hathor:${config.network}` }, + ], + extensions: [], + }); +}); - res.status(healthy ? 200 : 503).json({ - status: healthy ? 'healthy' : 'degraded', - wallets: { - facilitator: facilitatorOk ? 'ready' : 'disconnected', - seller: sellerOk ? 'ready' : 'disconnected', - }, - settlementCacheSize: settlementCache.size, +app.get('/health', (_req, res) => { + res.json({ + status: 'healthy', + network: config.network, + fullnodeUrl: config.fullnodeUrl, + dedup: store.stats(), uptime: process.uptime(), }); }); app.listen(config.facilitatorPort, () => { - log('FACILITATOR', `x402 Facilitator running on port ${config.facilitatorPort}`); - log('FACILITATOR', `Facilitator address: ${config.facilitatorAddress}`); - log('FACILITATOR', `Escrow blueprint: ${config.blueprintId}`); - log('FACILITATOR', `Channel blueprint: ${config.channelBlueprintId}`); - // Initial wallet check on startup - ensureWalletsReady().catch(err => log('FACILITATOR', `Initial wallet check error: ${err.message}`)); + log('FACILITATOR', `Running on :${config.facilitatorPort} — network=${config.network}, fullnode=${config.fullnodeUrl}`); + log('FACILITATOR', `Dedup store: ${config.dedupDbPath}`); }); diff --git a/helpers.js b/helpers.js index 47c1320..da5f503 100644 --- a/helpers.js +++ b/helpers.js @@ -1,49 +1,126 @@ -// Shared helpers for talking to wallet-headless and fullnode +// Small utilities shared across the backend: structured logging, fullnode +// reads, tx introspection, and bitcore-style message-signature verification. -const fetch = require('node-fetch'); -const config = require('./config'); - -async function walletRequest(method, path, body, walletId) { - const url = `${config.walletHeadlessUrl}${path}`; - const headers = { 'Content-Type': 'application/json' }; - if (walletId) headers['X-Wallet-Id'] = walletId; +'use strict'; - const opts = { method, headers }; - if (body && method !== 'GET') opts.body = JSON.stringify(body); +const config = require('./config'); - const resp = await fetch(url, opts); - return resp.json(); +function log(component, msg) { + // eslint-disable-next-line no-console + console.log(`[${component}] ${msg}`); } +// --- Fullnode HTTP ----------------------------------------------------------- + async function fullnodeRequest(path) { const url = `${config.fullnodeUrl}/v1a${path}`; const resp = await fetch(url); return resp.json(); } -async function getNanoContractState(ncId) { - return fullnodeRequest(`/nano_contract/state?id=${ncId}&fields[]=buyer&fields[]=seller&fields[]=facilitator&fields[]=token_uid&fields[]=amount&fields[]=phase&fields[]=deadline&fields[]=resource_url&fields[]=request_hash&balances[]=00`); +// GET /v1a/transaction?id= +// Returns { success, tx?, meta? } where meta has voided_by / conflict_with / first_block. +async function getTransaction(txId) { + return fullnodeRequest(`/transaction?id=${encodeURIComponent(txId)}`); } -async function waitForTxConfirmation(txId, maxAttempts = 30) { +// Poll until the tx is visible at our fullnode. We don't wait for first_block — +// the verifier is the one that decides whether zero-conf is OK for the amount. +async function waitForTxInMempool(txId, { maxAttempts = 30, intervalMs = 1000 } = {}) { for (let i = 0; i < maxAttempts; i++) { - const resp = await fullnodeRequest(`/transaction?id=${txId}`); - if (resp.success && resp.tx && resp.meta && resp.meta.first_block) { - return resp; - } - await new Promise(r => setTimeout(r, 1000)); + try { + const resp = await getTransaction(txId); + if (resp.success && resp.tx) return resp; + } catch (_) { /* swallow and retry */ } + await new Promise((r) => setTimeout(r, intervalMs)); } - throw new Error(`Transaction ${txId} not confirmed after ${maxAttempts}s`); + throw new Error(`tx ${txId} not visible at fullnode after ${maxAttempts} polls`); } -function log(component, msg) { - console.log(`[${component}] ${msg}`); +// --- Transaction introspection ---------------------------------------------- + +// Resolve an output's token UID by looking at token_data + the tx.tokens list. +// HTR is '00' (token_data 0). Custom tokens use the low 7 bits of token_data as +// an index into tx.tokens (1-based). The high bit marks authorities. +function resolveTokenUid(output, tx) { + const td = output.token_data || 0; + const tokenIndex = td & 0x7f; + if (tokenIndex === 0) return '00'; + const entry = (tx.tokens || [])[tokenIndex - 1]; + return entry ? entry.uid : null; +} + +// Find the FIRST output that pays `payTo` at least `minValue` of `asset`. +// Returns { outputIndex, value, token } or null. +function findPayingOutput(tx, { payTo, asset, minValue }) { + const min = BigInt(minValue); + const outputs = tx.outputs || []; + for (let i = 0; i < outputs.length; i++) { + const out = outputs[i]; + const decoded = out.decoded || {}; + if (decoded.address !== payTo) continue; + const token = resolveTokenUid(out, tx); + if (token !== asset) continue; + const value = BigInt(out.value); + if (value < min) continue; + return { outputIndex: i, value: out.value, token }; + } + return null; +} + +function getInputAddresses(tx) { + return new Set((tx.inputs || []).map((i) => i.decoded && i.decoded.address).filter(Boolean)); +} + +function getOutputAddresses(tx) { + return new Set((tx.outputs || []).map((o) => o.decoded && o.decoded.address).filter(Boolean)); +} + +// --- Message-signature verification (Bitcoin-compatible / Hathor) ----------- +// We go through @hathor/wallet-lib's verifyMessage so the address-version-byte +// handling is aligned with how the wallet stack signs. The lib lazily +// initialises network state; we pass the configured network. +let _walletLib = null; +function lazyWalletLib() { + if (_walletLib) return _walletLib; + _walletLib = require('@hathor/wallet-lib'); + // Set the global network so bitcore's address parsing knows which version + // byte to expect. The lib exports a Network class and a default config. + try { + const net = new _walletLib.Network(config.network); + if (_walletLib.config && typeof _walletLib.config.setNetwork === 'function') { + _walletLib.config.setNetwork(net); + } + } catch (_) { /* lib version variance — verifyMessage still works */ } + return _walletLib; +} + +function verifyMessageSignature(message, signatureBase64, address) { + const lib = lazyWalletLib(); + // wallet-lib v2 exposes the crypto helpers under `cryptoUtils.*`; older + // versions used `utils.crypto.*`. Support either. + const verify = + (lib.cryptoUtils && lib.cryptoUtils.verifyMessage) || + (lib.utils && lib.utils.crypto && lib.utils.crypto.verifyMessage) || + (lib.verifyMessage && lib.verifyMessage.bind(lib)); + if (typeof verify !== 'function') { + throw new Error('verifyMessage not available in @hathor/wallet-lib'); + } + try { + return Boolean(verify(message, signatureBase64, address)); + } catch (_) { + return false; + } } module.exports = { - walletRequest, - fullnodeRequest, - getNanoContractState, - waitForTxConfirmation, log, + fullnodeRequest, + getTransaction, + waitForTxInMempool, + resolveTokenUid, + findPayingOutput, + getInputAddresses, + getOutputAddresses, + verifyMessageSignature, }; diff --git a/init-seller-wallet.sh b/init-seller-wallet.sh new file mode 100755 index 0000000..f0876b3 --- /dev/null +++ b/init-seller-wallet.sh @@ -0,0 +1,34 @@ +#!/bin/sh +# Boot-time helper for the seller's wallet-headless. Waits for the headless +# service to come up, then POST /start with the seed so the rest of the stack +# can hit it. The seller wallet is only used by the upto scheme (to issue +# refund txs); the exact scheme never needs it. + +set -e + +HEADLESS_URL="${SELLER_WALLET_URL:-http://wallet-headless:8000}" +WALLET_ID="${SELLER_WALLET_ID:-seller}" + +if [ -z "${SELLER_SEED:-}" ]; then + echo "[init-seller-wallet] SELLER_SEED is empty — skipping (upto refunds will fail)" + exec "$@" +fi + +echo "[init-seller-wallet] Waiting for headless at $HEADLESS_URL ..." +until curl -sf "$HEADLESS_URL/wallet/status" > /dev/null 2>&1; do + sleep 2 +done +echo "[init-seller-wallet] headless is up" + +echo "[init-seller-wallet] Starting wallet '$WALLET_ID' ..." +curl -s -X POST "$HEADLESS_URL/start" \ + -H "Content-Type: application/json" \ + -d "{\"wallet-id\":\"$WALLET_ID\",\"seed\":\"$SELLER_SEED\"}" \ + || echo "[init-seller-wallet] /start returned non-zero (already started?)" + +echo "" +echo "[init-seller-wallet] Waiting a few seconds for sync ..." +sleep 5 +echo "[init-seller-wallet] Ready. Handing off." + +exec "$@" diff --git a/init-wallets.sh b/init-wallets.sh deleted file mode 100755 index ce98a84..0000000 --- a/init-wallets.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/sh -# Wait for wallet-headless to be ready -echo "Waiting for wallet-headless..." -until curl -sf http://wallet-headless:8000/wallet/status > /dev/null 2>&1; do - sleep 2 -done -echo "Wallet-headless is ready" - -# Start facilitator wallet -echo "Starting facilitator wallet..." -curl -s -X POST http://wallet-headless:8000/start \ - -H "Content-Type: application/json" \ - -d "{\"wallet-id\":\"facilitator\",\"seed\":\"$FACILITATOR_SEED\"}" -echo "" - -# Start seller wallet -echo "Starting seller wallet..." -curl -s -X POST http://wallet-headless:8000/start \ - -H "Content-Type: application/json" \ - -d "{\"wallet-id\":\"seller\",\"seed\":\"$SELLER_SEED\"}" -echo "" - -# Wait for wallets to sync -echo "Waiting for wallets to sync..." -sleep 10 -echo "Wallets initialized" - -# Start the actual service (passed as arguments) -exec "$@" diff --git a/package-lock.json b/package-lock.json index 0830a88..cbb86e1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,42 @@ { "name": "x402-poc", - "version": "0.1.0", + "version": "0.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "x402-poc", - "version": "0.1.0", + "version": "0.2.0", + "license": "MIT", + "dependencies": { + "@hathor/wallet-lib": "^2.17.0", + "better-sqlite3": "^11.5.0", + "express": "^4.21.0" + }, + "engines": { + "node": ">=22" + } + }, + "node_modules/@hathor/wallet-lib": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/@hathor/wallet-lib/-/wallet-lib-2.17.0.tgz", + "integrity": "sha512-PhPkv3kCPWX0gXrJTVlA50GfY64kGPmNxqy0XmOuA77tLm2TzvkZTuho/IlPYoaACQZLV2aXGTCJPqTq9eGtMQ==", + "license": "MIT", "dependencies": { - "express": "^4.21.0", - "node-fetch": "^2.7.0" + "axios": "1.7.7", + "bitcore-lib": "8.25.10", + "bitcore-mnemonic": "8.25.10", + "buffer": "6.0.3", + "crypto-js": "4.2.0", + "isomorphic-ws": "5.0.0", + "lodash": "4.17.21", + "queue-microtask": "1.2.3", + "ws": "8.17.1", + "zod": "3.23.8" + }, + "engines": { + "node": ">=22.0.0", + "npm": ">=10.0.0" } }, "node_modules/accepts": { @@ -31,10 +58,157 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "license": "MIT" }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/base-x": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz", + "integrity": "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bech32": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.3.tgz", + "integrity": "sha512-yuVFUvrNcoJi0sv5phmqc6P+Fl1HjRDRNOOkHY2X/3LBy2bIGNSFx4fZ95HMaXHupuS7cZR15AsvtmCIF4UEyg==", + "license": "MIT" + }, + "node_modules/better-sqlite3": { + "version": "11.10.0", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-11.10.0.tgz", + "integrity": "sha512-EwhOpyXiOEL/lKzHz9AW1msWFNzGc/z+LzeB3/jnFJpxu+th2yqvzsSWas1v9jgs9+xiXJcD5A8CJxAG2TaghQ==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "bindings": "^1.5.0", + "prebuild-install": "^7.1.1" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "license": "MIT", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bitcore-lib": { + "version": "8.25.10", + "resolved": "https://registry.npmjs.org/bitcore-lib/-/bitcore-lib-8.25.10.tgz", + "integrity": "sha512-MyHpSg7aFRHe359RA/gdkaQAal3NswYZTLEuu0tGX1RGWXAYN9i/24fsjPqVKj+z0ua+gzAT7aQs0KiKXWCgKA==", + "license": "MIT", + "dependencies": { + "bech32": "=1.1.3", + "bn.js": "=4.11.8", + "bs58": "^4.0.1", + "buffer-compare": "=1.1.1", + "elliptic": "^6.5.3", + "inherits": "=2.0.1", + "lodash": "^4.17.20" + } + }, + "node_modules/bitcore-mnemonic": { + "version": "8.25.10", + "resolved": "https://registry.npmjs.org/bitcore-mnemonic/-/bitcore-mnemonic-8.25.10.tgz", + "integrity": "sha512-FeXxO37BLV5JRvxPmVFB91zRHalavV8H4TdQGt1/hz0AkoPymIV68OkuB+TptpjeYgatcgKPoPvPhglJkTzFQQ==", + "license": "MIT", + "dependencies": { + "bitcore-lib": "^8.25.10", + "unorm": "^1.4.1" + }, + "peerDependencies": { + "bitcore-lib": "^8.20.1" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/bl/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "license": "MIT" + }, "node_modules/body-parser": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", - "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", + "version": "1.20.5", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz", + "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==", "license": "MIT", "dependencies": { "bytes": "~3.1.2", @@ -45,7 +219,7 @@ "http-errors": "~2.0.1", "iconv-lite": "~0.4.24", "on-finished": "~2.4.1", - "qs": "~6.14.0", + "qs": "~6.15.1", "raw-body": "~2.5.3", "type-is": "~1.6.18", "unpipe": "~1.0.0" @@ -55,6 +229,50 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "license": "MIT" + }, + "node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "license": "MIT", + "dependencies": { + "base-x": "^3.0.2" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-compare": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-compare/-/buffer-compare-1.1.1.tgz", + "integrity": "sha512-O6NvNiHZMd3mlIeMDjP6t/gPG75OqGPeiRZXoMQZJ6iy9GofCls4Ijs5YkPZZwoysizLiedhticmdyx/GyHghA==" + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -93,6 +311,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "license": "ISC" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -129,6 +365,12 @@ "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", "license": "MIT" }, + "node_modules/crypto-js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", + "license": "MIT" + }, "node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -138,6 +380,39 @@ "ms": "2.0.0" } }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -157,6 +432,15 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -177,6 +461,33 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "license": "MIT" }, + "node_modules/elliptic": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", + "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==", + "license": "MIT" + }, + "node_modules/elliptic/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, "node_modules/encodeurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", @@ -186,6 +497,15 @@ "node": ">= 0.8" } }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -205,9 +525,9 @@ } }, "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0" @@ -216,6 +536,21 @@ "node": ">= 0.4" } }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -231,15 +566,24 @@ "node": ">= 0.6" } }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "license": "(MIT OR WTFPL)", + "engines": { + "node": ">=6" + } + }, "node_modules/express": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", - "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.2.tgz", + "integrity": "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==", "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "~1.20.3", + "body-parser": "~1.20.5", "content-disposition": "~0.5.4", "content-type": "~1.0.4", "cookie": "~0.7.1", @@ -258,7 +602,7 @@ "parseurl": "~1.3.3", "path-to-regexp": "~0.1.12", "proxy-addr": "~2.0.7", - "qs": "~6.14.0", + "qs": "~6.15.1", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "~0.19.0", @@ -277,6 +621,12 @@ "url": "https://opencollective.com/express" } }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "license": "MIT" + }, "node_modules/finalhandler": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", @@ -295,6 +645,42 @@ "node": ">= 0.8" } }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -313,6 +699,12 @@ "node": ">= 0.6" } }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "license": "MIT" + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -359,6 +751,12 @@ "node": ">= 0.4" } }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "license": "MIT" + }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -383,10 +781,41 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/hash.js/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", + "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -395,6 +824,17 @@ "node": ">= 0.4" } }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "license": "MIT", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, "node_modules/http-errors": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", @@ -415,6 +855,12 @@ "url": "https://opencollective.com/express" } }, + "node_modules/http-errors/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -427,10 +873,36 @@ "node": ">=0.10.0" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "license": "ISC" }, "node_modules/ipaddr.js": { @@ -442,6 +914,21 @@ "node": ">= 0.10" } }, + "node_modules/isomorphic-ws": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", + "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -511,12 +998,57 @@ "node": ">= 0.6" } }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "license": "ISC" + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "license": "MIT" + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "license": "MIT" + }, "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "license": "MIT" + }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -526,24 +1058,16 @@ "node": ">= 0.6" } }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "node_modules/node-abi": { + "version": "3.92.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.92.0.tgz", + "integrity": "sha512-KdHvFWZjEKDf0cakgFjebl371GPsISX2oZHcuyKqM7DtogIsHrqKeLTo8wBHxaXRAQlY2PsPlZmfo+9ZCxEREQ==", "license": "MIT", "dependencies": { - "whatwg-url": "^5.0.0" + "semver": "^7.3.5" }, "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } + "node": ">=10" } }, "node_modules/object-inspect": { @@ -570,6 +1094,15 @@ "node": ">= 0.8" } }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -585,6 +1118,33 @@ "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", "license": "MIT" }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.", + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -598,10 +1158,26 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/qs": { - "version": "6.14.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", - "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", + "version": "6.15.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", + "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" @@ -613,6 +1189,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -637,6 +1233,41 @@ "node": ">= 0.8" } }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readable-stream/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -663,6 +1294,18 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "license": "MIT" }, + "node_modules/semver": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", + "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/send": { "version": "0.19.2", "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", @@ -734,13 +1377,13 @@ } }, "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" + "object-inspect": "^1.13.4" }, "engines": { "node": ">= 0.4" @@ -786,6 +1429,51 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, "node_modules/statuses": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", @@ -795,6 +1483,58 @@ "node": ">= 0.8" } }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -804,11 +1544,17 @@ "node": ">=0.6" } }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT" + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } }, "node_modules/type-is": { "version": "1.6.18", @@ -823,6 +1569,15 @@ "node": ">= 0.6" } }, + "node_modules/unorm": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/unorm/-/unorm-1.6.0.tgz", + "integrity": "sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==", + "license": "MIT or GPL-2.0", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -832,6 +1587,12 @@ "node": ">= 0.8" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -850,20 +1611,40 @@ "node": ">= 0.8" } }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" } } } diff --git a/package.json b/package.json index 1247d33..223ca4f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "x402-poc", - "version": "0.1.0", - "description": "x402 Payment Protocol POC for Hathor Network — Machine-to-machine payments via HTTP 402 + nano contract escrow", + "version": "0.2.0", + "description": "x402 Payment Protocol PoC for Hathor Network — hathor-direct scheme (regular UTXO payments, no nano contracts)", "license": "MIT", "repository": { "type": "git", @@ -10,13 +10,15 @@ "scripts": { "facilitator": "node facilitator.js", "resource-server": "node resource-server.js", + "start": "node resource-server.js", "client": "node client.js" }, "dependencies": { - "express": "^4.21.0", - "node-fetch": "^2.7.0" + "@hathor/wallet-lib": "^2.17.0", + "better-sqlite3": "^11.5.0", + "express": "^4.21.0" }, "engines": { - "node": ">=18" + "node": ">=22" } } diff --git a/refundIssuer.js b/refundIssuer.js new file mode 100644 index 0000000..9891c31 --- /dev/null +++ b/refundIssuer.js @@ -0,0 +1,64 @@ +// hathor-direct-upto refund: after the resource server determines the actual +// usage, it asks the seller's wallet-headless to send `paid - charged` back to +// the payer. Fire-and-forget; if it fails we surface refundError to the caller. +// +// We talk to the same POST /wallet/send-tx endpoint the dApp would have used. +// The seller wallet must be loaded and funded with HTR (or the relevant token) +// ahead of time — see init-seller-wallet.sh + docker-compose.yml. + +'use strict'; + +async function issueRefund({ + sellerWalletUrl, + sellerWalletId, + refundAddress, + amount, + asset, + log, +}) { + if (!sellerWalletUrl) throw new Error('refundIssuer: sellerWalletUrl not configured'); + if (!sellerWalletId) throw new Error('refundIssuer: sellerWalletId not configured'); + if (!refundAddress) throw new Error('refundIssuer: refundAddress missing'); + const value = Number(amount); + if (!Number.isFinite(value) || value <= 0) { + throw new Error(`refundIssuer: invalid amount ${amount}`); + } + + const output = { address: refundAddress, value }; + // HTR is '00' implicitly; for custom tokens we must set token. + if (asset && asset !== '00') output.token = asset; + + const body = { outputs: [output] }; + + if (log) log('REFUND', `POST ${sellerWalletUrl}/wallet/send-tx — ${value} ${asset || '00'} → ${refundAddress}`); + + const resp = await fetch(`${sellerWalletUrl}/wallet/send-tx`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-Wallet-Id': sellerWalletId, + }, + body: JSON.stringify(body), + }); + + let payload; + try { + payload = await resp.json(); + } catch (_) { + throw new Error(`refund tx call returned non-JSON (status ${resp.status})`); + } + + if (!resp.ok || payload.success === false) { + const msg = payload && (payload.error || payload.message) + || `HTTP ${resp.status}`; + throw new Error(`refund tx failed: ${msg}`); + } + + const txId = payload.hash || payload.tx_id || (payload.tx && payload.tx.hash) || null; + if (!txId) throw new Error('refund tx accepted but no txId in response'); + + if (log) log('REFUND', `refund tx broadcast — ${txId}`); + return { txId }; +} + +module.exports = { issueRefund }; diff --git a/requestId.js b/requestId.js new file mode 100644 index 0000000..d92ea64 --- /dev/null +++ b/requestId.js @@ -0,0 +1,81 @@ +// Stateless server-issued challenge token. Encodes the route/amount/payTo/asset +// commitment and an expiry; HMAC-SHA256 binds it to this server's secret so the +// server can verify a returned challenge without keeping any per-challenge state. + +'use strict'; + +const crypto = require('crypto'); + +function b64urlEncode(buf) { + return Buffer.from(buf).toString('base64url'); +} + +function b64urlDecode(str) { + return Buffer.from(str, 'base64url'); +} + +function hmac(secret, body) { + return crypto.createHmac('sha256', secret).update(body).digest(); +} + +// Mint a fresh requestId. `claims` is the canonical 402 challenge: a server +// promise to itself that it offered this exact deal. +function mintRequestId({ route, amount, payTo, asset, network }, secret, ttlSeconds) { + if (!secret) throw new Error('mintRequestId: missing server secret'); + const now = Math.floor(Date.now() / 1000); + const claims = { + route: String(route), + amount: String(amount), + payTo: String(payTo), + asset: String(asset), + network: String(network), + exp: now + Number(ttlSeconds || 60), + nonce: crypto.randomBytes(8).toString('base64url'), + }; + const body = b64urlEncode(JSON.stringify(claims)); + const mac = b64urlEncode(hmac(secret, body)); + return `${body}.${mac}`; +} + +// Verify the MAC, expiry, and that the claims match what the route expects. +// Returns { ok: true, claims } on success or { ok: false, reason } on failure. +function verifyAndDecodeRequestId(token, secret, expected = {}) { + if (!token || typeof token !== 'string') return { ok: false, reason: 'malformed_request_id' }; + const dot = token.indexOf('.'); + if (dot < 0) return { ok: false, reason: 'malformed_request_id' }; + const body = token.slice(0, dot); + const mac = token.slice(dot + 1); + if (!body || !mac) return { ok: false, reason: 'malformed_request_id' }; + + let recomputed; + try { + recomputed = b64urlEncode(hmac(secret, body)); + } catch (_) { + return { ok: false, reason: 'bad_request_id_mac' }; + } + if (recomputed.length !== mac.length || + !crypto.timingSafeEqual(Buffer.from(recomputed), Buffer.from(mac))) { + return { ok: false, reason: 'bad_request_id_mac' }; + } + + let claims; + try { + claims = JSON.parse(b64urlDecode(body).toString('utf-8')); + } catch (_) { + return { ok: false, reason: 'malformed_request_id' }; + } + + if (typeof claims.exp !== 'number' || claims.exp * 1000 < Date.now()) { + return { ok: false, reason: 'request_id_expired' }; + } + + for (const k of ['route', 'amount', 'payTo', 'asset', 'network']) { + if (expected[k] != null && String(expected[k]) !== String(claims[k])) { + return { ok: false, reason: `requestId_${k}_mismatch` }; + } + } + + return { ok: true, claims }; +} + +module.exports = { mintRequestId, verifyAndDecodeRequestId }; diff --git a/resource-server.js b/resource-server.js index d243501..be69780 100644 --- a/resource-server.js +++ b/resource-server.js @@ -1,183 +1,208 @@ -// x402 Resource Server (Seller) -// A simple API server that sells: -// GET /weather -> exact scheme (hathor-escrow / hathor-channel) -// GET /generate -> upto scheme (hathor-escrow-upto) — usage-billed (simulated LLM) -// Supports HTR and custom tokens +// x402 Resource Server — sells two routes: +// GET /weather — hathor-direct (exact) +// GET /generate — hathor-direct-upto (max-authorize, refund remainder) +// +// Self-verifies via verifier.js by default (VERIFY_MODE=self) so a public +// facilitator is optional. When VERIFY_MODE=facilitator it POSTs to the +// configured facilitator URL instead. + +'use strict'; const express = require('express'); -const fetch = require('node-fetch'); const config = require('./config'); const { log } = require('./helpers'); +const { openStore } = require('./dedupStore'); +const { mintRequestId } = require('./requestId'); +const { verifyDirectPayment } = require('./verifier'); +const { watchForVoid } = require('./voidWatcher'); +const { issueRefund } = require('./refundIssuer'); + +if (!config.sellerAddress) { + log('RESOURCE-SERVER', 'WARNING: SELLER_ADDRESS not set — 402 responses will be invalid'); +} +if (!config.serverSecret) { + log('RESOURCE-SERVER', 'WARNING: SERVER_SECRET not set — requestIds will be unverifiable'); +} +const store = openStore(config.dedupDbPath); const app = express(); -app.use(express.json()); +app.use(express.json({ limit: '32kb' })); -// CORS — allow browser dApps to call this server +// CORS — open for the dApp + curl tests. app.use((req, res, next) => { res.header('Access-Control-Allow-Origin', '*'); - res.header('Access-Control-Allow-Headers', 'Content-Type, PAYMENT-SIGNATURE, X-Payment'); - res.header('Access-Control-Expose-Headers', 'PAYMENT-RESPONSE, X-Payment-Response'); + res.header('Access-Control-Allow-Headers', 'Content-Type, PAYMENT-SIGNATURE'); + res.header('Access-Control-Expose-Headers', 'PAYMENT-RESPONSE'); if (req.method === 'OPTIONS') return res.sendStatus(204); next(); }); -// Build the list of accepted payment options for a route. -// `routeConfig` describes the pricing mode for that route: -// { mode: 'exact', price } -> one-shot escrow or channel -// { mode: 'upto', maxPrice } -> upto-scheme escrow (server settles actual usage) -function buildAcceptsList(path, routeConfig) { - const baseExtra = { - facilitatorUrl: config.facilitatorPublicUrl, - facilitatorAddress: config.facilitatorAddress, - deadlineSeconds: config.escrowDeadlineSeconds, - }; +// --------------------------------------------------------------------------- +// 402 building +// --------------------------------------------------------------------------- - const accepts = []; +function networkId() { + return `hathor:${config.network}`; +} - if (routeConfig.mode === 'upto') { - // Usage-based: client authorizes up to maxPrice, server settles actual usage. - accepts.push({ - scheme: 'hathor-escrow-upto', - network: `hathor:${config.network}`, - resource: `${config.resourceServerPublicUrl}${path}`, - mimeType: 'application/json', +function buildAccept(req, routeConfig) { + const resourceUrl = `${config.resourceServerPublicUrl}${req.path}`; + const amount = String(routeConfig.mode === 'upto' ? routeConfig.maxPrice : routeConfig.price); + const scheme = routeConfig.mode === 'upto' ? 'hathor-direct-upto' : 'hathor-direct'; + + // Mint a fresh, server-issued challenge token. The HMAC commitments include + // the route, amount, and payTo so a payment claim later can't be redirected. + const requestId = mintRequestId( + { + route: resourceUrl, + amount, payTo: config.sellerAddress, - maxTimeoutSeconds: config.escrowDeadlineSeconds, asset: config.htrTokenUid, - price: String(routeConfig.maxPrice), - description: `Pay up to ${(routeConfig.maxPrice / 100).toFixed(2)} HTR — billed by actual usage`, - extra: { ...baseExtra, blueprintId: config.blueprintId, pricing: 'upto' }, - }); - return accepts; - } + network: networkId(), + }, + config.serverSecret || 'dev-fallback-secret', + config.requestIdTtlSeconds + ); + + const description = routeConfig.mode === 'upto' + ? `Pay up to ${(routeConfig.maxPrice / 100).toFixed(2)} HTR — billed by actual usage, remainder refunded` + : `Pay ${(routeConfig.price / 100).toFixed(2)} HTR`; + + return { + scheme, + network: networkId(), + amount, + asset: config.htrTokenUid, + payTo: config.sellerAddress, + resource: resourceUrl, + maxTimeoutSeconds: config.requestIdTtlSeconds, + description, + extra: { + requestId, + facilitatorUrl: config.verifyMode === 'facilitator' ? config.facilitatorUrl : undefined, + }, + }; +} - // Default: exact pricing (escrow + optional channel) - const price = routeConfig.price; +function build402Body(req, routeConfig) { + return { + x402Version: 2, + accepts: [buildAccept(req, routeConfig)], + }; +} - accepts.push({ - scheme: 'hathor-escrow', - network: `hathor:${config.network}`, - resource: `${config.resourceServerPublicUrl}${path}`, - mimeType: 'application/json', - payTo: config.sellerAddress, - maxTimeoutSeconds: config.escrowDeadlineSeconds, - asset: config.htrTokenUid, - price: String(price), - description: `Pay ${(price / 100).toFixed(2)} HTR (single escrow)`, - extra: { ...baseExtra, blueprintId: config.blueprintId, pricing: 'exact' }, - }); +// --------------------------------------------------------------------------- +// Verify — either local (verifier.js) or via the standalone facilitator +// --------------------------------------------------------------------------- - if (config.channelBlueprintId) { - accepts.push({ - scheme: 'hathor-channel', - network: `hathor:${config.network}`, - resource: `${config.resourceServerPublicUrl}${path}`, - mimeType: 'application/json', - payTo: config.sellerAddress, - maxTimeoutSeconds: config.escrowDeadlineSeconds, - asset: config.htrTokenUid, - price: String(price), - description: `Pay ${(price / 100).toFixed(2)} HTR via channel (saves escrow creation)`, - extra: { ...baseExtra, channelBlueprintId: config.channelBlueprintId, pricing: 'exact' }, +async function runVerify(paymentPayload, requirement) { + if (config.verifyMode === 'facilitator') { + const resp = await fetch(`${config.facilitatorUrl}/x402/verify`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ paymentPayload, paymentRequirements: requirement }), }); + return resp.json(); } - - return accepts; + return verifyDirectPayment({ + payload: paymentPayload, + requirements: requirement, + fullnodeUrl: config.fullnodeUrl, + dedupStore: store, + serverSecret: config.serverSecret, + zeroConfMaxAmount: config.zeroConfMaxAmount, + }); } -// Handlers call res.setSettlementOverrides({ amount }) during request processing -// to specify the actual amount to charge in the "upto" scheme. Ignored by "exact". -function setSettlementOverrides(res, overrides) { - res.locals.x402SettlementOverrides = { - ...(res.locals.x402SettlementOverrides || {}), - ...overrides, - }; +// Handlers call `setUptoChargedAmount(res, n)` from inside the route to tell +// the middleware what actually to charge (in atomic units). Ignored by the +// exact scheme. +function setUptoChargedAmount(res, amount) { + res.locals.x402UptoCharged = amount; } -// Factory: build a middleware that verifies payment up-front and defers -// settlement until after the route handler has finished (so handlers can -// call setSettlementOverrides() for the "upto" scheme). +// --------------------------------------------------------------------------- +// Middleware +// --------------------------------------------------------------------------- + function x402Middleware(routeConfig) { - const paymentRequirements = buildAcceptsList('', routeConfig).map(opt => ({ - scheme: opt.scheme, - network: opt.network, - maxAmountRequired: opt.price, - payTo: opt.payTo, - asset: opt.asset, - })); - - return async function (req, res, next) { - // x402 V2: PAYMENT-SIGNATURE (Base64-encoded JSON), fallback to X-Payment (raw JSON) for backward compat + return async function middleware(req, res, next) { const signatureHeader = req.headers['payment-signature']; - const legacyHeader = req.headers['x-payment']; - if (!signatureHeader && !legacyHeader) { - log('RESOURCE-SERVER', `402 — No payment for ${req.path}`); - return res.status(402).json({ - x402Version: 2, - accepts: buildAcceptsList(req.path, routeConfig), - }); + if (!signatureHeader) { + log('RESOURCE-SERVER', `402 — no PAYMENT-SIGNATURE for ${req.path}`); + return res.status(402).json(build402Body(req, routeConfig)); } let payment; try { - payment = signatureHeader - ? JSON.parse(Buffer.from(signatureHeader, 'base64').toString('utf-8')) - : JSON.parse(legacyHeader); - } catch (err) { - return res.status(400).json({ error: 'Invalid PAYMENT-SIGNATURE header' }); + payment = JSON.parse(Buffer.from(signatureHeader, 'base64').toString('utf-8')); + } catch (_) { + return res.status(400).json({ error: 'invalid_payment_signature_header' }); } - const scheme = payment.scheme; - const isChannel = scheme === 'hathor-channel'; - const isUpto = scheme === 'hathor-escrow-upto'; - const id = isChannel ? payment.payload.channelId : payment.payload.ncId; - - log('RESOURCE-SERVER', `Verifying ${scheme} payment id=${id}`); - - // Step 1: Verify with facilitator (up-front, before running the handler) - const verifyResp = await fetch(`${config.facilitatorUrl}/x402/verify`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ paymentPayload: payment, paymentRequirements }), - }); - const verification = await verifyResp.json(); + // Re-issue a requestId-bound requirement so the verifier checks against + // the canonical route values, not anything the client could spoof. + const requirement = (() => { + const accept = buildAccept(req, routeConfig); + // Verifier uses what the payload claims and re-checks the HMAC; we just + // pass the canonical route/payTo/amount/asset/network back in. + return { + scheme: accept.scheme, + network: accept.network, + amount: accept.amount, + asset: accept.asset, + payTo: accept.payTo, + resource: accept.resource, + }; + })(); + + log('RESOURCE-SERVER', `verifying ${payment.scheme} for ${req.path}`); + let verification; + try { + verification = await runVerify(payment, requirement); + } catch (err) { + log('RESOURCE-SERVER', `verify error: ${err.message}`); + return res.status(502).json({ error: 'verify_failed', reason: err.message }); + } if (!verification.valid) { - log('RESOURCE-SERVER', `Payment INVALID: ${verification.invalidReason}`); - return res.status(402).json({ error: 'Payment invalid', reason: verification.invalidReason }); + log('RESOURCE-SERVER', `payment INVALID: ${verification.invalidReason}`); + return res.status(402).json({ + error: 'payment_invalid', + reason: verification.invalidReason, + ...build402Body(req, routeConfig), + }); } - log('RESOURCE-SERVER', `Payment VALID`); - // Stash context for post-handler settlement - res.locals.x402 = { payment, scheme, isChannel, isUpto, id, routeConfig }; + log('RESOURCE-SERVER', `payment VALID — tx=${verification.txId} idempotent=${!!verification.idempotent}`); + res.locals.x402 = { payment, verification, routeConfig, requirement }; - // Hook res.json so we can settle AFTER the handler finishes building its payload. - // This lets "upto" handlers compute actual usage and call setSettlementOverrides(). + // Hook res.json to settle (refund) AFTER the handler has produced a body + // so /generate can call setUptoChargedAmount() to specify actual usage. const originalJson = res.json.bind(res); - res.json = async function (body) { - // Only settle on 2xx responses — skip if the handler returned an error. - if (res.statusCode >= 400) { - return originalJson(body); - } + res.json = async function patched(body) { try { - const { chargedAmount, settlement } = await settlePayment(res); - const paymentResponse = { - x402Version: 2, - success: true, - scheme, - network: `hathor:${config.network}`, - ...(isChannel ? { channelId: id } : { ncId: id }), - settleTxId: settlement.txId, - ...(isUpto ? { chargedAmount, refundAmount: settlement.refundAmount, refundTxId: settlement.refundTxId } : {}), - }; - res.set('PAYMENT-RESPONSE', Buffer.from(JSON.stringify(paymentResponse)).toString('base64')); + const { paymentResponse } = await finalizeUpto(res); + if (paymentResponse) { + res.set('PAYMENT-RESPONSE', Buffer.from(JSON.stringify(paymentResponse)).toString('base64')); + } + // Start the void watcher only after we've committed to the response + // (so a verification failure doesn't accidentally arm one). + if (!verification.idempotent) { + watchForVoid({ + txId: verification.txId, + outputIndex: verification.outputIndex, + payerAddress: verification.payerAddress, + store, + log, + }); + } return originalJson({ data: body, payment: paymentResponse }); } catch (err) { - log('RESOURCE-SERVER', `Settlement FAILED: ${err.message}`); - // Use originalJson directly to avoid recursion through the wrapped res.json + log('RESOURCE-SERVER', `settlement failed: ${err.message}`); res.status(500); - return originalJson({ error: 'Settlement failed', reason: err.message }); + return originalJson({ error: 'settlement_failed', reason: err.message }); } }; @@ -185,92 +210,148 @@ function x402Middleware(routeConfig) { }; } -// Internal: call the facilitator to settle. Picks the right shape based on scheme. -async function settlePayment(res) { - const { payment, scheme, isChannel, isUpto, id, routeConfig } = res.locals.x402; - const overrides = res.locals.x402SettlementOverrides || {}; - - const settleBody = { paymentPayload: payment }; - let chargedAmount; - - if (isChannel) { - settleBody.amount = routeConfig.price; - settleBody.sellerAddress = config.sellerAddress; - chargedAmount = routeConfig.price; - } else if (isUpto) { - // Handler MUST call setSettlementOverrides({ amount }) — otherwise charge the full max. - chargedAmount = overrides.amount != null ? parseInt(overrides.amount) : routeConfig.maxPrice; - if (chargedAmount > routeConfig.maxPrice) chargedAmount = routeConfig.maxPrice; - if (chargedAmount < 1) chargedAmount = 1; - settleBody.chargedAmount = chargedAmount; - } else { - chargedAmount = routeConfig.price; +async function finalizeUpto(res) { + const ctx = res.locals.x402; + const { payment, verification, routeConfig } = ctx; + const scheme = payment.scheme; + const paidAmount = Number(verification.paidAmount); + + // Exact scheme — no refund, simple PAYMENT-RESPONSE. + if (scheme === 'hathor-direct') { + return { + paymentResponse: { + x402Version: 2, + success: true, + scheme, + network: `hathor:${config.network}`, + transaction: verification.txId, + amount: String(paidAmount), + payer: verification.payerAddress, + }, + }; } - log('RESOURCE-SERVER', `Settling ${scheme} id=${id}${isUpto ? ` chargedAmount=${chargedAmount}` : ''}`); - const settleResp = await fetch(`${config.facilitatorUrl}/x402/settle`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(settleBody), - }); - const settlement = await settleResp.json(); + // Upto scheme — clamp charged amount and issue a refund tx if there's + // remainder. Handler should have called setUptoChargedAmount(res, n). + let charged = Number(res.locals.x402UptoCharged); + if (!Number.isFinite(charged) || charged <= 0) charged = paidAmount; // default to full + if (charged > paidAmount) charged = paidAmount; + const refund = paidAmount - charged; + + let refundTxId = null; + let refundError = null; - if (!settlement.success) { - throw new Error(settlement.error || 'settle failed'); + if (refund > 0) { + try { + const r = await issueRefund({ + sellerWalletUrl: config.sellerWalletUrl, + sellerWalletId: config.sellerWalletId, + refundAddress: verification.payerAddress, + amount: refund, + asset: verification.asset, + log, + }); + refundTxId = r.txId; + } catch (err) { + refundError = err.message; + log('RESOURCE-SERVER', `refund FAILED: ${err.message}`); + } } - log('RESOURCE-SERVER', `Settlement confirmed — txId=${settlement.txId}`); - return { chargedAmount, settlement }; -} -// ----- Routes ----- - -// EXACT scheme: classic fixed-price endpoint -app.get('/weather', x402Middleware({ mode: 'exact', price: config.htrPaymentAmount }), async (req, res) => { - const weatherData = { - location: 'Sao Paulo, Brazil', - temperature: 28, - humidity: 65, - condition: 'Partly cloudy', - wind: '12 km/h NE', - forecast: 'Warm with chance of afternoon showers', - timestamp: new Date().toISOString(), + // Best-effort persistence of the upto settlement on the dedup row. + try { + store.attachUptoSettlement( + verification.txId, + verification.outputIndex, + charged, + refundTxId + ); + } catch (_) { /* don't block the response on accounting */ } + + return { + paymentResponse: { + x402Version: 2, + success: true, + scheme, + network: `hathor:${config.network}`, + transaction: verification.txId, + amount: String(paidAmount), + chargedAmount: String(charged), + refundAmount: String(refund), + refundTxId, + refundError, + payer: verification.payerAddress, + }, }; - res.json(weatherData); -}); - -// UPTO scheme: usage-based endpoint (simulated LLM generation) -// Client authorizes up to `maxPrice`; server charges based on tokens actually generated. -const GENERATE_MAX_PRICE = parseInt(process.env.GENERATE_MAX_PRICE || '500'); // 5.00 HTR -const GENERATE_PRICE_PER_TOKEN = 1; // 0.01 HTR per token generated - -app.get('/generate', x402Middleware({ mode: 'upto', maxPrice: GENERATE_MAX_PRICE }), async (req, res) => { - // Simulate variable LLM token usage between 50 and GENERATE_MAX_PRICE/PRICE_PER_TOKEN tokens - const maxTokens = Math.floor(GENERATE_MAX_PRICE / GENERATE_PRICE_PER_TOKEN); - const tokensUsed = Math.floor(50 + Math.random() * (maxTokens - 50)); - const actualCost = tokensUsed * GENERATE_PRICE_PER_TOKEN; +} - // Tell the middleware how much to actually charge - setSettlementOverrides(res, { amount: actualCost }); +// --------------------------------------------------------------------------- +// Routes +// --------------------------------------------------------------------------- + +// Exact: GET /weather +app.get( + '/weather', + x402Middleware({ mode: 'exact', price: config.htrPaymentAmount }), + async (_req, res) => { + res.json({ + location: 'Sao Paulo, Brazil', + temperature: 28, + humidity: 65, + condition: 'Partly cloudy', + wind: '12 km/h NE', + forecast: 'Warm with chance of afternoon showers', + timestamp: new Date().toISOString(), + }); + } +); + +// Upto: GET /generate — simulated LLM with variable usage +const GENERATE_PRICE_PER_TOKEN = 1; // 0.01 HTR per token + +app.get( + '/generate', + x402Middleware({ mode: 'upto', maxPrice: config.generateMaxPrice }), + async (req, res) => { + const maxTokens = Math.floor(config.generateMaxPrice / GENERATE_PRICE_PER_TOKEN); + const tokensUsed = Math.floor(50 + Math.random() * Math.max(1, maxTokens - 50)); + const actualCost = Math.max(1, tokensUsed * GENERATE_PRICE_PER_TOKEN); + + // Tell the middleware what to actually charge. + setUptoChargedAmount(res, actualCost); + + const prompt = req.query.prompt || 'default prompt'; + res.json({ + prompt, + completion: `Generated response for: "${prompt}". This mock simulates variable-length LLM output billed per token.`, + usage: { + tokensUsed, + pricePerToken: GENERATE_PRICE_PER_TOKEN, + authorizedMaxAtomic: config.generateMaxPrice, + actualChargedAtomic: actualCost, + }, + timestamp: new Date().toISOString(), + }); + } +); - const prompt = req.query.prompt || 'default prompt'; +app.get('/health', (_req, res) => { res.json({ - prompt, - completion: `Generated response for: "${prompt}". This mock response simulates variable-length LLM output billed per token.`, - usage: { - tokensUsed, - pricePerToken: GENERATE_PRICE_PER_TOKEN, - authorizedMaxAtomic: GENERATE_MAX_PRICE, - actualChargedAtomic: actualCost, - }, - timestamp: new Date().toISOString(), + status: 'healthy', + seller: config.sellerAddress, + verifyMode: config.verifyMode, + network: config.network, + dedup: store.stats(), + uptime: process.uptime(), }); }); app.listen(config.resourceServerPort, () => { - log('RESOURCE-SERVER', `Paid API running on port ${config.resourceServerPort}`); - log('RESOURCE-SERVER', `Seller address: ${config.sellerAddress}`); + log('RESOURCE-SERVER', `Running on :${config.resourceServerPort}`); + log('RESOURCE-SERVER', `Seller address: ${config.sellerAddress || '(unset)'}`); + log('RESOURCE-SERVER', `Verify mode: ${config.verifyMode}${config.verifyMode === 'facilitator' ? ` (${config.facilitatorUrl})` : ''}`); + log('RESOURCE-SERVER', `Dedup store: ${config.dedupDbPath}`); log('RESOURCE-SERVER', `Routes:`); - log('RESOURCE-SERVER', ` GET /weather — exact: ${(config.htrPaymentAmount / 100).toFixed(2)} HTR`); - log('RESOURCE-SERVER', ` GET /generate — upto: up to ${(GENERATE_MAX_PRICE / 100).toFixed(2)} HTR (usage-billed)`); - log('RESOURCE-SERVER', `Schemes: hathor-escrow${config.channelBlueprintId ? ' + hathor-channel' : ''} + hathor-escrow-upto`); + log('RESOURCE-SERVER', ` GET /weather — exact: ${(config.htrPaymentAmount / 100).toFixed(2)} HTR`); + log('RESOURCE-SERVER', ` GET /generate — upto: up to ${(config.generateMaxPrice / 100).toFixed(2)} HTR (usage-billed)`); }); diff --git a/verifier.js b/verifier.js new file mode 100644 index 0000000..7d47514 --- /dev/null +++ b/verifier.js @@ -0,0 +1,131 @@ +// The single source of truth for "is this hathor-direct payment claim valid?" +// Imported by resource-server.js (self-verify) and wrapped over HTTP by +// facilitator.js. No wallet, no nano contract — just fullnode reads plus a +// SQLite dedup/blocklist file. + +'use strict'; + +const { + getTransaction, + findPayingOutput, + getInputAddresses, + verifyMessageSignature, +} = require('./helpers'); +const { verifyAndDecodeRequestId } = require('./requestId'); + +function fail(reason) { + return { valid: false, invalidReason: reason }; +} + +// `requirements` is one PaymentRequirements (object) describing the route the +// client is trying to satisfy: { scheme, network, amount, asset, payTo, resource }. +// `payload` is the decoded PAYMENT-SIGNATURE payload from the client. +async function verifyDirectPayment({ + payload, + requirements, + fullnodeUrl, + dedupStore, + serverSecret, + zeroConfMaxAmount = Number.MAX_SAFE_INTEGER, +}) { + if (!payload || typeof payload !== 'object') return fail('missing_payload'); + const { txId, payerAddress, signature, requestId } = payload.payload || {}; + if (!txId || !payerAddress || !signature || !requestId) { + return fail('missing_payload_fields'); + } + + // 1) requestId — HMAC + expiry + commitment match against the route. + const decoded = verifyAndDecodeRequestId(requestId, serverSecret, { + route: requirements.resource, + amount: requirements.amount, + payTo: requirements.payTo, + asset: requirements.asset, + network: requirements.network, + }); + if (!decoded.ok) return fail(decoded.reason); + + // 2) Fetch the tx from the fullnode. (verifier.js doesn't need a wallet — + // this is what makes the facilitator stateless and seedless.) + let resp; + try { + resp = await getTransaction(txId); + } catch (err) { + return fail(`fullnode_error: ${err.message}`); + } + if (!resp || !resp.success || !resp.tx) return fail('tx_not_found'); + const { tx, meta } = resp; + + // 3) An output of the right token must pay `payTo` at least `amount`. + const paying = findPayingOutput(tx, { + payTo: requirements.payTo, + asset: requirements.asset, + minValue: requirements.amount, + }); + if (!paying) return fail('no_paying_output'); + + // 4) The address that signed `requestId` must appear as a TX INPUT — i.e., + // it actually contributed UTXOs to the payment. Accepting output addresses + // would let any recipient of the tx (or any third-party output owner) + // claim the resource. Inputs are the only set that proves payment ownership. + const inAddrs = getInputAddresses(tx); + if (!inAddrs.has(payerAddress)) { + return fail('payer_not_in_tx_inputs'); + } + + // 5) The signature must verify against the payer's address. + if (!verifyMessageSignature(requestId, signature, payerAddress)) { + return fail('bad_signature'); + } + + // 6) Blocklist: payers caught double-spending earlier are refused. + if (dedupStore && dedupStore.isBlocked(payerAddress)) { + return fail('blocklisted'); + } + + // 7) Zero-conf safety: refuse if the tx is currently voided or has a + // visible conflict. (Withheld double-spends are why we ALSO watch the tx + // post-serve; see voidWatcher.js.) + if (meta) { + if (Array.isArray(meta.voided_by) && meta.voided_by.length > 0) { + return fail('voided'); + } + if (Array.isArray(meta.conflict_with) && meta.conflict_with.length > 0) { + return fail('conflicted'); + } + } + + // 8) Tiered confirmation: amounts above the threshold must have first_block. + if (Number(requirements.amount) > zeroConfMaxAmount) { + if (!meta || !meta.first_block) return fail('awaiting_block'); + } + + // 9) Atomic dedup. This both detects replays and is the on-disk record of + // the redemption. + const dedup = dedupStore.markRedeemedIfFree( + { txId, outputIndex: paying.outputIndex }, + { + requestId, + payerAddress, + amount: requirements.amount, + asset: requirements.asset, + } + ); + + if (dedup.result === 'conflict') return fail('replay'); + const idempotent = dedup.result === 'idempotent'; + + return { + valid: true, + txId, + outputIndex: paying.outputIndex, + payerAddress, + amount: String(paying.value), + paidAmount: String(paying.value), + asset: paying.token, + requestId, + idempotent, + existingRecord: idempotent ? dedup.existing : null, + }; +} + +module.exports = { verifyDirectPayment }; diff --git a/voidWatcher.js b/voidWatcher.js new file mode 100644 index 0000000..c6515cd --- /dev/null +++ b/voidWatcher.js @@ -0,0 +1,60 @@ +// Background polling watcher: after we serve a resource on a zero-conf payment, +// we keep an eye on the tx in case the payer double-spends. On a detected void +// we mark the dedup row voided and add the payer to the blocklist. +// +// Best-effort, in-process — lost on restart. POC tradeoff. Real production +// would use the fullnode event WebSocket (VERTEX_METADATA_CHANGED). + +'use strict'; + +const { getTransaction } = require('./helpers'); + +// Cumulative backoff. ~17 min total then we give up. +const SCHEDULE_MS = [5_000, 10_000, 20_000, 40_000, 80_000, 160_000, 320_000, 600_000]; + +function watchForVoid({ txId, outputIndex, payerAddress, store, log }) { + let cancelled = false; + let i = 0; + + const tick = async () => { + if (cancelled) return; + try { + const resp = await getTransaction(txId); + if (resp && resp.success && resp.meta) { + const meta = resp.meta; + const voided = Array.isArray(meta.voided_by) && meta.voided_by.length > 0; + const conflict = Array.isArray(meta.conflict_with) && meta.conflict_with.length > 0; + + if (voided) { + store.markVoided(txId, outputIndex); + if (payerAddress) store.addBlock(payerAddress, 'double_spend', txId); + if (log) log('VOID-WATCH', `${txId}:${outputIndex} voided; blocked ${payerAddress}`); + return; // stop + } + + if (conflict) { + // Conflict but our tx hasn't been voided yet — keep watching, but + // log it so we have a breadcrumb. + if (log) log('VOID-WATCH', `${txId}:${outputIndex} has unresolved conflict, continuing to watch`); + } + + if (meta.first_block) { + // Confirmed: the tx is reorg-protected. Stop watching. + if (log) log('VOID-WATCH', `${txId}:${outputIndex} confirmed by block ${meta.first_block}`); + return; + } + } + } catch (err) { + if (log) log('VOID-WATCH', `poll error for ${txId}: ${err.message}`); + } + + if (++i >= SCHEDULE_MS.length || cancelled) return; + setTimeout(tick, SCHEDULE_MS[i] - (SCHEDULE_MS[i - 1] || 0)); + }; + + setTimeout(tick, SCHEDULE_MS[0]); + + return { cancel: () => { cancelled = true; } }; +} + +module.exports = { watchForVoid }; From 43e1956764e42ff890a7d34bb531ebee9b0dbf5a Mon Sep 17 00:00:00 2001 From: Pedro Ferreira Date: Thu, 28 May 2026 16:36:43 -0300 Subject: [PATCH 33/37] ci(dokploy): use named volume x402_data for SQLite persistence The relative bind mount './data:/app/data' depended on Dokploy not wiping the cloned repo dir, which isn't guaranteed across redeploys/branch swaps. A named volume is Docker-managed and survives everything except an explicit 'docker volume rm'. --- docker-compose.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index b56bcb6..0641e7d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -47,7 +47,7 @@ services: ports: - "${RESOURCE_SERVER_HOST_PORT:-3000}:3000" volumes: - - ./data:/app/data + - x402_data:/app/data healthcheck: test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/health',r=>{process.exit(r.statusCode<500?0:1)}).on('error',()=>process.exit(1))"] interval: 10s @@ -75,7 +75,7 @@ services: ports: - "${FACILITATOR_HOST_PORT:-8402}:8402" volumes: - - ./data:/app/data + - x402_data:/app/data healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8402/health"] interval: 10s @@ -104,3 +104,10 @@ services: depends_on: resource-server: condition: service_healthy + +# Docker-managed named volume for the verifier's dedup ledger + blocklist +# (SQLite at /app/data/payments.sqlite). Both `resource-server` and the +# optional `facilitator` share it. Persists across container recreations +# and across Dokploy redeploys. +volumes: + x402_data: From 5b5d04c1fffa1e4d34da33ba8a0bb25a8cca2ed6 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira Date: Thu, 28 May 2026 17:03:25 -0300 Subject: [PATCH 34/37] fix(verifier): align mint/verify SERVER_SECRET fallback Mint was using config.serverSecret || 'dev-fallback-secret' while verify used raw config.serverSecret. When SERVER_SECRET env was missing, mint hashed with the fallback and verify hashed with empty string, producing silent bad_request_id_mac on every retry. Make config.serverSecret resolve to the placeholder by default so both paths use the same key. --- config.js | 8 +++++--- resource-server.js | 4 +++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/config.js b/config.js index 8c414bc..4197691 100644 --- a/config.js +++ b/config.js @@ -33,9 +33,11 @@ module.exports = { sellerWalletUrl: env.SELLER_WALLET_URL || 'http://wallet-headless:8000', sellerWalletId: env.SELLER_WALLET_ID || 'seller', - // Server secret used to HMAC requestIds. Falls back to an ephemeral random - // value with a warning at startup if unset — fine for local dev, not for prod. - serverSecret: env.SERVER_SECRET || '', + // Server secret used to HMAC requestIds. If unset we fall back to a fixed + // string so mint+verify use the same key (otherwise empty=='' on verify + // wouldn't match the fallback used at mint, causing silent bad_request_id_mac + // failures). Set SERVER_SECRET in prod — startup logs a clear warning otherwise. + serverSecret: env.SERVER_SECRET || 'x402-poc-dev-secret-do-not-use-in-prod', requestIdTtlSeconds: int(env.REQUEST_ID_TTL_SECONDS, 120), // Dedup + blocklist store (better-sqlite3 file). diff --git a/resource-server.js b/resource-server.js index be69780..757be5f 100644 --- a/resource-server.js +++ b/resource-server.js @@ -52,6 +52,8 @@ function buildAccept(req, routeConfig) { // Mint a fresh, server-issued challenge token. The HMAC commitments include // the route, amount, and payTo so a payment claim later can't be redirected. + // config.serverSecret always has a value (env or fixed dev fallback) so + // mint+verify use the same key. const requestId = mintRequestId( { route: resourceUrl, @@ -60,7 +62,7 @@ function buildAccept(req, routeConfig) { asset: config.htrTokenUid, network: networkId(), }, - config.serverSecret || 'dev-fallback-secret', + config.serverSecret, config.requestIdTtlSeconds ); From 3348b2a69d97cb199c34eb6396d79b81fdd691c9 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira Date: Thu, 28 May 2026 17:08:19 -0300 Subject: [PATCH 35/37] fix(dapp): pin changeAddress to address-0 + stop auto-refresh balance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Document why payerAddress is by definition address-0 (WalletConnect's session approval shares getAddressAtIndex(0)) and add a null guard. - Always set changeAddress to address-0 so it stays funded across consecutive payments instead of draining into first_empty addresses. - Drop refreshBalance() call after a successful payment — it triggers an htr_getBalance popup on some wallets, which is noisy right after the user already signed twice. BalanceCard's manual button still works. --- dapp/components/X402Fetch.tsx | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/dapp/components/X402Fetch.tsx b/dapp/components/X402Fetch.tsx index 74b1a04..9257f27 100644 --- a/dapp/components/X402Fetch.tsx +++ b/dapp/components/X402Fetch.tsx @@ -77,7 +77,7 @@ function describeScheme(scheme: string) { // --- component ------------------------------------------------------------- export function X402Fetch() { - const { sendTransaction, signWithAddress, getUtxos, address, refreshBalance } = useWallet(); + const { sendTransaction, signWithAddress, getUtxos, address } = useWallet(); const { network, isConnected } = useHathor(); const [url, setUrl] = useState(config.defaultDemoUrl); @@ -136,7 +136,13 @@ export function X402Fetch() { // input address in the resulting tx is address-0, and signing with // addressIndex: 0 produces a signature the verifier accepts. const PAYER_INDEX = 0; - const payerAddress = address!; + // Address-0 is what WalletConnect shares at session approval + // (hathor-wallet/src/sagas/reown.js:184 derives `getAddressAtIndex(0)`), + // so the connected address is address-0 by definition. We use it both + // as the FROM (filter UTXOs to spend) and as the change recipient so + // address-0 keeps being funded for subsequent payments. + if (!address) throw new Error('Wallet not connected'); + const payerAddress = address; const amount = parseInt(String(opt.amount).replace(/[^0-9]/g, ''), 10); // Step 1: list the connected address's UTXOs (asset-filtered). @@ -180,7 +186,10 @@ export function X402Fetch() { network, outputs: [sendOutput], inputs: chosen.map((u) => ({ txId: u.tx_id, index: u.index })), - changeAddress: payerAddress, // consolidate change back to address-0 + // ALWAYS route change to address-0 so it stays funded for future + // payments. Otherwise the wallet defaults change to its + // `first_empty` address and address-0 slowly drains. + changeAddress: payerAddress, push_tx: true, }); const sentTxId = HathorRPCService.extractTxId(sendResp); @@ -266,7 +275,10 @@ export function X402Fetch() { setStep('done'); toast.success('Resource received!'); - refreshBalance('00', network); + // Intentionally NOT calling refreshBalance here — htr_getBalance + // prompts the wallet on some adapters, which is noisy right after the + // user just signed twice. The user can hit "Load Balance" on the + // BalanceCard explicitly if they want a fresh number. } catch (err: any) { setError(err.message); setStep('error'); From 48e0a2167677352bf3a503661794f9ce654372de Mon Sep 17 00:00:00 2001 From: Pedro Ferreira Date: Thu, 28 May 2026 23:21:16 -0300 Subject: [PATCH 36/37] feat(verifier): switch PAYMENT-SIGNATURE to multi-signature payload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The payload shape changes from {txId, payerAddress, signature, requestId} to {txId, signatures: [{address, signature}, ...], requestId}. The verifier now requires every unique input address of the broadcast tx to have a verified signature, proving the payer controls every funding source — not just the change/output address. This unblocks the x402-pay agent skill, whose headless wallet can pick UTXOs from multiple addresses; the dApp continues to send a single signature (address-0) wrapped in a one-element array. Breaking change: no back-compat with the legacy single-signature shape. Nothing in production today depends on it, and api.x402.hathor.dev + x402.hathor.dev redeploy atomically from this branch. - verifier.js: extract signatures[], require one per unique input address, identify the canonical payer as signatures[0].address (used for the upto-refund target and blocklist) - dapp/components/X402Fetch.tsx: wrap the WalletConnect signature into a one-element signatures array - client.js: same one-element wrap for the CLI path Co-Authored-By: Claude Opus 4.7 (1M context) --- client.js | 6 ++- dapp/components/X402Fetch.tsx | 10 +++-- verifier.js | 74 +++++++++++++++++++++++++++-------- 3 files changed, 69 insertions(+), 21 deletions(-) diff --git a/client.js b/client.js index 2d73316..8ca9a30 100644 --- a/client.js +++ b/client.js @@ -119,14 +119,16 @@ async function pay(wallet, accept) { } async function retry(accept, { txId, payerAddress, signature }) { + // Multi-signature payload: one {address, signature} entry per unique input + // address of the on-chain tx. The CLI uses address-0 (getCurrentAddress on + // a fresh wallet returns index 0), so the array is length 1. const payload = { x402Version: 2, scheme: accept.scheme, network: accept.network, payload: { txId, - payerAddress, - signature, + signatures: [{ address: payerAddress, signature }], requestId: accept.extra.requestId, }, }; diff --git a/dapp/components/X402Fetch.tsx b/dapp/components/X402Fetch.tsx index 9257f27..6fe8590 100644 --- a/dapp/components/X402Fetch.tsx +++ b/dapp/components/X402Fetch.tsx @@ -223,7 +223,10 @@ export function X402Fetch() { ); } - // Retry the original GET with the proof header. + // Retry the original GET with the proof header. The verifier expects a + // multi-signature payload (one {address, signature} entry per unique + // input address). The dApp constrains inputs to address-0, so the array + // is always length 1. setStep('retrying'); const payload = { x402Version: 2, @@ -231,8 +234,9 @@ export function X402Fetch() { network: opt.network, payload: { txId: sentTxId, - payerAddress: signed.address.address, - signature: signed.signature, + signatures: [ + { address: signed.address.address, signature: signed.signature }, + ], requestId: opt.extra.requestId, }, }; diff --git a/verifier.js b/verifier.js index 7d47514..5f2f326 100644 --- a/verifier.js +++ b/verifier.js @@ -20,6 +20,22 @@ function fail(reason) { // `requirements` is one PaymentRequirements (object) describing the route the // client is trying to satisfy: { scheme, network, amount, asset, payTo, resource }. // `payload` is the decoded PAYMENT-SIGNATURE payload from the client. +// +// Payload shape (multi-signature; no legacy single-sig back-compat): +// { +// x402Version: 2, scheme, network, +// payload: { +// txId, +// signatures: [{address, signature}, ...], // one entry per unique tx input address +// requestId, +// } +// } +// +// The verifier requires every unique input address in the tx to be present in +// `signatures` with a signature that verifies over `requestId`. That proves the +// claimant controls every funding source of the payment. The "canonical payer" +// (for blocklist / dedup record / upto refund target) is the address of the +// FIRST entry in `signatures` — client controls the ordering. async function verifyDirectPayment({ payload, requirements, @@ -29,11 +45,21 @@ async function verifyDirectPayment({ zeroConfMaxAmount = Number.MAX_SAFE_INTEGER, }) { if (!payload || typeof payload !== 'object') return fail('missing_payload'); - const { txId, payerAddress, signature, requestId } = payload.payload || {}; - if (!txId || !payerAddress || !signature || !requestId) { - return fail('missing_payload_fields'); + const inner = payload.payload || {}; + const { txId, signatures, requestId } = inner; + if (!txId || !requestId) return fail('missing_payload_fields'); + if (!Array.isArray(signatures) || signatures.length === 0) { + return fail('missing_signatures'); } + // Canonical payer = first signature's address. Used for blocklist, dedup + // record and upto refund recipient. + const firstSig = signatures[0]; + if (!firstSig || typeof firstSig.address !== 'string' || typeof firstSig.signature !== 'string') { + return fail('malformed_signatures'); + } + const payerAddress = firstSig.address; + // 1) requestId — HMAC + expiry + commitment match against the route. const decoded = verifyAndDecodeRequestId(requestId, serverSecret, { route: requirements.resource, @@ -63,21 +89,36 @@ async function verifyDirectPayment({ }); if (!paying) return fail('no_paying_output'); - // 4) The address that signed `requestId` must appear as a TX INPUT — i.e., - // it actually contributed UTXOs to the payment. Accepting output addresses - // would let any recipient of the tx (or any third-party output owner) - // claim the resource. Inputs are the only set that proves payment ownership. - const inAddrs = getInputAddresses(tx); - if (!inAddrs.has(payerAddress)) { - return fail('payer_not_in_tx_inputs'); + // 4) Build a map of {address → signature} from the payload. Reject + // duplicate addresses with conflicting signatures (defensive — the wallet + // shouldn't produce these, but we don't trust the wire). + const sigByAddr = new Map(); + for (const entry of signatures) { + if (!entry || typeof entry.address !== 'string' || typeof entry.signature !== 'string') { + return fail('malformed_signatures'); + } + const prev = sigByAddr.get(entry.address); + if (prev && prev !== entry.signature) return fail('duplicate_signatures'); + sigByAddr.set(entry.address, entry.signature); } - // 5) The signature must verify against the payer's address. - if (!verifyMessageSignature(requestId, signature, payerAddress)) { - return fail('bad_signature'); + // 5) Every unique input address must be present in the signatures map + // AND its signature must verify. That's what "the claimant controls + // every funding source" cryptographically reduces to. + const inAddrs = getInputAddresses(tx); + if (inAddrs.size === 0) return fail('no_input_addresses'); + + for (const inAddr of inAddrs) { + const sig = sigByAddr.get(inAddr); + if (!sig) return fail(`missing_signature_for_input:${inAddr}`); + if (!verifyMessageSignature(requestId, sig, inAddr)) { + return fail(`bad_signature:${inAddr}`); + } } - // 6) Blocklist: payers caught double-spending earlier are refused. + // 6) Blocklist: payers caught double-spending earlier are refused. The + // canonical payer (first signature) is the one we blocklist on void, so we + // check that address here. if (dedupStore && dedupStore.isBlocked(payerAddress)) { return fail('blocklisted'); } @@ -100,7 +141,8 @@ async function verifyDirectPayment({ } // 9) Atomic dedup. This both detects replays and is the on-disk record of - // the redemption. + // the redemption. We key dedup on (txId, outputIndex) and record the + // canonical payer (first signature address). const dedup = dedupStore.markRedeemedIfFree( { txId, outputIndex: paying.outputIndex }, { @@ -118,7 +160,7 @@ async function verifyDirectPayment({ valid: true, txId, outputIndex: paying.outputIndex, - payerAddress, + payerAddress, // first signature's address — used for refund target etc. amount: String(paying.value), paidAmount: String(paying.value), asset: paying.token, From 1bd4088de5a9f61eddb15047ac3c4733afe7fd3d Mon Sep 17 00:00:00 2001 From: Pedro Ferreira Date: Tue, 2 Jun 2026 09:40:39 -0300 Subject: [PATCH 37/37] feat(skill): add x402-pay Claude Code skill MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A Claude Code skill that pays HTTP 402 responses on Hathor via a hathor-wallet-headless backend — no browser, no popups. On a 402 it establishes the wallet (asks the user for the headless URL/wallet-id, or spins up a container), pays on-chain, signs the server's requestId once per unique input address, retries with the multi-signature PAYMENT-SIGNATURE payload, and surfaces the resource. Covers both hathor-direct and hathor-direct-upto. Safety: asks before any on-chain action, refuses cross-network payments, never persists the seed to memory, never auto-confirms mainnet. Depends on POST /wallet/sign-message in hathor-wallet-headless (upstream PR pending; README references it as #TBD until merged). Co-Authored-By: Claude Opus 4.8 (1M context) --- skills/x402-pay/README.md | 130 ++++++++++++++ skills/x402-pay/SKILL.md | 355 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 485 insertions(+) create mode 100644 skills/x402-pay/README.md create mode 100644 skills/x402-pay/SKILL.md diff --git a/skills/x402-pay/README.md b/skills/x402-pay/README.md new file mode 100644 index 0000000..f456479 --- /dev/null +++ b/skills/x402-pay/README.md @@ -0,0 +1,130 @@ +# x402-pay — Claude Code skill + +A Claude Code skill that handles HTTP 402 payments on Hathor Network. When a +Claude session makes a request that returns `402 Payment Required` from an +x402-enabled API (or the user explicitly asks to fetch a paid URL), this skill +takes over: it sets up a wallet-headless instance (starting one in Docker if +needed), pays the on-chain HTR, signs the server's `requestId` proof, retries +the request, and surfaces the resource. No browser, no popups, no human +clicking anything beyond yes/no setup prompts. + +## What it solves + +x402 (Coinbase/Cloudflare's HTTP 402 payment protocol) is built for machines +paying machines. The browser dApp at `https://x402.hathor.dev/` works for human +demos, but the real use case is agents making programmatic paid calls. This +skill is the agent-side companion of the resource server at +`https://api.x402.hathor.dev/`. + +## Requirements + +- **Claude Code** with skills support. +- **Docker** installed on the machine (only if you don't already run a + `hathor-wallet-headless` instance). +- **`hathor-wallet-headless`** ≥ the version that ships `POST /wallet/sign-message` + (see "Endpoint dependency" below). +- A **Hathor wallet seed** funded with HTR on the right network. Testnet + funds come from . + +## Endpoint dependency + +This skill uses `POST /wallet/sign-message` on the headless to sign the +`requestId` per input address of the broadcast payment tx. That endpoint was +added to `hathor-wallet-headless` for x402 specifically — PR `#TBD` upstream. +If your headless is older than the release that includes it, the skill aborts +at the signing step with a clear message pointing at the version requirement. + +## Install + +Copy or symlink this directory under `~/.claude/skills/`: + +```bash +# from the repo root +ln -s "$PWD/skills/x402-pay" ~/.claude/skills/x402-pay +``` + +Claude Code picks it up on next session start. To verify: + +``` +Inside Claude Code: /x402-pay +``` + +It should respond by initialising the skill (Step 1 — establish wallet +backend). + +## Trigger conditions + +The skill is invoked two ways: + +1. **Auto-trigger.** Claude detects a `402` status with an `accepts[]` body in + any tool result and considers this skill relevant. It asks the user + whether to proceed before doing anything on-chain. +2. **Explicit slash command.** The user types `/x402-pay` to force the skill + to load right now. Useful if you want to pre-warm the wallet setup before + any 402 hits. + +## Quick start (recommended demo) + +1. Get testnet HTR for your wallet: send `>= 5 HTR` to address-0 of your + wallet's seed. +2. In a Claude Code session, type: + + > "Fetch `https://api.x402.hathor.dev/weather` and tell me what the + > weather is in São Paulo." + +3. Claude makes the request, sees the 402, asks if you want to use the + x402-pay skill. Say yes. +4. First time only, Claude asks about your wallet: + - Is the headless running? (No → spin up via Docker.) + - What's the seed? (Pasted in chat for the demo, or pointed at a file.) +5. The skill pays, signs, retries, and surfaces the weather JSON. Claude + summarises. + +Subsequent calls in the same session skip Step 4 entirely. After the first +successful run, the skill offers to save the headless URL + wallet-id to +memory so future sessions also skip the setup. + +## Try the upto flow + +The resource server at `api.x402.hathor.dev` exposes a `/generate` route +configured as `hathor-direct-upto`. Try: + +> "Fetch `https://api.x402.hathor.dev/generate` and show me the response." + +You'll see: +- The 402's `amount` advertises the MAX (5.00 HTR), not a fixed price. +- The skill pays the full max. +- The response body includes `payment.chargedAmount` (actual usage) and + `payment.refundAmount` (remainder being refunded), with `payment.refundTxId` + pointing at the on-chain refund tx the seller broadcast back to you. +- The skill surfaces all of that to you. + +## Security notes + +- The **seed is never written to memory**. The skill takes it once, uses it + to start the headless, and forgets it. +- The skill **refuses to run cross-network**. A testnet wallet against a + mainnet API (or vice versa) aborts before any on-chain action. +- The skill **never auto-confirms mainnet usage**. If you opt into mainnet at + setup time, the prompt makes the risk explicit. +- The deployment at `headless.x402.hathor.dev` from the live PoC is publicly + reachable — convenient for ops parity during testnet demos but **not** a + pattern to copy in production. Real deployments should keep the headless + loopback-only. + +## File layout + +``` +skills/x402-pay/ +├── SKILL.md — the skill instructions Claude reads +└── README.md — this file (human-facing install + demo guide) +``` + +## Related + +- Resource server at `https://api.x402.hathor.dev/` — + source at `../../resource-server.js`. +- Reference dApp at `https://x402.hathor.dev/` — + source at `../../dapp/`. +- Spec discussion + design proposal at + `/Users/pedroferreira/Hathor/x402/x402-hathor-no-nc-proposal.md`. diff --git a/skills/x402-pay/SKILL.md b/skills/x402-pay/SKILL.md new file mode 100644 index 0000000..ddefb97 --- /dev/null +++ b/skills/x402-pay/SKILL.md @@ -0,0 +1,355 @@ +--- +name: x402-pay +description: Pay for HTTP 402 responses on Hathor Network. Use when a fetch/curl/HTTP request returns 402 Payment Required from an x402-enabled API (e.g., api.x402.hathor.dev), or when the user asks you to fetch a paid URL on Hathor. Orchestrates payment via a `hathor-wallet-headless` instance (starts one in Docker if not running). +metadata: + author: hathor-network + version: "0.1.0" +--- + +# x402-pay — pay HTTP 402 responses on Hathor + +You're driving an x402 payment for the user. The protocol is: +**fetch → 402 + payment requirements → pay on-chain → sign requestId → retry with proof → resource**. + +The wallet backend is `hathor-wallet-headless` running locally (Docker). The user **never sees a popup** — you handle the whole flow conversationally. Confirm intent once; ask for setup info only on the first call of the session; remember answers via `Memory` so subsequent calls skip prompts. + +## Inputs you need by the time you're done with Step 1 + +- `HEADLESS_URL` — **always ask the user; never default silently** (port 8000 is commonly taken on dev machines) +- `WALLET_ID` — **ask the user**; suggested defaults are `agent` or `default` +- `HEADLESS_NETWORK` — must match the 402's `network` field +- a wallet seed — only on cold start + +Save these to memory (`Memory` tool) at the end of a successful run so the next session skips Step 1. + +--- + +## Step 0 — Confirm intent (only on auto-trigger) + +If the user explicitly invoked you (e.g., `/x402-pay`), skip this step. + +Otherwise, when you see a 402 from a tool result, announce: + +> "I see this returned 402 Payment Required (`X.XX HTR` to `Wxxx…`). Want me to pay it with the x402-pay skill?" + +Only proceed on an explicit yes. + +--- + +## Step 1 — Establish the wallet backend + +**Ask first; do not probe-and-guess.** The skill MUST NOT: +- Assume `localhost:8000` silently (the port may be in use by another app). +- Run `docker ps`, read project compose files, or otherwise sniff the local environment to find a headless. +- Inspect the current working directory's repo to infer which wallet the user wants. + +Defaults appear only as suggestions inside `AskUserQuestion` options. + +### 1.0 — Check memory first + +If a previous session saved an `x402-pay-config` memory (HEADLESS_URL, WALLET_ID, HEADLESS_NETWORK), reuse those values and skip ahead to **Step 1.2** to confirm they're still reachable. + +### 1.1 — Ask the user where the headless is + +Use `AskUserQuestion` with two questions: + +**Question 1** — "Where is your hathor-wallet-headless?" +- "http://localhost:8000" *(common default; only correct if nothing else is on that port)* +- "I don't have one — start a local container in Docker" + +If neither option fits, the user picks "Other" and types a URL (e.g., `http://10.0.0.5:8000`). + +**Question 2** — "Wallet ID to use?" +- "agent" +- "default" + +If they pick "Other", they type their own wallet-id. + +If the user picked "start a local container in Docker" for Question 1, branch to **Step 1.4** instead. Otherwise continue. + +### 1.2 — Validate the URL is really a headless + +Don't trust `/health`: it's a 200-OK on many web services that aren't a headless (e.g., TmuxDeck on port 8000). Hit a headless-specific route and check the response is JSON: + +```bash +curl -fsS -H "Accept: application/json" \ + "${HEADLESS_URL}/wallet/status" \ + -H "X-Wallet-Id: ${WALLET_ID}" \ + -o /tmp/x402-status.txt -w "%{http_code} %{content_type}\n" +head -c 400 /tmp/x402-status.txt +``` + +Three things can come back: + +- **Body starts with `<` or content-type is `text/html`** → the URL isn't a headless. Tell the user clearly: + > "`` returned HTML, not JSON — it's serving a different app (port 8000 is often used by other tools). What's the right URL of your hathor-wallet-headless?" + + Re-ask Question 1 from Step 1.1. Do **not** scan the local environment to find another candidate. + +- **JSON with `statusCode: 3`** → wallet is READY. Go to **Step 1.6**. + +- **JSON with `error`/`message` saying the wallet isn't started, or HTTP 404** → URL is a headless but this wallet-id isn't loaded yet. Go to **Step 1.3** to start it. + +### 1.3 — Start a wallet on the existing headless + +Use `AskUserQuestion` for the seed material: +- **Paste seed** (24 words) — for testnet PoC only +- **Path to a seed file** — use `Read` to load it +- **Use a pre-configured `seedKey`** (if their headless has one) + +**Use the value the user actually supplied** — do not copy any literal value (`"default"`, `"test"`, etc.) from examples elsewhere in this skill. Match the right branch below: + +```bash +# Branch A — user pasted a 24-word seed (or you read it from a file): +curl -fsS -X POST "${HEADLESS_URL}/start" \ + -H "Content-Type: application/json" \ + -d "$(jq -nc --arg wid "${WALLET_ID}" --arg seed "${SEED}" \ + '{"wallet-id":$wid, seed:$seed}')" + +# Branch B — user supplied a seedKey configured in their headless: +curl -fsS -X POST "${HEADLESS_URL}/start" \ + -H "Content-Type: application/json" \ + -d "$(jq -nc --arg wid "${WALLET_ID}" --arg sk "${SEED_KEY}" \ + '{"wallet-id":$wid, seedKey:$sk}')" +``` + +The `SEED_KEY` value is **whatever the user typed** in the `AskUserQuestion` answer. If they said "test", send `"seedKey":"test"`. Never substitute "default" unless the user explicitly chose "default". + +If the response is `{success: false, error: "..."}`, surface the error verbatim and stop. Common one: `Invalid wallet seedKey` means the key isn't configured in the headless's settings — re-ask Step 1.1 for the right key or switch to the paste-seed branch. + +Then run the polling block from Step 1.7. On READY, go to **Step 1.6**. + +### 1.4 — Start a local headless in Docker + +Use `AskUserQuestion` for the network: +- **testnet** (default for demos) +- **mainnet** (extra warning: this signs real on-chain payments) +- **abort** + +Then ask for the **host port** to bind. Default 8000 is commonly taken on dev machines (TmuxDeck, other dev servers). Suggest: +- **8000** *(only if you know nothing else is on it)* +- **8765** *(safe random high port)* + +Bind the chosen port and set `HEADLESS_URL=http://localhost:${HOST_PORT}` accordingly. Then ask for the seed (same options as 1.3) and: + +```bash +docker run -d --name x402-headless \ + -p ${HOST_PORT}:8000 \ + -e HEADLESS_NETWORK="${NETWORK}" \ + -e HEADLESS_SERVER="${FULLNODE_URL}" \ + -e HEADLESS_SEED_DEFAULT="${SEED}" \ + hathornetwork/hathor-wallet-headless:latest +``` + +Where `FULLNODE_URL` is: +- `https://node1.testnet.hathor.network/v1a/` for testnet +- `https://node1.mainnet.hathor.network/v1a/` for mainnet + +Poll `${HEADLESS_URL}/wallet/status -H "X-Wallet-Id: ..."` until it returns JSON (max 30s); use the same JSON-vs-HTML check as Step 1.2 to confirm we're talking to a headless we just started, not something else that happened to be on the port. The `HEADLESS_SEED_DEFAULT` env var automatically registers a seed under the key `default`, but the wallet under that key is **not** auto-started — you still need to POST `/start` with `seedKey: "default"` (the literal string `"default"` is correct here because the Docker spin-up registers the seed under exactly that key — *not* a value the user picked): + +```bash +curl -fsS -X POST "${HEADLESS_URL}/start" \ + -H "Content-Type: application/json" \ + -d "$(jq -nc --arg wid "${WALLET_ID:-agent}" '{"wallet-id":$wid, seedKey:"default"}')" +``` + +Then run the polling block from Step 1.7. On READY, go to **Step 1.6**. + +### 1.7 — Wait for `statusCode === 3` (READY) + +**Run this exactly once as a single Bash call.** Do not fire it as multiple parallel curls — concurrent Bash calls in the same response cancel each other on the first non-zero exit. + +```bash +for i in $(seq 1 60); do + STATUS=$(curl -fsS -H "Accept: application/json" \ + "${HEADLESS_URL}/wallet/status" -H "X-Wallet-Id: ${WALLET_ID}" 2>/dev/null \ + | jq -r .statusCode 2>/dev/null) + if [ "$STATUS" = "3" ]; then + echo "READY" + exit 0 # <-- explicit clean exit; do NOT rely on loop fall-through + fi + sleep 1 +done +echo "TIMEOUT statusCode=$STATUS" +exit 1 +``` + +If this prints `READY` and exits 0, the wallet is ready — **do not re-poll, do not double-check in parallel**. Go straight to Step 1.6. + +If it prints `TIMEOUT`, tell the user and stop. Don't retry; the wallet is in a bad state and needs operator attention. + +### 1.6 — Network match check + +Get the headless's configured network: + +```bash +curl -fsS "${HEADLESS_URL}/wallet/status" -H "X-Wallet-Id: ${WALLET_ID}" | jq -r .network +``` + +Compare to the 402's `accepts[0].network` (e.g., `hathor:testnet`). The headless reports a bare name (`testnet`, `mainnet`); strip the `hathor:` prefix from the 402's value before comparing. + +If they don't match, **abort with a clear error**: + +> "Your headless wallet is on `mainnet` but the API at `` advertises `hathor:testnet`. Refusing to pay across networks. Either point the skill at a testnet wallet or refresh the URL." + +No transaction is broadcast. Do not proceed. + +--- + +## Step 2 — Pay + +Parse the 402's `accepts[0]`. You need: +- `amount` (string, atomic units) +- `asset` (token UID, `"00"` for HTR) +- `payTo` (address string) +- `scheme` (`hathor-direct` or `hathor-direct-upto`) +- `network` (e.g., `hathor:testnet`) +- `extra.requestId` (HMAC-signed challenge token) + +### 2.1 — Send the payment tx + +```bash +curl -fsS -X POST "${HEADLESS_URL}/wallet/send-tx" \ + -H "Content-Type: application/json" \ + -H "X-Wallet-Id: ${WALLET_ID}" \ + -d "$(jq -nc --arg addr "${PAY_TO}" --argjson val ${AMOUNT_INT} --arg tok "${ASSET}" '{ + outputs: [{ address: $addr, value: $val, token: $tok }] + }')" +``` + +The `value` field must be an **integer** (atomic units), not a string. The response has `{ success: true, hash: "" }`. Capture `hash` as `TX_ID`. + +If `success` is false, surface the error and stop. Common cause: insufficient HTR. Tell the user to fund the wallet and retry. + +### 2.2 — Fetch the broadcast tx and extract input addresses + +```bash +curl -fsS "${HEADLESS_URL}/wallet/transaction?id=${TX_ID}" -H "X-Wallet-Id: ${WALLET_ID}" \ + | jq -r '[.inputs[].decoded.address] | unique | .[]' +``` + +That gives you the **unique** input addresses, one per line. Save them into a shell array (or process iteratively). + +### 2.3 — Sign requestId once per unique input address + +For each `addr` in the unique-inputs set: + +```bash +curl -fsS -X POST "${HEADLESS_URL}/wallet/sign-message" \ + -H "Content-Type: application/json" \ + -H "X-Wallet-Id: ${WALLET_ID}" \ + -d "$(jq -nc --arg msg "${REQUEST_ID}" --arg addr "${addr}" '{ + message: $msg, + address: $addr + }')" +``` + +The response is `{ success: true, signature: "BASE64…", address: "Wxxx…", index: N }`. Accumulate the `{address, signature}` pairs into a JSON array `SIGNATURES`. + +> Endpoint requirement: `POST /wallet/sign-message` was added to `hathor-wallet-headless` in version ≥ X.Y.Z (the upstream PR motivated by this skill). If you get a 404 here, the user's headless is too old — point them at the version requirement in this skill's README. + +### 2.4 — Assemble the PAYMENT-SIGNATURE header and retry + +Build the payload: + +```bash +PAYLOAD=$(jq -nc \ + --arg scheme "${SCHEME}" \ + --arg network "${NETWORK_HEADER}" \ + --arg txId "${TX_ID}" \ + --argjson sigs "${SIGNATURES}" \ + --arg requestId "${REQUEST_ID}" \ + '{ + x402Version: 2, + scheme: $scheme, + network: $network, + payload: { txId: $txId, signatures: $sigs, requestId: $requestId } + }') + +PAYMENT_SIG=$(printf '%s' "${PAYLOAD}" | base64 -w0) + +curl -fsS "${URL}" -H "PAYMENT-SIGNATURE: ${PAYMENT_SIG}" +``` + +`NETWORK_HEADER` is the 402's `network` field verbatim (e.g., `hathor:testnet`). +`SCHEME` is the 402's `scheme` field. + +Order matters in the `signatures` array: the **first** entry's address is the canonical payer (used by the server for blocklist and — for upto — refund target). If the user has a preference for which address gets the refund, put it first; otherwise the wallet's natural ordering is fine. + +If the response is 200, the body is `{ data: , payment: }`. Return `data` to the user. + +If the response is 402 again, surface the error reason from the body (`reason` or `error` field) and stop. Common reasons: +- `request_id_expired` — the 402's `extra.requestId` is past its TTL. Re-fetch the URL to get a fresh 402, then redo Step 2. +- `bad_signature:` — one of the signatures didn't verify. The headless's sign-message must have a bug, or the wallet's keys changed; retry once. +- `missing_signature_for_input:` — we missed an input address. Step 2.2 should have caught all; double-check the unique set. +- `replay` — the payment was already redeemed. (Unlikely on first try; means the wallet's send-tx returned a known txId, maybe a no-op tx.) + +--- + +## Step 3 — Surface the result + +### For `scheme: hathor-direct` +Print the response's `data` field to the user. Mention the txId briefly: + +> "Paid `0.XX HTR` via tx ``. Here's the response: ..." + +### For `scheme: hathor-direct-upto` +The response body includes `payment.chargedAmount`, `payment.refundAmount`, `payment.refundTxId`. Show the user a summary: + +> "Authorized up to **5.00 HTR**, actually charged **1.20 HTR**, refunded **3.80 HTR** (refund tx ``). Here's the response: ..." + +Then print `data`. + +The refund tx is on-chain and may not yet be confirmed by the time you respond. It will land within seconds on testnet; the user's wallet will pick it up automatically. + +--- + +## Step 4 — Remember setup (offer once) + +If everything succeeded and the user hasn't already opted in, ask: + +> "Want me to remember `HEADLESS_URL=`, `WALLET_ID=`, and `HEADLESS_NETWORK=` so the next x402 payment in a new session skips the setup prompts?" + +If yes, save a project memory via the `Memory` tool: + +``` +--- +name: x402-pay-config +description: Saved wallet-headless config for x402-pay skill (auto-detected on first 402) +metadata: + type: project +--- + +HEADLESS_URL: +WALLET_ID: +HEADLESS_NETWORK: + +(Write the actual values here, not the placeholders.) +``` + +Do **not** save the seed under any circumstances. The seed should only ever be passed at start-time and the user re-types/re-points-to it on each new headless boot. + +--- + +## Error handling — quick reference + +| Where | Symptom | What to do | +|---|---|---| +| Step 1.4 | `docker: command not found` | Tell user to install Docker, or re-run Step 1.1 with the URL of an existing headless | +| Step 1.4 | `port is already allocated` | Re-prompt for a different host port (suggest 8765 or 9000) and adjust `HEADLESS_URL` | +| Step 1.2 | URL returns HTML | The URL isn't a headless. Re-prompt Step 1.1 for the right URL; do **not** scan docker/compose to guess | +| Step 2.1 | `{success: false, error: "Insufficient amount of HTR..."}` | Tell user the wallet is underfunded, print the wallet's address-0 (`curl /wallet/address?index=0`), suggest the testnet faucet | +| Step 2.2 | tx not found at headless | Headless may not have indexed the tx yet — retry once after 2s | +| Step 2.3 | `POST /wallet/sign-message` returns 404 | Headless version is too old; mention the version requirement | +| Step 2.3 | `{success: false, error: "address does not belong to the wallet"}` | A tx input came from outside the wallet — that means we're talking to the wrong wallet. Recheck `WALLET_ID` | +| Step 2.4 | `request_id_expired` | Re-fetch the URL for a fresh requestId, then redo from Step 2 (the on-chain tx can be reused with a new signature over the new requestId) | + +--- + +## Notes on what this skill **does not** do + +- It does not run on mainnet without an explicit prompt + warning. +- It does not save the seed to memory. +- It does not try to recover from a hung headless beyond a single retry. If the user's wallet is in a weird state (`statusCode` 1 or 2 for minutes), tell them to restart it. +- It does not retry a failed payment indefinitely. One attempt per 402. +- It does not support payment channels (those don't exist in the current `hathor-direct` scheme).