diff --git a/README.md b/README.md index 2890158..e85a7c6 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,188 @@ -# psf-bch-api +# psf-bch-api-base -This is a REST API for communicating with Bitcoin Cash infrastructure. It replaces [bch-api](https://github.com/Permissionless-Software-Foundation/bch-api), and it implements [x402-bch protocol](https://github.com/x402-bch/x402-bch) to handle payments to access the API. +[![License](https://img.shields.io/npm/l/@psf/bch-js)](https://github.com/Permissionless-Software-Foundation/psf-bch-api/blob/master/LICENSE.md) +[![js-standard-style](https://img.shields.io/badge/javascript-standard%20code%20style-green.svg?style=flat-square)](https://github.com/feross/standard) + +This project is a fork of `psf-bch-api` with one major change: paid access now uses the `x402` protocol on the Base ecosystem, with pricing in USDC, instead of `x402-bch` on BCH. + +The API surface remains focused on BCH infrastructure (BCH full node, Fulcrum, and SLP indexer), but monetization and payment verification are handled through x402-compatible middleware and facilitator endpoints. + +## What Changed In This Fork + +- Switched from `x402-bch` middleware to `x402-express`. +- Added Base/EVM payment support (`@x402/evm`) and `x402-axios` client example. +- Pricing is configured in `X402_PRICE_USDC` (USDC amount), not BCH satoshis. +- x402 network is configured using CAIP-2 format (for example `eip155:8453` for Base mainnet and `eip155:84532` for Base Sepolia). +- Facilitator auth headers are generated using Coinbase CDP JWT auth (`FACILITATOR_KEY_ID` and `FACILITATOR_SECRET_KEY`) when using CDP endpoints. + +## Architecture + +The server is a Node.js + Express REST API following a Clean Architecture style, and it still depends on: + +- BCH full node JSON-RPC +- Fulcrum API +- SLP indexer API + +The access-control layer now supports: + +- open access (no auth, no payment) +- bearer-token auth +- x402 paid access on Base + USDC +- optional bearer bypass for trusted clients when x402 is enabled + +## Quick Start + +1. Install dependencies: + +```bash +npm install +``` + +2. Create a local env file: + +```bash +cp .env-example .env +``` + +3. Edit `.env` for your infrastructure and access-control mode. + +4. Start the server: + +```bash +npm start +``` + +By default, the API runs on `http://localhost:5942` and controllers are mounted under `/v6`. + +## Environment Variables + +All configuration is loaded from environment variables (typically from `.env`). + +### Core Server and BCH Infrastructure + +- `PORT` (default: `5942`) +- `NODE_ENV` (default: `development`) +- `API_PREFIX` (default: `/v6`) +- `LOG_LEVEL` (default: `info`) +- `RPC_BASEURL` (default: `http://127.0.0.1:8332`) +- `RPC_USERNAME` +- `RPC_PASSWORD` +- `RPC_TIMEOUT_MS` (default: `15000`) +- `RPC_REQUEST_ID_PREFIX` (default: `psf-bch-api`) +- `FULCRUM_API` +- `FULCRUM_TIMEOUT_MS` (default: `15000`) +- `SLP_INDEXER_API` +- `SLP_INDEXER_TIMEOUT_MS` (default: `15000`) +- `REST_URL` or `LOCAL_RESTURL` (default fallback: `http://127.0.0.1:5942/v6/`) +- `IPFS_GATEWAY` (default: `p2wdb-gateway-678.fullstack.cash`) +- `SERVER_KEEPALIVE_TIMEOUT_MS` (default: `3000`) +- `SERVER_HEADERS_TIMEOUT_MS` (default: `65000`) +- `SERVER_REQUEST_TIMEOUT_MS` (default: `120000`) + +### x402 + Base + USDC Settings + +- `X402_ENABLED` (default: `true`) +- `SERVER_BASE_ADDRESS` (EVM address receiving x402 settlements) +- `X402_PRICE_USDC` (USDC charged per request) +- `x402_NETWORK` (CAIP-2 chain ID; e.g. `eip155:8453` or `eip155:84532`) +- `x402_FACILITATOR_URL` (default: `https://api.cdp.coinbase.com/platform/v2/x402`) +- `FACILITATOR_KEY_ID` (required for CDP facilitator auth) +- `FACILITATOR_SECRET_KEY` (required for CDP facilitator auth) + +### Optional Bearer Auth + +- `USE_BASIC_AUTH` (default: `false`) +- `BASIC_AUTH_TOKEN` + +## Access Control Modes + +Behavior is controlled by `X402_ENABLED` and `USE_BASIC_AUTH`. + +### 1) Open Access + +```bash +X402_ENABLED=false +USE_BASIC_AUTH=false +``` + +No payment and no auth checks. + +### 2) Bearer Auth Only + +```bash +X402_ENABLED=false +USE_BASIC_AUTH=true +BASIC_AUTH_TOKEN=my-secret-token +``` + +Requests (except `/` and `/health`) must send: + +```text +Authorization: Bearer my-secret-token +``` + +### 3) x402 Payments on Base (USDC) + +```bash +X402_ENABLED=true +USE_BASIC_AUTH=false +SERVER_BASE_ADDRESS=0xYourBaseAddress +X402_PRICE_USDC=0.1 +x402_NETWORK=eip155:8453 +x402_FACILITATOR_URL=https://api.cdp.coinbase.com/platform/v2/x402 +FACILITATOR_KEY_ID=your_key_id +FACILITATOR_SECRET_KEY=your_secret +``` + +Protected endpoints return `402 Payment Required` when no valid payment is attached. x402-capable clients can pay and retry automatically. + +### 4) x402 + Bearer Bypass + +```bash +X402_ENABLED=true +USE_BASIC_AUTH=true +BASIC_AUTH_TOKEN=my-secret-token +``` + +Bearer-authenticated requests bypass payment; all others must pay via x402. + +## Client Example: Axios + x402 + +Use `examples/01-x402-axios-client.js` to test the payment flow end-to-end. + +What it does: + +1. Calls a protected endpoint without payment and expects `402`. +2. Repeats the call using `x402-axios` + an EVM wallet and expects success. + +Run it with an EVM private key: + +```bash +PRIVATE_KEY=0x... node examples/01-x402-axios-client.js +``` + +The script is configured for Base mainnet by default (`viem/chains` `base`). You can switch it to Base Sepolia by using the commented testnet import in the file. + +## Coinbase CDP Credentials + +When using Coinbase's hosted facilitator (`https://api.cdp.coinbase.com/platform/v2/x402`), you must provide: + +- `FACILITATOR_KEY_ID` +- `FACILITATOR_SECRET_KEY` + +These are CDP Secret API Key credentials from the Coinbase Developer Platform API Keys dashboard and are used to generate JWT auth headers for `/verify` and `/settle`. + +## Development + +Common commands: + +```bash +npm start +npm test +npm run test:integration +npm run docs +``` ## License [MIT](./LICENSE.md) - -## x402-bch Payments - -All REST endpoints exposed under the `/v6` prefix are protected by the [`x402-bch-express`](https://www.npmjs.com/package/x402-bch-express) middleware. Each API call requires a BCH payment authorization for **200 satoshis**. The middleware advertises payment requirements via HTTP 402 responses and validates incoming `X-PAYMENT` headers with a configured Facilitator. - -### Configuration - -Environment variables control the payment flow: - -- `X402_ENABLED` — set to `false` (case-insensitive) to disable the middleware. Defaults to enabled. -- `SERVER_BCH_ADDRESS` — BCH cash address that receives funding transactions. Defaults to `bitcoincash:qqlrzp23w08434twmvr4fxw672whkjy0py26r63g3d`. -- `FACILITATOR_URL` — Root URL of the facilitator service (e.g., `http://localhost:4345/facilitator`). -- `X402_PRICE_SAT` — Optional; override the satoshi price per call (defaults to `200`). - -When `X402_ENABLED=false`, the server continues to operate without payment headers for local development or trusted deployments. - -### Manual Verification - -1. Start or point to an `x402-bch` facilitator service (the example facilitator listens at `http://localhost:4345/facilitator`). -2. Run the API server with the default configuration: `npm start`. -3. Call a protected endpoint without an `X-PAYMENT` header, e.g. `curl -i http://localhost:5942/v6/full-node/control/getNetworkInfo`. The server will respond with HTTP `402` and include payment requirements. -4. Restart the server with `X402_ENABLED=false npm start` to confirm that the same request now bypasses the middleware (useful for local development without payments). - diff --git a/bch-api-dependency-graph.png b/bch-api-dependency-graph.png new file mode 100644 index 0000000..a48e713 Binary files /dev/null and b/bch-api-dependency-graph.png differ diff --git a/bin/server.js b/bin/server.js index 587edeb..73bc9bf 100644 --- a/bin/server.js +++ b/bin/server.js @@ -60,6 +60,7 @@ class Server { try { // Create an Express instance. const app = express() + app.set('trust proxy', true) const x402Settings = getX402Settings() const basicAuthSettings = getBasicAuthSettings() @@ -195,7 +196,10 @@ class Server { // Request logging middleware app.use((req, res, next) => { - wlogger.info(`${req.method} ${req.path}`) + wlogger.info(`${req.method} ${req.path}`, { + client_ip: req.ip, + remote_address: req.socket?.remoteAddress || null + }) next() }) @@ -258,6 +262,11 @@ class Server { wlogger.info(`Server started on port ${this.config.port}`) }) + // Explicit timeout settings reduce stale keep-alive socket reuse races. + this.server.keepAliveTimeout = this.config.serverKeepAliveTimeoutMs + this.server.headersTimeout = this.config.serverHeadersTimeoutMs + this.server.requestTimeout = this.config.serverRequestTimeoutMs + this.server.on('error', (err) => { console.error('Server error:', err) wlogger.error('Server error:', err) diff --git a/dev-docs/update-logs/2026-03-16.md b/dev-docs/update-logs/2026-03-16.md new file mode 100644 index 0000000..fa1bf66 --- /dev/null +++ b/dev-docs/update-logs/2026-03-16.md @@ -0,0 +1,21 @@ +# 2026-03-16 Update Log + +## Summary + +Reduced noisy error logging for common SLP transaction misses in the `/v6/slp/txid` path. + +## Changes Made + +- Updated `src/use-cases/slp-use-cases.js` in `getTxid()`: + - Added a guard for expected missing-record errors (`404` + `Key not found in database`). + - Skips `wlogger.error()` for that specific, common case. + - Still rethrows the error so API response behavior is unchanged. +- Updated `src/controllers/rest-api/slp/controller.js` in `handleError()`: + - Added the same guard to suppress duplicate error-level logs for the same expected case. + - Keeps normal error logging for all other errors. + +## Outcome + +- The common "Key not found in database" case no longer pollutes error logs. +- Unexpected failures continue to be logged at error level. +- Client-facing status and error message behavior remains unchanged. diff --git a/dev-docs/update-logs/2026-03-17.md b/dev-docs/update-logs/2026-03-17.md new file mode 100644 index 0000000..710707b --- /dev/null +++ b/dev-docs/update-logs/2026-03-17.md @@ -0,0 +1,76 @@ +# 2026-03-17 Update Log + +## Summary + +Enhanced REST request logging to capture client network identity in Winston logs, enabled proxy-aware IP resolution, and reduced Fulcrum error-log noise for expected missing-transaction requests. + +## Changes Made + +- Updated `bin/server.js`: + - Set Express proxy handling with `app.set('trust proxy', true)`. + - Kept the current Winston request message format (`"${req.method} ${req.path}"`). + - Added structured Winston metadata fields to request logs: + - `client_ip` from `req.ip` + - `remote_address` from `req.socket.remoteAddress` +- Updated `src/adapters/fulcrum-api.js`: + - Added parsing helpers to normalize Fulcrum error messages from multiple response shapes. + - Mapped common daemon missing-TX error (`No such mempool or blockchain transaction`) to: + - status `404` + - message `Transaction not found` +- Updated `src/use-cases/fulcrum-use-cases.js`: + - Removed duplicate error logging in `getTransactionDetails()` and now rethrows adapter errors without a second error-level log. +- Updated `src/controllers/rest-api/fulcrum/controller.js`: + - Added TXID validation (`64`-character hex) for `GET /v6/fulcrum/tx/data/:txid`. + - Updated `handleError()` logging policy: + - `Transaction not found` (`404`) logs at `info` + - other `4xx` logs at `warn` + - `5xx` logs at `error` + +## Useful Fields Available for REST Request Logging + +- Routing and request basics: + - `method` (`req.method`) + - `path` (`req.path`) + - `original_url` (`req.originalUrl`) + - `query` (`req.query`) +- Client network identity: + - `client_ip` (`req.ip`) + - `forwarded_ips` (`req.ips`, when behind one or more proxies) + - `remote_address` (`req.socket.remoteAddress`) +- HTTP and transport: + - `protocol` (`req.protocol`) + - `secure` (`req.secure`) + - `http_version` (`req.httpVersion`) + - `host` (`req.get('host')`) + - `origin` (`req.get('origin')`) + - `referer` (`req.get('referer')`) + - `user_agent` (`req.get('user-agent')`) +- Request/response performance and size: + - `status_code` (`res.statusCode`, from `res.on('finish')`) + - `duration_ms` (elapsed time between request start and response finish) + - `request_size_bytes` (`req.get('content-length')`) + - `response_size_bytes` (`res.getHeader('content-length')`) +- App-specific request context in this codebase: + - `basic_auth_valid` (`req.locals.basicAuthValid`) + - x402 decision/bypass status (derived from middleware path and config) + +## Already Logging + +- In Winston request logs: + - `message` with method + path (for example `GET /v6/full-node/blockchain/getBlockCount`) + - `client_ip` + - `remote_address` + - `timestamp` (from Winston timestamp formatter) + - `level` +- In console endpoint logs: + - Request line with method, path, and `req.ip` + - Response line with method, path, and final `res.statusCode` + +## Outcome + +- Request logs now preserve existing behavior while adding IP attribution fields. +- `trust proxy` ensures `req.ip` is proxy-aware when the server is deployed behind a reverse proxy. +- The project now has a documented list of high-value request fields for future logging expansion. +- Fulcrum missing-transaction lookups now return cleaner API semantics (`404 Transaction not found`). +- Duplicate error logs for a single missing TX lookup were removed. +- Invalid TXIDs are rejected early with a `400` validation error. diff --git a/examples/01-create-account.js b/examples/01-create-account.js deleted file mode 100644 index 3f82033..0000000 --- a/examples/01-create-account.js +++ /dev/null @@ -1,67 +0,0 @@ -/* - Example script creating a key-pair for a Nostr account and publishing profile metadata. - Refactored to use REST API instead of WebSocket. - - Run the server with `npm start` in the main directory, before running this example. -*/ - -import { generateSecretKey, getPublicKey, finalizeEvent } from 'nostr-tools/pure' -import * as nip19 from 'nostr-tools/nip19' -import { bytesToHex } from '@noble/hashes/utils.js' - -const API_URL = process.env.API_URL || 'http://localhost:5942' - -// Generate keys -const sk = generateSecretKey() // `sk` is a Uint8Array -const nsec = nip19.nsecEncode(sk) -const skHex = bytesToHex(sk) - -const pk = getPublicKey(sk) // `pk` is a hex string -const npub = nip19.npubEncode(pk) - -console.log('private key:', skHex) -console.log('encoded private key:', nsec) -console.log() -console.log('public key:', pk) -console.log('encoded public key:', npub) -console.log() - -// Create profile metadata event (kind 0) -const profileMetadata = { - name: 'Alice', - about: 'Hello, I am Alice!', - picture: 'https://example.com/alice.jpg' -} - -const eventTemplate = { - kind: 0, - created_at: Math.floor(Date.now() / 1000), - tags: [], - content: JSON.stringify(profileMetadata) -} - -// Sign the event -const signedEvent = finalizeEvent(eventTemplate, sk) -console.log('Signed event:', JSON.stringify(signedEvent, null, 2)) - -// Publish to REST API -try { - const response = await fetch(`${API_URL}/event`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(signedEvent) - }) - - const result = await response.json() - console.log('Publish result:', result) - - if (result.accepted) { - console.log('Profile metadata published successfully!') - } else { - console.error('Failed to publish:', result.message) - } -} catch (err) { - console.error('Error publishing event:', err) -} diff --git a/examples/08-x402-axios-client.js b/examples/01-x402-axios-client.js similarity index 100% rename from examples/08-x402-axios-client.js rename to examples/01-x402-axios-client.js diff --git a/examples/02-read-posts.js b/examples/02-read-posts.js deleted file mode 100644 index 4776a13..0000000 --- a/examples/02-read-posts.js +++ /dev/null @@ -1,44 +0,0 @@ -/* - Example script for reading posts (kind 1 events) from a relay. - Refactored to use REST API instead of WebSocket. - - Run the server with `npm start` in the main directory, before running this example. -*/ - -const API_URL = process.env.API_URL || 'http://localhost:5942' - -// JB55's public key -const jb55 = '32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245' - -// Create subscription ID -const subId = 'read-posts-' + Date.now() - -// Create filters - read posts from JB55 -const filters = { - limit: 2, - kinds: [1], - authors: [jb55] -} - -try { - // Query events using GET /req/:subId - const filtersJson = encodeURIComponent(JSON.stringify([filters])) - const url = `${API_URL}/req/${subId}?filters=${filtersJson}` - - console.log(`Querying events from ${API_URL}`) - console.log('Filters:', JSON.stringify(filters, null, 2)) - - const response = await fetch(url) - const events = await response.json() - - console.log(`\nReceived ${events.length} events:`) - events.forEach((ev, index) => { - console.log(`\nEvent ${index + 1}:`) - console.log(' ID:', ev.id) - console.log(' Author:', ev.pubkey) - console.log(' Created:', new Date(ev.created_at * 1000).toISOString()) - console.log(' Content:', ev.content) - }) -} catch (err) { - console.error('Error reading posts:', err) -} diff --git a/examples/03-write-post.js b/examples/03-write-post.js deleted file mode 100644 index 4721444..0000000 --- a/examples/03-write-post.js +++ /dev/null @@ -1,55 +0,0 @@ -/* - Example script for writing a post to a relay. - Refactored to use REST API instead of WebSocket. - - Run the server with `npm start` in the main directory, before running this example. -*/ - -import { finalizeEvent, getPublicKey } from 'nostr-tools/pure' -import { hexToBytes } from '@noble/hashes/utils.js' - -const API_URL = process.env.API_URL || 'http://localhost:5942' - -// Alice is our user making the post. -const alicePrivKeyHex = '3292a48aa331aeccce003d50d70fbd79617ba91860abbd2c78fa4a8301e36bc0' -const alicePrivKeyBin = hexToBytes(alicePrivKeyHex) -const alicePubKey = getPublicKey(alicePrivKeyBin) -console.log(`Alice Public Key: ${alicePubKey}`) - -const now = new Date() - -// Generate a post. -const eventTemplate = { - kind: 1, - created_at: Math.floor(Date.now() / 1000), - tags: [], - content: `This is a test message posted at ${now.toLocaleString()}` -} -console.log(`eventTemplate: ${JSON.stringify(eventTemplate, null, 2)}`) - -// Sign the post -const signedEvent = finalizeEvent(eventTemplate, alicePrivKeyBin) -console.log('signedEvent:', JSON.stringify(signedEvent, null, 2)) - -// Publish to REST API -try { - const response = await fetch(`${API_URL}/event`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(signedEvent) - }) - - const result = await response.json() - console.log('result:', result) - - if (result.accepted) { - console.log('Post published successfully!') - console.log('Event ID:', result.eventId) - } else { - console.error('Failed to publish:', result.message) - } -} catch (err) { - console.error('Error publishing post:', err) -} diff --git a/examples/04-read-alice-posts.js b/examples/04-read-alice-posts.js deleted file mode 100644 index 1636f18..0000000 --- a/examples/04-read-alice-posts.js +++ /dev/null @@ -1,49 +0,0 @@ -/* - Example script for reading posts from user Alice. - Refactored to use REST API instead of WebSocket. - - Run the server with `npm start` in the main directory, before running this example. -*/ - -import { getPublicKey } from 'nostr-tools/pure' -import { hexToBytes } from '@noble/hashes/utils.js' - -const API_URL = process.env.API_URL || 'http://localhost:5942' - -// Alice is our user. -const alicePrivKeyHex = '3292a48aa331aeccce003d50d70fbd79617ba91860abbd2c78fa4a8301e36bc0' -const alicePrivKeyBin = hexToBytes(alicePrivKeyHex) -const alicePubKey = getPublicKey(alicePrivKeyBin) -console.log(`Alice Public Key: ${alicePubKey}`) - -// Create subscription ID -const subId = 'read-alice-posts-' + Date.now() - -// Create filters - read posts from Alice -const filters = { - limit: 2, - kinds: [1], - authors: [alicePubKey] -} - -try { - // Query events using GET /req/:subId - const filtersJson = encodeURIComponent(JSON.stringify([filters])) - const url = `${API_URL}/req/${subId}?filters=${filtersJson}` - - console.log(`Querying events from ${API_URL}`) - console.log('Filters:', JSON.stringify(filters, null, 2)) - - const response = await fetch(url) - const events = await response.json() - - console.log(`\nReceived ${events.length} events from Alice:`) - events.forEach((ev, index) => { - console.log(`\nEvent ${index + 1}:`) - console.log(' ID:', ev.id) - console.log(' Created:', new Date(ev.created_at * 1000).toISOString()) - console.log(' Content:', ev.content) - }) -} catch (err) { - console.error('Error reading Alice posts:', err) -} diff --git a/examples/05-get-follow-list.js b/examples/05-get-follow-list.js deleted file mode 100644 index 7ef397d..0000000 --- a/examples/05-get-follow-list.js +++ /dev/null @@ -1,53 +0,0 @@ -/* - Example script for getting a follow list (kind 3 events). - Refactored to use REST API instead of WebSocket. - - Run the server with `npm start` in the main directory, before running this example. -*/ - -import { getPublicKey } from 'nostr-tools/pure' -import { hexToBytes } from '@noble/hashes/utils.js' - -const API_URL = process.env.API_URL || 'http://localhost:5942' - -// Alice is our user to get the follow list. -const alicePrivKeyHex = '3292a48aa331aeccce003d50d70fbd79617ba91860abbd2c78fa4a8301e36bc0' -const alicePrivKeyBin = hexToBytes(alicePrivKeyHex) -const alicePubKey = getPublicKey(alicePrivKeyBin) -console.log(`Alice Public Key: ${alicePubKey}`) - -// Create subscription ID -const subId = 'get-follow-list-' + Date.now() - -// Create filters - get follow list (kind 3) from Alice -const filters = { - limit: 5, - kinds: [3], - authors: [alicePubKey] -} - -try { - // Query events using GET /req/:subId - const filtersJson = encodeURIComponent(JSON.stringify([filters])) - const url = `${API_URL}/req/${subId}?filters=${filtersJson}` - - console.log(`Querying follow list from ${API_URL}`) - console.log('Filters:', JSON.stringify(filters, null, 2)) - - const response = await fetch(url) - const events = await response.json() - - if (events.length > 0) { - // Get the most recent follow list (kind 3 events are replaceable) - const followListEvent = events[0] - const aliceFollowList = followListEvent.tags.filter(tag => tag[0] === 'p') - console.log(`\nAlice Follow list (${aliceFollowList.length} followed users):`) - aliceFollowList.forEach((tag, index) => { - console.log(` ${index + 1}. ${tag[1]}${tag[3] ? ` (${tag[3]})` : ''}`) - }) - } else { - console.log('\nNo follow list found for Alice') - } -} catch (err) { - console.error('Error getting follow list:', err) -} diff --git a/examples/06-update-follow-list.js b/examples/06-update-follow-list.js deleted file mode 100644 index 292e241..0000000 --- a/examples/06-update-follow-list.js +++ /dev/null @@ -1,63 +0,0 @@ -/* - Example to update the follow list with a new list of people to follow. - Refactored to use REST API instead of WebSocket. - - Run the server with `npm start` in the main directory, before running this example. -*/ - -import { finalizeEvent, getPublicKey } from 'nostr-tools/pure' -import { hexToBytes } from '@noble/hashes/utils.js' - -const API_URL = process.env.API_URL || 'http://localhost:5942' - -// Alice wants to update her follow list -const alicePrivKeyHex = '3292a48aa331aeccce003d50d70fbd79617ba91860abbd2c78fa4a8301e36bc0' -const alicePrivKeyBin = hexToBytes(alicePrivKeyHex) -const alicePubKey = getPublicKey(alicePrivKeyBin) -console.log(`Alice Public Key: ${alicePubKey}`) - -// Bob is the person to be added to the new follow list -const bobPrivKeyHex = 'd2e71a977bc3900d6b0f787421e3d1a666cd12ca625482b0d9eeffd23489c99f' -const bobPrivKeyBin = hexToBytes(bobPrivKeyHex) -const bobPubKey = getPublicKey(bobPrivKeyBin) -console.log(`Bob Public Key: ${bobPubKey}`) - -const psf = 'wss://nostr-relay.psfoundation.info' - -const followList = [ - ['p', bobPubKey, psf, 'bob'] -] - -// Generate a follow list event (kind 3) -const eventTemplate = { - kind: 3, - created_at: Math.floor(Date.now() / 1000), - tags: followList, - content: '' -} -console.log(`eventTemplate: ${JSON.stringify(eventTemplate, null, 2)}`) - -// Sign the event -const signedEvent = finalizeEvent(eventTemplate, alicePrivKeyBin) - -// Publish to REST API -try { - const response = await fetch(`${API_URL}/event`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(signedEvent) - }) - - const result = await response.json() - console.log('Publish result:', result) - - if (result.accepted) { - console.log('Follow list updated successfully!') - } else { - console.error('Failed to update follow list:', result.message) - } -} catch (err) { - console.error('Error updating follow list:', err) -} diff --git a/examples/07-liking-event.js b/examples/07-liking-event.js deleted file mode 100644 index 5c0a685..0000000 --- a/examples/07-liking-event.js +++ /dev/null @@ -1,59 +0,0 @@ -/* - Example script for adding a reaction (like) to an event. - Refactored to use REST API instead of WebSocket. - https://github.com/nostr-protocol/nips/blob/master/25.md - - Run the server with `npm start` in the main directory, before running this example. -*/ - -import { hexToBytes } from '@noble/hashes/utils.js' -import { finalizeEvent, getPublicKey } from 'nostr-tools/pure' - -const API_URL = process.env.API_URL || 'http://localhost:5942' - -const bobPrivKeyHex = 'd2e71a977bc3900d6b0f787421e3d1a666cd12ca625482b0d9eeffd23489c99f' -const bobPrivKeyBin = hexToBytes(bobPrivKeyHex) -const bobPubKey = getPublicKey(bobPrivKeyBin) - -const psf = 'wss://nostr-relay.psfoundation.info' - -const evIdToLike = 'd09b4c5da59be3cd2768aa53fa78b77bf4859084c94f3bf26d401f004a9c8167' -const evIdAuthorPubKey = '2c7e76c0f8dc1dca9d0197c7d19be580a8d074ccada6a2f6ebe056ae41092e92' - -// Generate like event (kind 7) -const likeEventTemplate = { - kind: 7, - created_at: Math.floor(Date.now() / 1000), - pubkey: bobPubKey, - tags: [ - ['e', evIdToLike, psf], // "e" tag includes event id, relay reference - ['p', evIdAuthorPubKey, psf] // "p" tag includes author pubkey, relay reference - ], - content: '+' -} - -// Sign the event -const signedEvent = finalizeEvent(likeEventTemplate, bobPrivKeyBin) -console.log('signedEvent:', JSON.stringify(signedEvent, null, 2)) - -// Publish to REST API -try { - const response = await fetch(`${API_URL}/event`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(signedEvent) - }) - - const result = await response.json() - console.log('result:', result) - - if (result.accepted) { - console.log('Like published successfully!') - } else { - console.error('Failed to publish like:', result.message) - } -} catch (err) { - console.error('Error publishing like:', err) -} diff --git a/examples/README.md b/examples/README.md index d840c99..b407ffc 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,90 +1,7 @@ -# REST2NOSTR Examples +# x402 Examples -This directory contains examples refactored from the `nostr-sandbox/` directory to use the REST API instead of WebSocket connections. +This example uses the Base blockchain to talk to the psf-bch-api server at https://x402.fullstack.cash. -## Prerequisites - -1. Install dependencies: -```bash -npm install nostr-tools @noble/hashes -``` - -2. Start the REST2NOSTR proxy server: -```bash -npm start -``` - -3. Set the API_URL environment variable if the server is not running on localhost:3000: -```bash -export API_URL=http://localhost:3000 -``` - -## Examples - -### 01-create-account.js -Creates a new Nostr account keypair and publishes profile metadata (kind 0 event). - -```bash -node examples/01-create-account.js -``` - -### 02-read-posts.js -Reads posts (kind 1 events) from a specific author using GET /req/:subId. - -```bash -node examples/02-read-posts.js -``` - -### 03-write-post.js -Publishes a text post (kind 1 event) using POST /event. - -```bash -node examples/03-write-post.js -``` - -### 04-read-alice-posts.js -Reads posts from Alice's account using GET /req/:subId with author filter. - -```bash -node examples/04-read-alice-posts.js -``` - -### 14-get-follow-list.js -Retrieves a user's follow list (kind 3 event) using GET /req/:subId. - -```bash -node examples/05-get-follow-list.js -``` - -### 15-update-follow-list.js -Updates a user's follow list (kind 3 event) using POST /event. - -```bash -node examples/06-update-follow-list.js -``` - -### 17-liking-event.js -Adds a reaction/like to an event (kind 7 event) using POST /event. - -```bash -node examples/07-liking-event.js -``` - -## API Endpoints Used - -- **POST /event**: Publish events to the relay -- **GET /req/:subId**: Stateless query for events (returns immediately) - -## Differences from WebSocket Examples - -1. **No WebSocket connections**: All communication is via HTTP REST API -2. **Stateless queries**: GET /req/:subId returns events immediately rather than streaming -3. **Event publishing**: POST /event returns immediately with acceptance status -4. **No subscription management**: For stateless queries, subscriptions are automatically closed after EOSE - -## Notes - -- These examples use the same private keys as the original sandbox examples for consistency -- The REST API handles WebSocket connections to relays internally -- For real-time streaming, use POST /req/:subId which supports Server-Sent Events (SSE) +Get a private key for an Base address that contains some USDC. Then execute the example like this: +- `PRIVATE_KEY=0x8bff4962a50d43fe93ac2d7df4da12e6bd701bd1bf12b66d391365ae03058d4f node 08-x402-axios-client.js` diff --git a/package-lock.json b/package-lock.json index b37825c..c935549 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,14 +10,14 @@ "license": "MIT", "dependencies": { "@coinbase/cdp-sdk": "1.45.0", - "@psf/bch-js": "7.1.11", + "@psf/bch-js": "7.1.14", "@x402/core": "2.6.0", "@x402/evm": "2.6.0", "axios": "1.7.7", "cors": "2.8.5", "dotenv": "16.3.1", "express": "5.1.0", - "minimal-slp-wallet": "7.1.4", + "minimal-slp-wallet": "7.1.5", "psffpp": "1.2.1", "slp-token-media": "1.2.10", "winston": "3.11.0", @@ -36,15 +36,15 @@ } }, "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==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==", "license": "MIT" }, "node_modules/@babel/runtime": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", - "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz", + "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -164,6 +164,12 @@ "lodash": "^4.17.20" } }, + "node_modules/@chris.troutner/bitcore-lib-cash/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/@chris.troutner/bitcore-lib-cash/node_modules/inherits": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", @@ -247,27 +253,6 @@ "zod": "^3.24.4" } }, - "node_modules/@coinbase/cdp-sdk/node_modules/abitype": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.6.tgz", - "integrity": "sha512-MMSqYh4+C/aVqI2RQaWqbvI4Kxo5cQV40WQ4QFtDnNzCkqChm8MuENhElmynZlO0qUy/ObkEUaXtKqYnx1Kp3A==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/wevm" - }, - "peerDependencies": { - "typescript": ">=5.0.4", - "zod": "^3 >=3.22.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - }, - "zod": { - "optional": true - } - } - }, "node_modules/@coinbase/cdp-sdk/node_modules/axios": { "version": "1.13.6", "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.6.tgz", @@ -802,6 +787,30 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/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/@eslint/eslintrc/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/@eslint/js": { "version": "8.57.1", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", @@ -990,13 +999,13 @@ } }, "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "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.0.1" + "ansi-regex": "^6.2.2" }, "engines": { "node": ">=12" @@ -1576,6 +1585,19 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "license": "MIT" }, + "node_modules/@metamask/sdk-communication-layer/node_modules/utf-8-validate": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", + "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, "node_modules/@metamask/sdk-install-modal-web": { "version": "0.32.1", "resolved": "https://registry.npmjs.org/@metamask/sdk-install-modal-web/-/sdk-install-modal-web-0.32.1.tgz", @@ -1664,9 +1686,9 @@ } }, "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==", + "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" @@ -1750,9 +1772,9 @@ } }, "node_modules/@psf/bch-js": { - "version": "7.1.11", - "resolved": "https://registry.npmjs.org/@psf/bch-js/-/bch-js-7.1.11.tgz", - "integrity": "sha512-gDJCaY2aG8EtUWcR9D4tbiyM1BkHd7gkuO7NRaLpwdbSrnU51lyPr69mjQLKOcVlL+aXdJsOjL5pm15t4zq18w==", + "version": "7.1.14", + "resolved": "https://registry.npmjs.org/@psf/bch-js/-/bch-js-7.1.14.tgz", + "integrity": "sha512-B/NXuxSoOHgMR0tHyY8qpXN3VDATeBhd6qhasJsiEjb22IGIjsXsdJ0oZR2DLnn/1UA+94+XJNyVz2UlcaqEpw==", "license": "MIT", "dependencies": { "@chris.troutner/bip32-utils": "1.0.5", @@ -3310,27 +3332,6 @@ } } }, - "node_modules/@solana/errors/node_modules/chalk": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", - "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@solana/errors/node_modules/commander": { - "version": "14.0.2", - "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.2.tgz", - "integrity": "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==", - "license": "MIT", - "engines": { - "node": ">=20" - } - }, "node_modules/@solana/fast-stable-stringify": { "version": "5.5.1", "resolved": "https://registry.npmjs.org/@solana/fast-stable-stringify/-/fast-stable-stringify-5.5.1.tgz", @@ -3792,27 +3793,6 @@ } } }, - "node_modules/@solana/rpc-subscriptions-channel-websocket/node_modules/ws": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", - "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", - "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/@solana/rpc-subscriptions-spec": { "version": "5.5.1", "resolved": "https://registry.npmjs.org/@solana/rpc-subscriptions-spec/-/rpc-subscriptions-spec-5.5.1.tgz", @@ -3883,12 +3863,6 @@ } } }, - "node_modules/@solana/rpc-transport-http/node_modules/undici-types": { - "version": "7.22.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.22.0.tgz", - "integrity": "sha512-RKZvifiL60xdsIuC80UY0dq8Z7DbJUV8/l2hOVbyZAxBzEeQU4Z58+4ZzJ6WN2Lidi9KzT5EbiGX+PI/UGYuRw==", - "license": "MIT" - }, "node_modules/@solana/rpc-types": { "version": "5.5.1", "resolved": "https://registry.npmjs.org/@solana/rpc-types/-/rpc-types-5.5.1.tgz", @@ -4159,33 +4133,6 @@ "typescript": ">=5.3.3" } }, - "node_modules/@solana/web3.js/node_modules/bn.js": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.3.tgz", - "integrity": "sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w==", - "license": "MIT" - }, - "node_modules/@solana/web3.js/node_modules/chalk": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", - "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@solana/web3.js/node_modules/commander": { - "version": "14.0.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", - "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", - "license": "MIT", - "engines": { - "node": ">=20" - } - }, "node_modules/@spruceid/siwe-parser": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@spruceid/siwe-parser/-/siwe-parser-2.1.2.tgz", @@ -4238,10 +4185,16 @@ "tslib": "^2.8.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/@tanstack/query-core": { - "version": "5.90.20", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.20.tgz", - "integrity": "sha512-OMD2HLpNouXEfZJWcKeVKUgQ5n+n3A2JFmBaScpNDUqSrQSjiveC7dKMe53uJUg1nDG16ttFPz2xfilz6i2uVg==", + "version": "5.95.2", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.95.2.tgz", + "integrity": "sha512-o4T8vZHZET4Bib3jZ/tCW9/7080urD4c+0/AUaYVpIqOsr7y0reBc1oX3ttNaSW5mYyvZHctiQ/UOP2PfdmFEQ==", "license": "MIT", "peer": true, "funding": { @@ -4250,13 +4203,13 @@ } }, "node_modules/@tanstack/react-query": { - "version": "5.90.21", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.21.tgz", - "integrity": "sha512-0Lu6y5t+tvlTJMTO7oh5NSpJfpg/5D41LlThfepTixPYkJ0sE2Jj0m0f6yYqujBwIXlId87e234+MxG3D3g7kg==", + "version": "5.95.2", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.95.2.tgz", + "integrity": "sha512-/wGkvLj/st5Ud1Q76KF1uFxScV7WeqN1slQx5280ycwAyYkIPGaRZAEgHxe3bjirSd5Zpwkj6zNcR4cqYni/ZA==", "license": "MIT", "peer": true, "dependencies": { - "@tanstack/query-core": "5.90.20" + "@tanstack/query-core": "5.95.2" }, "funding": { "type": "github", @@ -4276,9 +4229,9 @@ } }, "node_modules/@types/debug": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", + "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", "license": "MIT", "dependencies": { "@types/ms": "*" @@ -4343,14 +4296,20 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "25.0.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.9.tgz", - "integrity": "sha512-/rpCXHlCWeqClNBwUhDcusJxXYDjZTyE8v5oTO7WbL8eij2nKhUeU89/6xgjU7N4/Vh3He0BtyhJdQbDyhiXAw==", + "version": "22.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", + "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", "license": "MIT", "dependencies": { - "undici-types": "~7.16.0" + "undici-types": "~6.19.2" } }, + "node_modules/@types/node/node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "license": "MIT" + }, "node_modules/@types/retry": { "version": "0.12.1", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz", @@ -4677,6 +4636,21 @@ "ws": "^7.5.1" } }, + "node_modules/@walletconnect/jsonrpc-ws-connection/node_modules/utf-8-validate": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", + "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, "node_modules/@walletconnect/jsonrpc-ws-connection/node_modules/ws": { "version": "7.5.10", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", @@ -5336,28 +5310,6 @@ "zod": "^3.24.2" } }, - "node_modules/@x402/extensions/node_modules/ajv": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@x402/extensions/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "license": "MIT" - }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -5371,16 +5323,16 @@ "license": "Apache-2.0" }, "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==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.6.tgz", + "integrity": "sha512-MMSqYh4+C/aVqI2RQaWqbvI4Kxo5cQV40WQ4QFtDnNzCkqChm8MuENhElmynZlO0qUy/ObkEUaXtKqYnx1Kp3A==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/wevm" }, "peerDependencies": { "typescript": ">=5.0.4", - "zod": "^3.22.0 || ^4.0.0" + "zod": "^3 >=3.22.0" }, "peerDependenciesMeta": { "typescript": { @@ -5405,9 +5357,9 @@ } }, "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -5458,16 +5410,15 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "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" + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -5491,28 +5442,18 @@ } } }, - "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" + "fast-deep-equal": "^3.1.3" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "peerDependencies": { + "ajv": "^8.8.2" } }, - "node_modules/ajv-formats/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "license": "MIT" - }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -5537,6 +5478,24 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/ansi-styles/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/ansi-styles/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/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -5598,6 +5557,16 @@ "node": ">=16.0.0" } }, + "node_modules/apidoc/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -5734,7 +5703,6 @@ "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", @@ -5900,12 +5868,15 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.9.15", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.15.tgz", - "integrity": "sha512-kX8h7K2srmDyYnXRIppo4AH/wYgzWVCs+eKr3RusRSQ5PvRYoEFmR/I0PbdTjKFAoKqp5+kbxnNTFO9jOfSVJg==", + "version": "2.10.10", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.10.tgz", + "integrity": "sha512-sUoJ3IMxx4AyRqO4MLeHlnGDkyXRoUG0/AI9fjK+vS72ekpV0yWVY7O0BVjmBcRtkNcsAO2QDZ4tdKKGoI6YaQ==", "license": "Apache-2.0", "bin": { - "baseline-browser-mapping": "dist/cli.js" + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" } }, "node_modules/bc-bip68": { @@ -6750,6 +6721,12 @@ "node": ">=8.0.0" } }, + "node_modules/bitcore-lib/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/bitcore-lib/node_modules/inherits": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", @@ -6757,9 +6734,9 @@ "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==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.3.tgz", + "integrity": "sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w==", "license": "MIT" }, "node_modules/body-parser": { @@ -6823,12 +6800,6 @@ "text-encoding-utf-8": "^1.0.2" } }, - "node_modules/borsh/node_modules/bn.js": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.3.tgz", - "integrity": "sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w==", - "license": "MIT" - }, "node_modules/bowser": { "version": "2.14.1", "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.14.1.tgz", @@ -7124,9 +7095,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001764", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001764.tgz", - "integrity": "sha512-9JGuzl2M+vPL+pz70gtMF9sHdMFbY9FJaQBi186cHKH3pSzDvzoUJUPV6fqiKIMyXbud9ZLg4F3Yza1vJ1+93g==", + "version": "1.0.30001781", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001781.tgz", + "integrity": "sha512-RdwNCyMsNBftLjW6w01z8bKEvT6e/5tpPVEgtn22TiLGlstHOVecsX2KHFkD5e/vRnIE4EGzpuIODb3mtswtkw==", "funding": [ { "type": "opencollective", @@ -7170,12 +7141,6 @@ "sha.js": "^2.4.11" } }, - "node_modules/cbw-sdk/node_modules/bn.js": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.3.tgz", - "integrity": "sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w==", - "license": "MIT" - }, "node_modules/cbw-sdk/node_modules/eventemitter3": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", @@ -7193,17 +7158,12 @@ } }, "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, + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { - "node": ">=10" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { "url": "https://github.com/chalk/chalk?sponsor=1" @@ -7309,45 +7269,6 @@ } }, "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/color-string": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-2.1.4.tgz", - "integrity": "sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg==", - "license": "MIT", - "dependencies": { - "color-name": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/color-string/node_modules/color-name": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", - "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", - "license": "MIT", - "engines": { - "node": ">=12.20" - } - }, - "node_modules/color/node_modules/color-convert": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-3.1.3.tgz", "integrity": "sha512-fasDH2ont2GqF5HpyO4w0+BcewlhHEZOFn9c1ckZdHpJ56Qb7MHhH/IcJZbBGgvdtwdwNbLvxiBEdg336iA9Sg==", @@ -7359,7 +7280,7 @@ "node": ">=14.6" } }, - "node_modules/color/node_modules/color-name": { + "node_modules/color-name": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", @@ -7368,6 +7289,18 @@ "node": ">=12.20" } }, + "node_modules/color-string": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-2.1.4.tgz", + "integrity": "sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg==", + "license": "MIT", + "dependencies": { + "color-name": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", @@ -7387,13 +7320,12 @@ } }, "node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "dev": true, + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.2.tgz", + "integrity": "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==", "license": "MIT", "engines": { - "node": ">=14" + "node": ">=20" } }, "node_modules/concat-map": { @@ -7962,21 +7894,6 @@ "node": ">=16" } }, - "node_modules/eciesjs/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/ecurve": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/ecurve/-/ecurve-1.0.6.tgz", @@ -7994,9 +7911,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.267", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", - "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==", + "version": "1.5.321", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.321.tgz", + "integrity": "sha512-L2C7Q279W2D/J4PLZLk7sebOILDSWos7bMsMNN06rK482umHUrh/3lM8G7IlHFOYip2oAg5nha1rCMxr/rs6ZQ==", "license": "ISC" }, "node_modules/elliptic": { @@ -8015,9 +7932,9 @@ } }, "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", - "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "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/emoji-regex": { @@ -8078,6 +7995,27 @@ "xmlhttprequest-ssl": "~2.1.1" } }, + "node_modules/engine.io-client/node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "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/engine.io-parser": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", @@ -8088,13 +8026,13 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.18.4", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.4.tgz", - "integrity": "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==", + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.1.tgz", + "integrity": "sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==", "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "tapable": "^2.3.0" }, "engines": { "node": ">=10.13.0" @@ -8238,9 +8176,9 @@ } }, "node_modules/es-iterator-helpers": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.2.tgz", - "integrity": "sha512-BrUQ0cPTB/IwXj23HtwHjS9n7O4h9FX94b4xc5zlTHxeLgTAdzYUDyy6KdExAl9lbN5rtfe44xpjpmj9grxs5w==", + "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": { @@ -8259,6 +8197,7 @@ "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": { @@ -8302,7 +8241,6 @@ "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" @@ -8802,19 +8740,25 @@ } }, "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "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": { - "is-core-module": "^2.13.0", + "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" } @@ -8888,6 +8832,47 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/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/eslint/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/eslint/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/espree": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", @@ -9157,13 +9142,6 @@ "node": ">=14.0.0" } }, - "node_modules/ethers/node_modules/@adraffy/ens-normalize": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", - "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==", - "license": "MIT", - "peer": true - }, "node_modules/ethers/node_modules/@noble/curves": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", @@ -9190,30 +9168,6 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/ethers/node_modules/@types/node": { - "version": "22.7.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", - "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "undici-types": "~6.19.2" - } - }, - "node_modules/ethers/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", - "license": "0BSD", - "peer": true - }, - "node_modules/ethers/node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "license": "MIT", - "peer": true - }, "node_modules/ethers/node_modules/ws": { "version": "8.17.1", "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", @@ -9541,9 +9495,9 @@ } }, "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", "dev": true, "license": "ISC" }, @@ -9661,9 +9615,9 @@ } }, "node_modules/fs-extra": { - "version": "11.3.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.3.tgz", - "integrity": "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==", + "version": "11.3.4", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.4.tgz", + "integrity": "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==", "dev": true, "license": "MIT", "dependencies": { @@ -9831,7 +9785,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "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", "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", @@ -9925,9 +9879,9 @@ "license": "MIT" }, "node_modules/h3": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.6.tgz", - "integrity": "sha512-oi15ESLW5LRthZ+qPCi5GNasY/gvynSKUQxgiovrY63bPAtG59wtM+LSrlcwvOHAXzGrXVLnI97brbkdPF9WoQ==", + "version": "1.15.10", + "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.10.tgz", + "integrity": "sha512-YzJeWSkDZxAhvmp8dexjRK5hxziRO7I9m0N53WhvYL5NiWfkUkzssVzY9jvGu0HBoLFW6+duYmNSn6MaZBCCtg==", "license": "MIT", "dependencies": { "cookie-es": "^1.2.2", @@ -10155,9 +10109,9 @@ } }, "node_modules/hono": { - "version": "4.12.7", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.7.tgz", - "integrity": "sha512-jq9l1DM0zVIvsm3lv9Nw9nlJnMNPOcAtsbsgiUhWcFzPE99Gvo6yRTlszSLLYacMeQ6quHD6hMfId8crVHvexw==", + "version": "4.12.9", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.9.tgz", + "integrity": "sha512-wy3T8Zm2bsEvxKZM5w21VdHDDcwVS1yUFFY6i8UobSsKfFceT7TOwhbhfKsDyx7tYQlmRM5FLpIuYvNFyjctiA==", "license": "MIT", "engines": { "node": ">=16.9.0" @@ -11014,6 +10968,21 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "license": "MIT" }, + "node_modules/jayson/node_modules/utf-8-validate": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", + "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, "node_modules/jayson/node_modules/ws": { "version": "7.5.10", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", @@ -11065,9 +11034,9 @@ } }, "node_modules/jose": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.1.tgz", - "integrity": "sha512-jUaKr1yrbfaImV7R2TN/b3IcZzsw38/chqMpo2XJ7i2F8AfM/lA4G1goC3JVEwg0H7UldTmSt3P68nt31W7/mw==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.2.tgz", + "integrity": "sha512-d7kPDd34KO/YnzaDOlikGpOurfF0ByC2sEV4cANCtdqLlTfBlw2p14O/5d/zv40gJPbIQxfES3nSx1/oYNyuZQ==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/panva" @@ -11159,10 +11128,9 @@ "license": "ISC" }, "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, + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { @@ -11398,9 +11366,9 @@ } }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", "license": "MIT" }, "node_modules/lodash.merge": { @@ -11427,6 +11395,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/log-symbols/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/logform": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz", @@ -11457,11 +11442,13 @@ } }, "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" + "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/make-dir": { "version": "4.0.0", @@ -11618,13 +11605,13 @@ } }, "node_modules/minimal-slp-wallet": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/minimal-slp-wallet/-/minimal-slp-wallet-7.1.4.tgz", - "integrity": "sha512-oHPDu+dUyAT8YOyKvb6JGZYIoalXAEHvcAUby7OgL3D/5R+cR21FTjpqpp7BJp+NFcGRANohnLAqpP2vt6tgFA==", + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/minimal-slp-wallet/-/minimal-slp-wallet-7.1.5.tgz", + "integrity": "sha512-dROdawFZJZLvyTRndJi987S+z0cOG9k6coyyTAfkaaQftP+UayjUyjKeQlJVrKAPgIzxhk6EoZKD6AtoGjwQrw==", "license": "MIT", "dependencies": { "@chris.troutner/retry-queue": "1.0.11", - "@psf/bch-js": "7.1.11", + "@psf/bch-js": "7.1.14", "bch-consumer": "1.6.2", "bch-donation": "1.1.2", "crypto-js": "4.0.0" @@ -11643,9 +11630,9 @@ "license": "MIT" }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -11664,11 +11651,11 @@ } }, "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "engines": { "node": ">=16 || 14 >=14.17" } @@ -11744,6 +11731,7 @@ "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": { @@ -11762,13 +11750,13 @@ } }, "node_modules/mocha/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "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.1" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -11836,9 +11824,9 @@ "license": "(Apache-2.0 AND MIT)" }, "node_modules/nan": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.24.0.tgz", - "integrity": "sha512-Vpf9qnVW1RaDkoNKFUvfxqAbtI8ncb8OJlqZ9wwpXzWPEsvsB1nvdUi6oYrHIkQ1Y/tMDnr1h4nczS0VB9Xykg==", + "version": "2.26.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.26.2.tgz", + "integrity": "sha512-0tTvBTYkt3tdGw22nrAy50x7gpbGCCFH3AFcyS5WiUu7Eu4vWlri1woE6qHBSfy11vksDqkiwjOnlR7WV8G1Hw==", "license": "MIT" }, "node_modules/natural-compare": { @@ -11869,6 +11857,33 @@ "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", "license": "MIT" }, + "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==", + "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-exports-info/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -11913,22 +11928,22 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.27", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", - "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "version": "2.0.36", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", + "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", "license": "MIT" }, "node_modules/nodemon": { - "version": "3.1.11", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.11.tgz", - "integrity": "sha512-is96t8F/1//UHAjNPHpbsNY46ELPpftGUoSVNXwUfMk/qdjSylYrWSu1XavVTBOn526kFiOR733ATgNBCQyH0g==", + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.14.tgz", + "integrity": "sha512-jakjZi93UtB3jHMWsXL68FXSAosbLfY0In5gtKq3niLSkrWznrVBzXFNOEMJUfc9+Ke7SHWoAZsiMkNP3vq6Jw==", "dev": true, "license": "MIT", "dependencies": { "chokidar": "^3.5.2", "debug": "^4", "ignore-by-default": "^1.0.1", - "minimatch": "^3.1.2", + "minimatch": "^10.2.1", "pstree.remy": "^1.1.8", "semver": "^7.5.3", "simple-update-notifier": "^2.0.0", @@ -11947,6 +11962,29 @@ "url": "https://opencollective.com/nodemon" } }, + "node_modules/nodemon/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/nodemon/node_modules/brace-expansion": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", + "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, "node_modules/nodemon/node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -11995,6 +12033,22 @@ "node": ">=4" } }, + "node_modules/nodemon/node_modules/minimatch": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/nodemon/node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -12156,7 +12210,6 @@ "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", @@ -12319,9 +12372,9 @@ } }, "node_modules/ox": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/ox/-/ox-0.14.0.tgz", - "integrity": "sha512-WLOB7IKnmI3Ol6RAqY7CJdZKl8QaI44LN91OGF1061YIeN6bL5IsFcdp7+oQShRyamE/8fW/CBRWhJAOzI35Dw==", + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.14.7.tgz", + "integrity": "sha512-zSQ/cfBdolj7U4++NAvH7sI+VG0T3pEohITCgcQj8KlawvTDY4vGVhDT64Atsm0d6adWfIYHDpu88iUBMMp+AQ==", "funding": [ { "type": "github", @@ -12348,6 +12401,48 @@ } } }, + "node_modules/ox/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/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/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/ox/node_modules/eventemitter3": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", @@ -12768,6 +12863,13 @@ "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-to-regexp": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", @@ -13078,6 +13180,48 @@ } } }, + "node_modules/porto/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/porto/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/porto/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/porto/node_modules/eventemitter3": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", @@ -13432,9 +13576,9 @@ } }, "node_modules/qs": { - "version": "6.14.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", - "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz", + "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" @@ -13833,9 +13977,9 @@ } }, "node_modules/rpc-websockets": { - "version": "9.3.5", - "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-9.3.5.tgz", - "integrity": "sha512-4mAmr+AEhPYJ9TmDtxF3r3ZcbWy7W8kvZ4PoZYw/Xgp2J7WixjwTgiQZsoTDvch5nimmg3Ay6/0Kuh9oIvVs9A==", + "version": "9.3.6", + "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-9.3.6.tgz", + "integrity": "sha512-RzuOQDGd+EtR/cBYQAH/0jjaBzhyvXXGROhxigGJPf+q3XKyvtelZCucylzxiq5MaGlfBx1075djTsxFsFDgrA==", "license": "LGPL-3.0-only", "dependencies": { "@swc/helpers": "^0.5.11", @@ -13870,20 +14014,6 @@ "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", "license": "MIT" }, - "node_modules/rpc-websockets/node_modules/utf-8-validate": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-6.0.6.tgz", - "integrity": "sha512-q3l3P9UtEEiAHcsgsqTgf9PPjctrDWoIXW3NpOHFdRDbLvu4DLIcxHangJ4RLrWkBcKjmcs/6NkerI8T/rE4LA==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=6.14.2" - } - }, "node_modules/rpc-websockets/node_modules/uuid": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", @@ -14045,40 +14175,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/schema-utils/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/schema-utils/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/schema-utils/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "license": "MIT" - }, "node_modules/scryptsy": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-2.1.0.tgz", @@ -14105,10 +14201,16 @@ "node": ">=4.0.0" } }, + "node_modules/secp256k1/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/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -14147,6 +14249,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" @@ -14488,9 +14591,9 @@ } }, "node_modules/socket.io-parser": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.5.tgz", - "integrity": "sha512-bPMmpy/5WWKHea5Y/jYAP6k74A+hvmRCQaJuJB6I/ML5JZq/KfNieUVo/3Mh7SAqn7TyFdIo6wqYHInG1MU1bQ==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.6.tgz", + "integrity": "sha512-asJqbVBDsBCJx0pTqw3WfesSY0iRX+2xzWEWzrpcH7L6fLzrhyF8WPI8UaeM4YCuDfpwA/cgsdugMsmtz8EJeg==", "license": "MIT", "dependencies": { "@socket.io/component-emitter": "~3.1.0", @@ -14915,9 +15018,9 @@ } }, "node_modules/tapable": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", - "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.1.tgz", + "integrity": "sha512-b+u3CEM6FjDHru+nhUSjDofpWSBp2rINziJWgApm72wwGasQ/wKXftZe4tI2Y5HPv6OpzXSZHOFq87H4vfsgsw==", "license": "MIT", "engines": { "node": ">=6" @@ -14964,26 +15067,32 @@ } }, "node_modules/tape/node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "version": "2.0.0-next.6", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.6.tgz", + "integrity": "sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA==", "license": "MIT", "dependencies": { - "is-core-module": "^2.13.0", + "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/terser": { - "version": "5.46.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz", - "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", + "version": "5.46.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.1.tgz", + "integrity": "sha512-vzCjQO/rgUuK9sf8VJZvjqiqiHFaZLnOiimmUuOKODxWL8mm/xua7viT7aqX7dgPY60otQjUotzFMmCB4VdmqQ==", "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -14999,15 +15108,14 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.16", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz", - "integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.4.0.tgz", + "integrity": "sha512-Bn5vxm48flOIfkdl5CaD2+1CiUVbonWQ3KQPyP7/EuIl9Gbzq/gQFOzaMFUEgVjB1396tcK0SG8XcNJ/2kDH8g==", "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", "schema-utils": "^4.3.0", - "serialize-javascript": "^6.0.2", "terser": "^5.31.1" }, "engines": { @@ -15039,34 +15147,48 @@ "license": "MIT" }, "node_modules/test-exclude": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", - "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", + "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": "^9.0.4" + "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": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", + "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "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": { @@ -15084,14 +15206,31 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/test-exclude/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "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.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "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.1" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -15100,6 +15239,22 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/text-encoding-utf-8": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz", @@ -15213,9 +15368,9 @@ } }, "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==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "license": "0BSD" }, "node_modules/tweetnacl": { @@ -15355,9 +15510,9 @@ "license": "MIT" }, "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.2.tgz", + "integrity": "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ==", "license": "Apache-2.0", "peer": true, "bin": { @@ -15433,9 +15588,9 @@ "license": "MIT" }, "node_modules/undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.5.tgz", + "integrity": "sha512-kNh333UBSbgK35OIW7FwJTr9tTfVIG51Fm1tSVT7m8foPHfDVjsb7OIee/q/rs3bB2aV/3qOPgG5mHNWl1odiA==", "license": "MIT" }, "node_modules/universalify": { @@ -15567,15 +15722,6 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/unstorage/node_modules/lru-cache": { - "version": "11.2.6", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", - "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", - "license": "BlueOak-1.0.0", - "engines": { - "node": "20 || >=22" - } - }, "node_modules/unstorage/node_modules/readdirp": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", @@ -15648,11 +15794,12 @@ } }, "node_modules/utf-8-validate": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", - "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-6.0.6.tgz", + "integrity": "sha512-q3l3P9UtEEiAHcsgsqTgf9PPjctrDWoIXW3NpOHFdRDbLvu4DLIcxHangJ4RLrWkBcKjmcs/6NkerI8T/rE4LA==", "hasInstallScript": true, "license": "MIT", + "optional": true, "dependencies": { "node-gyp-build": "^4.3.0" }, @@ -15781,9 +15928,9 @@ } }, "node_modules/viem": { - "version": "2.47.1", - "resolved": "https://registry.npmjs.org/viem/-/viem-2.47.1.tgz", - "integrity": "sha512-frlK109+X5z2vlZeIGKa6Rxev6CcIpumV/VVhaIPc/QFotiB6t/CgUwkMlYfr4F2YNBZZ2l6jguWz2sY1XrQHw==", + "version": "2.47.6", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.47.6.tgz", + "integrity": "sha512-zExmbI99NGvMdYa7fmqSTLgkwh48dmhgEqFrUgkpL4kfG4XkVefZ8dZqIKVUhZo6Uhf0FrrEXOsHm9LUyIvI2Q==", "funding": [ { "type": "github", @@ -15798,7 +15945,7 @@ "@scure/bip39": "1.6.0", "abitype": "1.2.3", "isows": "1.0.7", - "ox": "0.14.0", + "ox": "0.14.7", "ws": "8.18.3" }, "peerDependencies": { @@ -15810,6 +15957,63 @@ } } }, + "node_modules/viem/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/viem/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/viem/node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "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/wagmi": { "version": "2.19.5", "resolved": "https://registry.npmjs.org/wagmi/-/wagmi-2.19.5.tgz", @@ -15861,9 +16065,9 @@ "license": "BSD-2-Clause" }, "node_modules/webpack": { - "version": "5.104.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.104.1.tgz", - "integrity": "sha512-Qphch25abbMNtekmEGJmeRUhLDbe+QfiWTiqpKYkpCOWY64v9eyl+KRRLmqOFA2AvKPpc9DC6+u2n76tQLBoaA==", + "version": "5.105.4", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.4.tgz", + "integrity": "sha512-jTywjboN9aHxFlToqb0K0Zs9SbBoW4zRUlGzI2tYNxVYcEi/IPpn+Xi4ye5jTLvX2YeLuic/IvxNot+Q1jMoOw==", "license": "MIT", "dependencies": { "@types/eslint-scope": "^3.7.7", @@ -15872,11 +16076,11 @@ "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.15.0", + "acorn": "^8.16.0", "acorn-import-phases": "^1.0.3", "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.4", + "enhanced-resolve": "^5.20.0", "es-module-lexer": "^2.0.0", "eslint-scope": "5.1.1", "events": "^3.2.0", @@ -15888,9 +16092,9 @@ "neo-async": "^2.6.2", "schema-utils": "^4.3.3", "tapable": "^2.3.0", - "terser-webpack-plugin": "^5.3.16", - "watchpack": "^2.4.4", - "webpack-sources": "^3.3.3" + "terser-webpack-plugin": "^5.3.17", + "watchpack": "^2.5.1", + "webpack-sources": "^3.3.4" }, "bin": { "webpack": "bin/webpack.js" @@ -16032,9 +16236,9 @@ } }, "node_modules/webpack/node_modules/webpack-sources": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", - "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.4.tgz", + "integrity": "sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q==", "license": "MIT", "engines": { "node": ">=10.13.0" @@ -16292,9 +16496,9 @@ "license": "ISC" }, "node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz", + "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==", "license": "MIT", "engines": { "node": ">=10.0.0" @@ -17122,6 +17326,21 @@ "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", "license": "MIT" }, + "node_modules/x402-express/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/x402-express/node_modules/raw-body": { "version": "2.5.3", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", diff --git a/package.json b/package.json index 7d68700..f6790e7 100644 --- a/package.json +++ b/package.json @@ -16,14 +16,14 @@ "description": "REST API proxy to Bitcoin Cash infrastructure", "dependencies": { "@coinbase/cdp-sdk": "1.45.0", - "@psf/bch-js": "7.1.11", + "@psf/bch-js": "7.1.14", "@x402/core": "2.6.0", "@x402/evm": "2.6.0", "axios": "1.7.7", "cors": "2.8.5", "dotenv": "16.3.1", "express": "5.1.0", - "minimal-slp-wallet": "7.1.4", + "minimal-slp-wallet": "7.1.5", "psffpp": "1.2.1", "slp-token-media": "1.2.10", "winston": "3.11.0", diff --git a/production/data/.gitkeep b/production/data/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/production/data/.gitkeep @@ -0,0 +1 @@ + diff --git a/production/docker/.env-example b/production/docker/.env-example index 3d1e320..53488be 100644 --- a/production/docker/.env-example +++ b/production/docker/.env-example @@ -9,7 +9,7 @@ RPC_PASSWORD=password FULCRUM_API=http://172.17.0.1:3001/v1 # SLP Indexer -SLP_INDEXER_API=http://172.17.0.1:5010 +SLP_INDEXER_API=http://172.17.0.1:5020 # REST API URL for wallet operations LOCAL_RESTURL=http://172.17.0.1:5942/v6 diff --git a/production/docker/docker-compose.yml b/production/docker/docker-compose.yml index 881d8d8..0bca108 100644 --- a/production/docker/docker-compose.yml +++ b/production/docker/docker-compose.yml @@ -17,4 +17,6 @@ services: volumes: #- ./start-rest2nostr.sh:/home/safeuser/REST2NOSTR/start-rest2nostr.sh - ./.env:/home/safeuser/.env + - ../data:/home/safeuser/psf-bch-api/production/data + - ../data/logs:/home/safeuser/psf-bch-api/logs restart: always \ No newline at end of file diff --git a/src/adapters/fulcrum-api.js b/src/adapters/fulcrum-api.js index d39a7f7..fd2c744 100644 --- a/src/adapters/fulcrum-api.js +++ b/src/adapters/fulcrum-api.js @@ -65,17 +65,28 @@ class FulcrumAPIAdapter { // Attempt to extract error message from response data if (err.response && err.response.data) { const data = err.response.data + const status = err.response.status || 400 + const message = this._extractErrorMessage(data) + + if (this._isCommonMissingTxError(message)) { + return this._formatError('Transaction not found', 404) + } + + if (message) { + return this._formatError(message, status) + } + // Handle structured error responses if (data.error) { - return this._formatError(data.error, err.response.status || 400) + return this._formatError(data.error, status) } // Handle string error messages if (typeof data === 'string') { - return this._formatError(data, err.response.status || 400) + return this._formatError(data, status) } // Handle object responses that might contain error info if (typeof data === 'object' && data.message) { - return this._formatError(data.message, err.response.status || 400) + return this._formatError(data.message, status) } // Fallback to returning the status return this._formatError('Fulcrum API error', err.response.status || 500) @@ -119,6 +130,25 @@ class FulcrumAPIAdapter { status: status || 500 } } + + _extractErrorMessage (data) { + if (!data) return '' + + if (typeof data === 'string') return data + + if (typeof data === 'object') { + if (typeof data.error === 'string') return data.error + if (data.error && typeof data.error === 'object' && data.error.message) return data.error.message + if (data.message) return data.message + } + + return '' + } + + _isCommonMissingTxError (message = '') { + return typeof message === 'string' && + message.includes('No such mempool or blockchain transaction') + } } export default FulcrumAPIAdapter diff --git a/src/config/env/common.js b/src/config/env/common.js index 777a844..9d77b96 100644 --- a/src/config/env/common.js +++ b/src/config/env/common.js @@ -57,6 +57,11 @@ export default { // Server port port: parseInt(process.env.PORT, 10) || 5942, + // HTTP server connection lifecycle configuration. + serverKeepAliveTimeoutMs: Number(process.env.SERVER_KEEPALIVE_TIMEOUT_MS || 3000), + serverHeadersTimeoutMs: Number(process.env.SERVER_HEADERS_TIMEOUT_MS || 65000), + serverRequestTimeoutMs: Number(process.env.SERVER_REQUEST_TIMEOUT_MS || 120000), + // Environment env: process.env.NODE_ENV || 'development', diff --git a/src/controllers/rest-api/fulcrum/controller.js b/src/controllers/rest-api/fulcrum/controller.js index ca018df..dd88d63 100644 --- a/src/controllers/rest-api/fulcrum/controller.js +++ b/src/controllers/rest-api/fulcrum/controller.js @@ -87,6 +87,16 @@ class FulcrumRESTController { return cashAddr } + _isValidTxid (txid) { + return typeof txid === 'string' && /^[a-fA-F0-9]{64}$/.test(txid) + } + + _isCommonMissingTxError (err) { + return err?.status === 404 && + typeof err?.message === 'string' && + err.message.includes('Transaction not found') + } + /** * @api {get} /v6/fulcrum/balance/:address Get balance for a single address * @apiName GetBalance @@ -239,10 +249,10 @@ class FulcrumRESTController { try { const txid = req.params.txid - if (typeof txid !== 'string') { + if (!this._isValidTxid(txid)) { return res.status(400).json({ success: false, - error: 'txid must be a string' + error: 'txid must be a 64-character hex string' }) } @@ -424,7 +434,20 @@ class FulcrumRESTController { const cashAddr = this._validateAndConvertAddress(address) - const result = await this.fulcrumUseCases.getTransactions({ address: cashAddr, allTxs }) + // Extract bearer token from request header if present + let bearerToken = null + if (req.headers && req.headers.authorization) { + const parts = req.headers.authorization.split(' ') + if (parts.length === 2 && parts[0] === 'Bearer') { + bearerToken = parts[1] + } + } + + const result = await this.fulcrumUseCases.getTransactions({ + address: cashAddr, + allTxs, + bearerToken + }) return res.status(200).json(result) } catch (err) { return this.handleError(err, res) @@ -470,9 +493,19 @@ class FulcrumRESTController { } } + // Extract bearer token from request header if present + let bearerToken = null + if (req.headers && req.headers.authorization) { + const parts = req.headers.authorization.split(' ') + if (parts.length === 2 && parts[0] === 'Bearer') { + bearerToken = parts[1] + } + } + const result = await this.fulcrumUseCases.getTransactionsBulk({ addresses: validatedAddresses, - allTxs + allTxs, + bearerToken }) return res.status(200).json(result) } catch (err) { @@ -552,9 +585,17 @@ class FulcrumRESTController { } handleError (err, res) { - wlogger.error('Error in FulcrumRESTController:', err) - const status = err.status || 500 + const isCommonMissingTxError = this._isCommonMissingTxError(err) + + if (isCommonMissingTxError) { + wlogger.info(`Fulcrum transaction not found: ${err.message}`) + } else if (status >= 500) { + wlogger.error('Error in FulcrumRESTController:', err) + } else { + wlogger.warn(`Fulcrum client error (${status}): ${err.message}`) + } + const message = err.message || 'Internal server error' return res.status(status).json({ error: message }) diff --git a/src/controllers/rest-api/slp/controller.js b/src/controllers/rest-api/slp/controller.js index a5837e0..4698720 100644 --- a/src/controllers/rest-api/slp/controller.js +++ b/src/controllers/rest-api/slp/controller.js @@ -208,7 +208,14 @@ class SlpRESTController { } handleError (err, res) { - wlogger.error('Error in SlpRESTController:', err) + const isCommonMissingTxError = + err?.status === 404 && + typeof err?.message === 'string' && + err.message.includes('Key not found in database') + + if (!isCommonMissingTxError) { + wlogger.error('Error in SlpRESTController:', err) + } const status = err.status || 500 const message = err.message || 'Internal server error' diff --git a/src/use-cases/fulcrum-use-cases.js b/src/use-cases/fulcrum-use-cases.js index e019956..1a9c833 100644 --- a/src/use-cases/fulcrum-use-cases.js +++ b/src/use-cases/fulcrum-use-cases.js @@ -6,9 +6,14 @@ import wlogger from '../adapters/wlogger.js' import BCHJS from '@psf/bch-js' import config from '../config/index.js' +// Use RESTURL (from test) or REST_URL (from psf-bch-api config) or fallback to config +const restURL = process.env.RESTURL || process.env.REST_URL || process.env.LOCAL_RESTURL || config.restURL +// Use BCHJSBEARERTOKEN (from test) or BASIC_AUTH_TOKEN (from psf-bch-api config) or fallback to config +const bearerToken = process.env.BCHJSBEARERTOKEN || process.env.BASIC_AUTH_TOKEN || config.basicAuth.token + const bchjs = new BCHJS({ - restURL: config.restURL, - bearerToken: config.basicAuth.token + restURL, + bearerToken }) class FulcrumUseCases { @@ -57,14 +62,9 @@ class FulcrumUseCases { } async getTransactionDetails ({ txid }) { - try { - const response = await this.fulcrum.get(`electrumx/tx/data/${txid}`) - // console.log(`getTransactionDetails() TXID ${txid}: ${JSON.stringify(response, null, 2)}`) - return response - } catch (err) { - wlogger.error('Error in FulcrumUseCases.getTransactionDetails()', err) - throw err - } + const response = await this.fulcrum.get(`electrumx/tx/data/${txid}`) + // console.log(`getTransactionDetails() TXID ${txid}: ${JSON.stringify(response, null, 2)}`) + return response } async getTransactionDetailsBulk ({ txids, verbose }) { @@ -101,13 +101,24 @@ class FulcrumUseCases { } } - async getTransactions ({ address, allTxs }) { + async getTransactions ({ address, allTxs, bearerToken = null }) { try { const response = await this.fulcrum.get(`electrumx/transactions/${address}`) // Sort transactions in descending order, so that newest transactions are first. if (response.transactions && Array.isArray(response.transactions)) { - response.transactions = await this.bchjs.Electrumx.sortAllTxs(response.transactions, 'DESCENDING') + // Use bearer token from request if provided, otherwise use the default bchjs instance + let bchjsInstance = this.bchjs + if (bearerToken) { + // Create a temporary bchjs instance with the bearer token from the request + const restURL = process.env.RESTURL || process.env.REST_URL || process.env.LOCAL_RESTURL || config.restURL + bchjsInstance = new BCHJS({ + restURL, + bearerToken + }) + } + + response.transactions = await bchjsInstance.Electrumx.sortAllTxs(response.transactions, 'DESCENDING') if (!allTxs) { // Return only the first 100 transactions of the history. @@ -122,16 +133,31 @@ class FulcrumUseCases { } } - async getTransactionsBulk ({ addresses, allTxs }) { + async getTransactionsBulk ({ addresses, allTxs, bearerToken = null }) { try { const response = await this.fulcrum.post('electrumx/transactions/', { addresses }) // Sort transactions in descending order for each address entry. if (response.transactions && Array.isArray(response.transactions)) { + // Use bearer token from request if provided, otherwise use the default bchjs instance + let bchjsInstance = this.bchjs + + // console.log('getTransactionsBulk() bearerToken: ', bearerToken) + if (bearerToken) { + // Create a temporary bchjs instance with the bearer token from the request + const restURL = config.restURL + + // console.log('getTransactionsBulk() restURL: ', restURL) + bchjsInstance = new BCHJS({ + restURL, + bearerToken + }) + } + for (let i = 0; i < response.transactions.length; i++) { const thisEntry = response.transactions[i] if (thisEntry.transactions && Array.isArray(thisEntry.transactions)) { - thisEntry.transactions = await this.bchjs.Electrumx.sortAllTxs(thisEntry.transactions, 'DESCENDING') + thisEntry.transactions = await bchjsInstance.Electrumx.sortAllTxs(thisEntry.transactions, 'DESCENDING') if (!allTxs && thisEntry.transactions.length > 100) { // Extract only the first 100 transactions. diff --git a/src/use-cases/slp-use-cases.js b/src/use-cases/slp-use-cases.js index 406f7ce..f528f82 100644 --- a/src/use-cases/slp-use-cases.js +++ b/src/use-cases/slp-use-cases.js @@ -98,7 +98,14 @@ class SlpUseCases { try { return await this.slpIndexer.post('slp/tx/', { txid }) } catch (err) { - wlogger.error('Error in SlpUseCases.getTxid()', err) + const isCommonMissingTxError = + err?.status === 404 && + typeof err?.message === 'string' && + err.message.includes('Key not found in database') + + if (!isCommonMissingTxError) { + wlogger.error('Error in SlpUseCases.getTxid()', err) + } throw err } }