tantk commited on
Commit
dcf8b6b
Β·
verified Β·
1 Parent(s): c45ab3c

initial deploy: hardened mainnet build

Browse files
.env.example ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Network selection: "stellar:testnet" (default) or "stellar:public"
2
+ # Set to stellar:public for mainnet deployments
3
+ NETWORK=stellar:testnet
4
+
5
+ # Stellar public key to receive payments (starts with G...)
6
+ # Must match the network selected above
7
+ PAY_TO=
8
+
9
+ # Stellar secret key for the server β€” used to send refunds (starts with S...)
10
+ # Must match the network selected above; needs USDC trustline + small balance
11
+ SERVER_SECRET=
12
+
13
+ # Client's Stellar secret key β€” for demo-client.js only (starts with S...)
14
+ # Must match the network selected above
15
+ DEMO_PRIVATE_KEY=
16
+
17
+ # Optional: override x402 facilitator URL (default: https://www.x402.org/facilitator)
18
+ # FACILITATOR_URL=
.gitignore ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ node_modules/
2
+ .env
3
+ test_*.py
4
+ bench_*.py
5
+ __pycache__/
6
+ docs/superpowers/
7
+
8
+ # Tooling/agent CLI configs (local only)
9
+ .pi/
10
+ .qwen/
11
+
12
+ # One-off experiment scripts
13
+ test-obscura.sh
Dockerfile ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM node:22-slim
2
+
3
+ # Install Playwright system dependencies
4
+ RUN apt-get update && apt-get install -y \
5
+ libnss3 libatk1.0-0 libatk-bridge2.0-0 libcups2 libdrm2 \
6
+ libxkbcommon0 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 \
7
+ libgbm1 libpango-1.0-0 libcairo2 libasound2 libatspi2.0-0 \
8
+ fonts-liberation fonts-noto-color-emoji \
9
+ && rm -rf /var/lib/apt/lists/*
10
+
11
+ WORKDIR /app
12
+
13
+ COPY package.json package-lock.json ./
14
+ RUN npm ci --omit=dev
15
+
16
+ # Install Playwright Chromium as node user (matches runtime user)
17
+ USER node
18
+ RUN npx playwright install chromium
19
+
20
+ COPY --chown=node:node server.js renderer.js refund.js ./
21
+
22
+ ENV PORT=7860
23
+
24
+ EXPOSE 7860
25
+
26
+ CMD ["node", "server.js"]
README.md CHANGED
@@ -1,10 +1,281 @@
1
  ---
2
- title: Rendergate Mainnet
3
- emoji: πŸ¦€
4
- colorFrom: red
5
- colorTo: pink
6
  sdk: docker
7
- pinned: false
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: RenderGate
3
+ emoji: πŸ”
4
+ colorFrom: blue
5
+ colorTo: purple
6
  sdk: docker
7
+ app_port: 7860
8
  ---
9
 
10
+ # RenderGate
11
+
12
+ **Pay-per-render headless browser API, powered by x402 micropayments on Stellar.**
13
+
14
+ **Live service:** https://tantk-rendergate.hf.space
15
+
16
+ ## Why Agents Need This
17
+
18
+ Most AI agents are just HTTP clients β€” they call `fetch()` or `curl` and that's it. No browser engine, no JavaScript execution. When they hit a modern website, they get an empty HTML shell back.
19
+
20
+ This affects every major agent framework:
21
+ - **Claude Code** β€” `WebFetch` is HTTP GET only, no JS rendering
22
+ - **OpenAI Codex / GPT agents** β€” HTTP-based tools
23
+ - **LangChain / CrewAI agents** β€” Python `requests` library
24
+ - **Trading bots / arb agents** β€” lightweight scripts, no browser
25
+ - **MCP-based agents** β€” whatever tools they have, usually plain HTTP
26
+
27
+ **Why can't agents just install a browser?**
28
+ - Chromium is **500MB+** β€” too heavy for serverless, Lambda, or lightweight containers
29
+ - Needs system-level dependencies (`libnss3`, `libgbm`, etc.) β€” not a simple `npm install`
30
+ - Each render uses **200-500MB RAM** β€” agents on minimal infra can't afford this
31
+ - Browser management is complex β€” crashes, timeouts, memory leaks, concurrency
32
+
33
+ **RenderGate:** The agent pays $0.001 USDC and gets fully rendered content in one HTTP call. No browser install, no dependencies, no memory overhead. Heavy lifting happens on our infra. This is the x402 model β€” pay for compute you can't or don't want to run yourself.
34
+
35
+ ## How It Works
36
+
37
+ 1. Agent requests `GET /render?url=https://x.com/stellarorg`
38
+ 2. Server responds with **402 Payment Required** + Stellar payment instructions
39
+ 3. Agent signs a $0.001 USDC payment on Stellar testnet
40
+ 4. Server verifies payment via x402 facilitator, settles on-chain (~5s)
41
+ 5. Playwright renders the page with smart wait + scroll for lazy content
42
+ 6. Agent receives fully rendered content with title, text, and metadata
43
+
44
+ ## The Problem
45
+
46
+ ```
47
+ # Standard HTTP fetch on Twitter/X:
48
+ curl https://x.com/stellarorg
49
+ β†’ Empty SPA shell. No tweets. No content.
50
+
51
+ # RenderGate ($0.001 USDC on Stellar):
52
+ β†’ "Stellar @StellarOrg Β· 9,913 posts Β· 840K Followers"
53
+ β†’ "Meridian is headed to Lisbon. October 28–29."
54
+ β†’ "10 days until Stellar House. Who's joining us in CDMX?"
55
+ β†’ Full tweets, engagement metrics, retweets, quoted content
56
+ ```
57
+
58
+ ## Tested Sites
59
+
60
+ All tested against the live deployed service at `tantk-rendergate.hf.space` with real Stellar testnet payments. Every request is a verifiable on-chain transaction.
61
+
62
+ ### Social Media
63
+
64
+ | Site | Render Time | Result |
65
+ |------|-------------|--------|
66
+ | x.com (Twitter profiles) | 8-11s | Full tweets, bios, follower counts, engagement metrics, retweets |
67
+ | linkedin.com (company pages) | 5.7s | Full profile, about, employees, locations |
68
+ | tiktok.com (profiles) | 5.4s | Profile metadata, follower counts (video content needs login) |
69
+ | instagram.com | 3.7s | Login wall only |
70
+
71
+ ### Crypto Exchanges
72
+
73
+ | Site | Render Time | Result |
74
+ |------|-------------|--------|
75
+ | coinbase.com/price | 4.9s | Full price page, charts, market data (21K chars) |
76
+ | okx.com/price | 6.6s | Full price page, live data |
77
+ | kraken.com/prices | 7.5s | Full price page, history, about |
78
+ | binance.com/price | β€” | Blocked (bot protection) |
79
+
80
+ ### Crypto Analytics & Data
81
+
82
+ | Site | Render Time | Result |
83
+ |------|-------------|--------|
84
+ | coingecko.com | 8.9s | Full token page, price, market cap, charts (37K chars) |
85
+ | coinmarketcap.com | 6.0s | Full token page, rankings, data |
86
+ | defillama.com | 3.6s | TVL, fees, revenue, protocol rankings |
87
+ | dexscreener.com | 5.7s | Live pair data β€” price, volume, liquidity, buy/sell ratio |
88
+ | solscan.io | 4.4s | Solana explorer, analytics |
89
+ | etherscan.io | β€” | Blocked (Cloudflare challenge) |
90
+ | nansen.ai | 3.7s | Landing page content |
91
+ | messari.io | β€” | Blocked (Vercel security checkpoint) |
92
+
93
+ ### Crypto News
94
+
95
+ | Site | Render Time | Result |
96
+ |------|-------------|--------|
97
+ | cointelegraph.com | 4.2s | Headlines, prices, articles |
98
+ | decrypt.co | 4.0s | Full news feed, coin prices (14K chars) |
99
+ | blockworks.co | 7.4s | Analytics, prices, articles |
100
+ | theblock.co | 5.2s | News content (behind cookie wall) |
101
+ | medium.com (articles) | ~6s | Full articles (21K chars) β€” Cloudflare-blocked for normal fetch, works via RenderGate |
102
+
103
+ ### Stellar Ecosystem
104
+
105
+ | Site | Render Time | Result |
106
+ |------|-------------|--------|
107
+ | stellar.expert | 4.5s | Block explorer, network stats |
108
+ | stellarchain.io | 4.7s | Explorer, price, assets |
109
+ | dashboard.stellar.org | 4.4s | Live network status, stats (6.5K chars) |
110
+ | meridian.stellar.org | 7.2s | Conference details β€” Lisbon 2026 |
111
+ | stellarterm.com | 5.3s | DEX trading interface |
112
+ | stellarx.com | 5.4s | DEX, markets |
113
+ | lobstr.co | 4.2s | Wallet landing, trade features |
114
+ | soroswap.finance | 3.7s | Soroban DEX aggregator content |
115
+ | freighter.app | 3.2s | Wallet download page |
116
+ | scopuly.com | 6.3s | Full wallet/DEX interface |
117
+ | lumenswap.io | 3.6s | DEX landing page |
118
+
119
+ ### DeFi Apps
120
+
121
+ | Site | Render Time | Result |
122
+ |------|-------------|--------|
123
+ | app.uniswap.org | 7.3s | Live token prices, swap UI, TVL stats |
124
+ | aave.com | 3.4s | Full landing, product info |
125
+ | compound.finance | 3.1s | Market data, protocol stats |
126
+ | blur.io | 3.5s | NFT marketplace, collections, floor prices |
127
+
128
+ ### On-Chain Analytics
129
+
130
+ | Site | Render Time | Result |
131
+ |------|-------------|--------|
132
+ | tokenterminal.com | 5.1s | Stellar project page, metrics |
133
+ | artemis.xyz | 5.1s | Full analytics platform (26K chars) |
134
+ | flipsidecrypto.xyz | 3.9s | Data platform landing |
135
+
136
+ ### Developer Tools
137
+
138
+ | Site | Render Time | Result |
139
+ |------|-------------|--------|
140
+ | npmjs.com | 4.6s | Full package pages + README (Cloudflare-protected, works) |
141
+ | github.com (issues) | 6.3s | Full issue lists, content |
142
+ | dorahacks.io | 6.5s | Full SPA content β€” hackathon details, resources |
143
+
144
+ ### Blocked Sites
145
+
146
+ These sites block requests from data center IPs regardless of rendering β€” this is an IP reputation issue, not a rendering limitation.
147
+
148
+ | Site | Reason |
149
+ |------|--------|
150
+ | reddit.com | IP banned from HF's data center |
151
+ | producthunt.com | Cloudflare challenge |
152
+ | binance.com | Bot protection |
153
+ | etherscan.io | Cloudflare challenge |
154
+ | messari.io | Vercel security checkpoint |
155
+ | instagram.com | Requires login |
156
+
157
+ | opensea.io | Cloudflare challenge |
158
+ | dune.com | Cloudflare block |
159
+ | alchemy.com | Blocked |
160
+
161
+ Example transaction: [`5c898eb4...`](https://stellar.expert/explorer/testnet/tx/5c898eb489265c142baee086d502e25b87a5536e4386e5ccdf69edc2515c0ef6)
162
+
163
+ ## Using the Service
164
+
165
+ ### Option 1: MCP Tool (Claude Code, Codex, any MCP-compatible agent)
166
+
167
+ Add to your MCP config (`.mcp.json` or Claude Code settings):
168
+
169
+ ```json
170
+ {
171
+ "mcpServers": {
172
+ "rendergate": {
173
+ "command": "node",
174
+ "args": ["/path/to/rendergate/mcp-server.js"],
175
+ "env": {
176
+ "DEMO_PRIVATE_KEY": "S...your_testnet_secret_key...",
177
+ "RENDERGATE_URL": "https://tantk-rendergate.hf.space"
178
+ }
179
+ }
180
+ }
181
+ }
182
+ ```
183
+
184
+ Then the agent can simply call `render_page("https://x.com/stellarorg")` β€” payment happens transparently.
185
+
186
+ ### Option 2: x402 Fetch (any Node.js agent)
187
+
188
+ ```javascript
189
+ import { wrapFetchWithPayment } from "@x402/fetch";
190
+
191
+ const paidFetch = wrapFetchWithPayment(fetch, x402Client);
192
+ const response = await paidFetch(
193
+ "https://tantk-rendergate.hf.space/render?url=https://x.com/stellarorg"
194
+ );
195
+ const data = await response.json();
196
+ // { title, description, headings, links, content, renderTimeMs, payment }
197
+ ```
198
+
199
+ The agent just needs:
200
+ - `@x402/fetch` + `@x402/stellar` (npm packages)
201
+ - A Stellar wallet with USDC
202
+ - Our URL
203
+
204
+ ### Try It
205
+
206
+ `demo-client.js` is included to test the service end-to-end:
207
+
208
+ ```bash
209
+ npm install
210
+ cp .env.example .env
211
+ # Add your Stellar testnet secret key (DEMO_PRIVATE_KEY)
212
+ SERVER_URL=https://tantk-rendergate.hf.space node demo-client.js "https://x.com/stellarorg"
213
+ ```
214
+
215
+ You'll need a Stellar testnet wallet funded with USDC β€” generate one at [lab.stellar.org](https://lab.stellar.org/account/create), fund it, add a USDC trustline, and get testnet USDC from [faucet.circle.com](https://faucet.circle.com).
216
+
217
+ ## API
218
+
219
+ ### `GET /` (free)
220
+ Returns service info and usage instructions.
221
+
222
+ ### `GET /health` (free)
223
+ Health check.
224
+
225
+ ### `GET /render?url=<encoded_url>` (paid β€” $0.001 USDC)
226
+ Renders the URL with a headless browser and returns structured output:
227
+ ```json
228
+ {
229
+ "title": "Stellar (@StellarOrg) / X",
230
+ "description": "Meta description from the page",
231
+ "headings": [{ "level": "H1", "text": "Stellar's posts" }],
232
+ "links": [{ "text": "stellar.org", "href": "https://stellar.org" }],
233
+ "content": "Full rendered text content...",
234
+ "url": "https://x.com/stellarorg",
235
+ "renderedAt": "2026-04-13T06:59:12.395Z",
236
+ "renderTimeMs": 8071,
237
+ "payment": { "price": "$0.001", "network": "stellar:testnet" }
238
+ }
239
+ ```
240
+
241
+ If the page is blocked or empty, the payment is automatically refunded:
242
+ ```json
243
+ {
244
+ "title": "Just a moment...",
245
+ "content": "Cloudflare security verification...",
246
+ "refund": {
247
+ "transaction": "bf68b792...",
248
+ "amount": "0.001 USDC",
249
+ "reason": "blocked_page"
250
+ }
251
+ }
252
+ ```
253
+
254
+ ## Architecture
255
+
256
+ ```
257
+ Agent RenderGate Stellar
258
+ | | |
259
+ |--- GET /render?url= --->| |
260
+ |<-- 402 Payment Required -| |
261
+ | | |
262
+ |--- Sign USDC payment ---|------------------------->|
263
+ |--- GET + payment header->| |
264
+ | |--- verify via x402.org ->|
265
+ | |<-- settlement confirmed -|
266
+ | | |
267
+ | |--- Playwright render --->| (browser)
268
+ |<-- 200 + rendered JSON --| |
269
+ ```
270
+
271
+ ## Tech Stack
272
+
273
+ - **Payment:** x402 protocol on Stellar (USDC testnet)
274
+ - **Facilitator:** x402.org (OpenZeppelin-based, sponsored fees)
275
+ - **Rendering:** Playwright with Chromium (smart wait + scroll)
276
+ - **Server:** Express.js
277
+ - **Deployment:** Hugging Face Spaces (Docker)
278
+
279
+ ## Built For
280
+
281
+ [Stellar Hacks: Agents](https://dorahacks.io/hackathon/stellar-agents-x402-stripe-mpp) hackathon β€” exploring x402 micropayments for the agentic economy on Stellar.
demo-client.js ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import "dotenv/config";
2
+ import { Transaction, TransactionBuilder } from "@stellar/stellar-sdk";
3
+ import { x402Client, x402HTTPClient } from "@x402/fetch";
4
+ import { createEd25519Signer, getNetworkPassphrase } from "@x402/stellar";
5
+ import { ExactStellarScheme } from "@x402/stellar/exact/client";
6
+
7
+ const DEMO_PRIVATE_KEY = process.env.DEMO_PRIVATE_KEY;
8
+ const SERVER_URL = process.env.SERVER_URL || "http://localhost:3001";
9
+ const NETWORK = "stellar:testnet";
10
+ const STELLAR_RPC_URL = "https://soroban-testnet.stellar.org";
11
+
12
+ if (!DEMO_PRIVATE_KEY) {
13
+ console.error("ERROR: DEMO_PRIVATE_KEY not set in .env");
14
+ process.exit(1);
15
+ }
16
+
17
+ const targetUrl = process.argv[2] || "https://x.com/stellarorg";
18
+
19
+ async function main() {
20
+ const renderEndpoint = `${SERVER_URL}/render?url=${encodeURIComponent(targetUrl)}`;
21
+
22
+ // Setup x402 client
23
+ const signer = createEd25519Signer(DEMO_PRIVATE_KEY, NETWORK);
24
+ const rpcConfig = { url: STELLAR_RPC_URL };
25
+ const client = new x402Client().register(
26
+ "stellar:*",
27
+ new ExactStellarScheme(signer, rpcConfig),
28
+ );
29
+ const httpClient = new x402HTTPClient(client);
30
+
31
+ console.log(`Target URL: ${targetUrl}`);
32
+ console.log(`Render endpoint: ${renderEndpoint}`);
33
+ console.log(`Paying from: ${signer.address}`);
34
+
35
+ // Step 1: Request without payment β€” expect 402
36
+ console.log("\n--- Step 1: Request without payment ---");
37
+ const firstTry = await fetch(renderEndpoint);
38
+ console.log(`Response: ${firstTry.status} ${firstTry.statusText}`);
39
+
40
+ if (firstTry.status !== 402) {
41
+ console.log("No payment required! Response:", await firstTry.text());
42
+ return;
43
+ }
44
+
45
+ // Step 2: Extract payment requirements from 402 response
46
+ console.log("\n--- Step 2: Create payment ---");
47
+ const paymentRequired = httpClient.getPaymentRequiredResponse((name) =>
48
+ firstTry.headers.get(name),
49
+ );
50
+ console.log("Payment required:", JSON.stringify(paymentRequired, null, 2));
51
+
52
+ // Step 3: Create and configure payment payload
53
+ let paymentPayload = await client.createPaymentPayload(paymentRequired);
54
+ const networkPassphrase = getNetworkPassphrase(NETWORK);
55
+ const tx = new Transaction(
56
+ paymentPayload.payload.transaction,
57
+ networkPassphrase,
58
+ );
59
+ const sorobanData = tx.toEnvelope().v1()?.tx()?.ext()?.sorobanData();
60
+ if (sorobanData) {
61
+ paymentPayload = {
62
+ ...paymentPayload,
63
+ payload: {
64
+ ...paymentPayload.payload,
65
+ transaction: TransactionBuilder.cloneFrom(tx, {
66
+ fee: "1",
67
+ sorobanData,
68
+ networkPassphrase,
69
+ })
70
+ .build()
71
+ .toXDR(),
72
+ },
73
+ };
74
+ }
75
+
76
+ // Step 4: Send paid request
77
+ console.log("\n--- Step 3: Send paid request ---");
78
+ const paymentHeaders =
79
+ httpClient.encodePaymentSignatureHeader(paymentPayload);
80
+ const start = Date.now();
81
+ const paidResponse = await fetch(renderEndpoint, {
82
+ method: "GET",
83
+ headers: paymentHeaders,
84
+ });
85
+ const elapsed = Date.now() - start;
86
+
87
+ // Step 5: Show results
88
+ console.log(`\n--- Result (${elapsed}ms) ---`);
89
+ console.log(`Status: ${paidResponse.status}`);
90
+
91
+ const paymentResponse = httpClient.getPaymentSettleResponse((name) =>
92
+ paidResponse.headers.get(name),
93
+ );
94
+ if (paymentResponse) {
95
+ console.log("Settlement:", JSON.stringify(paymentResponse, null, 2));
96
+ }
97
+
98
+ const data = await paidResponse.json();
99
+ console.log(`\nTitle: ${data.title}`);
100
+ console.log(`Render time: ${data.renderTimeMs}ms`);
101
+ console.log(`Content length: ${data.content?.length} chars`);
102
+ console.log(`\nContent preview:\n${data.content?.substring(0, 600)}`);
103
+ }
104
+
105
+ main().catch((err) => {
106
+ console.error("Client error:", err);
107
+ process.exit(1);
108
+ });
mcp-server.js ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env node
2
+ import "dotenv/config";
3
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
+ import { z } from "zod";
6
+ import { Transaction, TransactionBuilder } from "@stellar/stellar-sdk";
7
+ import { x402Client, x402HTTPClient } from "@x402/fetch";
8
+ import { createEd25519Signer, getNetworkPassphrase } from "@x402/stellar";
9
+ import { ExactStellarScheme } from "@x402/stellar/exact/client";
10
+
11
+ const DEMO_PRIVATE_KEY = process.env.DEMO_PRIVATE_KEY;
12
+ const SERVER_URL = process.env.RENDERGATE_URL || "https://tantk-rendergate.hf.space";
13
+ const NETWORK = "stellar:testnet";
14
+ const STELLAR_RPC_URL = "https://soroban-testnet.stellar.org";
15
+
16
+ // Setup x402 payment client
17
+ let httpClient = null;
18
+ let client = null;
19
+
20
+ function getPaymentClient() {
21
+ if (!client && DEMO_PRIVATE_KEY) {
22
+ const signer = createEd25519Signer(DEMO_PRIVATE_KEY, NETWORK);
23
+ client = new x402Client().register(
24
+ "stellar:*",
25
+ new ExactStellarScheme(signer, { url: STELLAR_RPC_URL }),
26
+ );
27
+ httpClient = new x402HTTPClient(client);
28
+ }
29
+ return { client, httpClient };
30
+ }
31
+
32
+ async function paidRender(url) {
33
+ const { client, httpClient } = getPaymentClient();
34
+ if (!client) {
35
+ throw new Error("DEMO_PRIVATE_KEY not set β€” cannot make x402 payments");
36
+ }
37
+
38
+ const renderEndpoint = `${SERVER_URL}/render?url=${encodeURIComponent(url)}`;
39
+
40
+ // Step 1: Get 402 response
41
+ const firstTry = await fetch(renderEndpoint);
42
+ if (firstTry.status !== 402) {
43
+ return await firstTry.json();
44
+ }
45
+
46
+ // Step 2: Create payment
47
+ const paymentRequired = httpClient.getPaymentRequiredResponse((name) =>
48
+ firstTry.headers.get(name),
49
+ );
50
+
51
+ let paymentPayload = await client.createPaymentPayload(paymentRequired);
52
+ const networkPassphrase = getNetworkPassphrase(NETWORK);
53
+ const tx = new Transaction(
54
+ paymentPayload.payload.transaction,
55
+ networkPassphrase,
56
+ );
57
+ const sorobanData = tx.toEnvelope().v1()?.tx()?.ext()?.sorobanData();
58
+ if (sorobanData) {
59
+ paymentPayload = {
60
+ ...paymentPayload,
61
+ payload: {
62
+ ...paymentPayload.payload,
63
+ transaction: TransactionBuilder.cloneFrom(tx, {
64
+ fee: "1",
65
+ sorobanData,
66
+ networkPassphrase,
67
+ })
68
+ .build()
69
+ .toXDR(),
70
+ },
71
+ };
72
+ }
73
+
74
+ // Step 3: Send paid request
75
+ const headers = httpClient.encodePaymentSignatureHeader(paymentPayload);
76
+ const resp = await fetch(renderEndpoint, { method: "GET", headers });
77
+
78
+ if (!resp.ok) {
79
+ const text = await resp.text();
80
+ throw new Error(`Render failed (${resp.status}): ${text}`);
81
+ }
82
+
83
+ return await resp.json();
84
+ }
85
+
86
+ // Create MCP server
87
+ const server = new McpServer({
88
+ name: "rendergate",
89
+ version: "1.0.0",
90
+ });
91
+
92
+ server.tool(
93
+ "render_page",
94
+ "Render a JavaScript-heavy webpage using a headless browser. Pays $0.001 USDC on Stellar per request via x402. Use this when standard HTTP fetch returns empty content from SPAs, Twitter/X, LinkedIn, DeFi apps, or Cloudflare-protected sites.",
95
+ {
96
+ url: z.string().url().describe("The URL to render (must be public http/https)"),
97
+ },
98
+ async ({ url }) => {
99
+ try {
100
+ const result = await paidRender(url);
101
+ return {
102
+ content: [
103
+ {
104
+ type: "text",
105
+ text: `# ${result.title}\n\nURL: ${result.url}\nRendered: ${result.renderedAt}\nRender time: ${result.renderTimeMs}ms\nPayment: ${result.payment?.price} on ${result.payment?.network}${result.refund ? `\nRefund: ${result.refund.amount} β€” ${result.refund.reason} (tx: ${result.refund.transaction})` : ""}\n\n${result.content}`,
106
+ },
107
+ ],
108
+ };
109
+ } catch (err) {
110
+ return {
111
+ content: [{ type: "text", text: `Error: ${err.message}` }],
112
+ isError: true,
113
+ };
114
+ }
115
+ },
116
+ );
117
+
118
+ // Start
119
+ const transport = new StdioServerTransport();
120
+ await server.connect(transport);
network-config.js ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Network configuration. Reads NETWORK from env (default: stellar:testnet).
2
+ // Set NETWORK=stellar:public for mainnet deployments.
3
+ import { Networks } from "@stellar/stellar-sdk";
4
+
5
+ const NETWORKS = {
6
+ "stellar:testnet": {
7
+ network: "stellar:testnet",
8
+ passphrase: Networks.TESTNET,
9
+ horizonUrl: "https://horizon-testnet.stellar.org",
10
+ usdcIssuer: "GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5",
11
+ },
12
+ "stellar:public": {
13
+ network: "stellar:public",
14
+ passphrase: Networks.PUBLIC,
15
+ horizonUrl: "https://horizon.stellar.org",
16
+ usdcIssuer: "GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN",
17
+ },
18
+ };
19
+
20
+ const selected = process.env.NETWORK || "stellar:testnet";
21
+ if (!NETWORKS[selected]) {
22
+ throw new Error(
23
+ `Invalid NETWORK="${selected}". Must be "stellar:testnet" or "stellar:public".`,
24
+ );
25
+ }
26
+
27
+ export const NETWORK = NETWORKS[selected].network;
28
+ export const NETWORK_PASSPHRASE = NETWORKS[selected].passphrase;
29
+ export const HORIZON_URL = NETWORKS[selected].horizonUrl;
30
+ export const USDC_ISSUER = NETWORKS[selected].usdcIssuer;
31
+ export const FACILITATOR_URL =
32
+ process.env.FACILITATOR_URL || "https://www.x402.org/facilitator";
package-lock.json ADDED
@@ -0,0 +1,2344 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "rendergate",
3
+ "version": "1.0.0",
4
+ "lockfileVersion": 3,
5
+ "requires": true,
6
+ "packages": {
7
+ "": {
8
+ "name": "rendergate",
9
+ "version": "1.0.0",
10
+ "license": "MIT",
11
+ "dependencies": {
12
+ "@modelcontextprotocol/sdk": "^1.29.0",
13
+ "@stellar/stellar-sdk": "^15.0.1",
14
+ "@x402/core": "^2.9.0",
15
+ "@x402/express": "^2.9.0",
16
+ "@x402/fetch": "^2.9.0",
17
+ "@x402/stellar": "^2.9.0",
18
+ "dotenv": "^17.4.2",
19
+ "express": "^5.2.1",
20
+ "playwright": "^1.59.1"
21
+ },
22
+ "devDependencies": {
23
+ "@trionlabs/stellar8004": "^0.0.11"
24
+ }
25
+ },
26
+ "node_modules/@adraffy/ens-normalize": {
27
+ "version": "1.10.1",
28
+ "resolved": "https://registry.npmmirror.com/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz",
29
+ "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==",
30
+ "license": "MIT",
31
+ "peer": true
32
+ },
33
+ "node_modules/@hono/node-server": {
34
+ "version": "1.19.14",
35
+ "resolved": "https://registry.npmmirror.com/@hono/node-server/-/node-server-1.19.14.tgz",
36
+ "integrity": "sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==",
37
+ "license": "MIT",
38
+ "engines": {
39
+ "node": ">=18.14.1"
40
+ },
41
+ "peerDependencies": {
42
+ "hono": "^4"
43
+ }
44
+ },
45
+ "node_modules/@modelcontextprotocol/sdk": {
46
+ "version": "1.29.0",
47
+ "resolved": "https://registry.npmmirror.com/@modelcontextprotocol/sdk/-/sdk-1.29.0.tgz",
48
+ "integrity": "sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==",
49
+ "license": "MIT",
50
+ "dependencies": {
51
+ "@hono/node-server": "^1.19.9",
52
+ "ajv": "^8.17.1",
53
+ "ajv-formats": "^3.0.1",
54
+ "content-type": "^1.0.5",
55
+ "cors": "^2.8.5",
56
+ "cross-spawn": "^7.0.5",
57
+ "eventsource": "^3.0.2",
58
+ "eventsource-parser": "^3.0.0",
59
+ "express": "^5.2.1",
60
+ "express-rate-limit": "^8.2.1",
61
+ "hono": "^4.11.4",
62
+ "jose": "^6.1.3",
63
+ "json-schema-typed": "^8.0.2",
64
+ "pkce-challenge": "^5.0.0",
65
+ "raw-body": "^3.0.0",
66
+ "zod": "^3.25 || ^4.0",
67
+ "zod-to-json-schema": "^3.25.1"
68
+ },
69
+ "engines": {
70
+ "node": ">=18"
71
+ },
72
+ "peerDependencies": {
73
+ "@cfworker/json-schema": "^4.1.1",
74
+ "zod": "^3.25 || ^4.0"
75
+ },
76
+ "peerDependenciesMeta": {
77
+ "@cfworker/json-schema": {
78
+ "optional": true
79
+ },
80
+ "zod": {
81
+ "optional": false
82
+ }
83
+ }
84
+ },
85
+ "node_modules/@modelcontextprotocol/sdk/node_modules/eventsource": {
86
+ "version": "3.0.7",
87
+ "resolved": "https://registry.npmmirror.com/eventsource/-/eventsource-3.0.7.tgz",
88
+ "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==",
89
+ "license": "MIT",
90
+ "dependencies": {
91
+ "eventsource-parser": "^3.0.1"
92
+ },
93
+ "engines": {
94
+ "node": ">=18.0.0"
95
+ }
96
+ },
97
+ "node_modules/@modelcontextprotocol/sdk/node_modules/jose": {
98
+ "version": "6.2.2",
99
+ "resolved": "https://registry.npmmirror.com/jose/-/jose-6.2.2.tgz",
100
+ "integrity": "sha512-d7kPDd34KO/YnzaDOlikGpOurfF0ByC2sEV4cANCtdqLlTfBlw2p14O/5d/zv40gJPbIQxfES3nSx1/oYNyuZQ==",
101
+ "license": "MIT",
102
+ "funding": {
103
+ "url": "https://github.com/sponsors/panva"
104
+ }
105
+ },
106
+ "node_modules/@noble/ciphers": {
107
+ "version": "1.3.0",
108
+ "resolved": "https://registry.npmmirror.com/@noble/ciphers/-/ciphers-1.3.0.tgz",
109
+ "integrity": "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==",
110
+ "license": "MIT",
111
+ "engines": {
112
+ "node": "^14.21.3 || >=16"
113
+ },
114
+ "funding": {
115
+ "url": "https://paulmillr.com/funding/"
116
+ }
117
+ },
118
+ "node_modules/@noble/curves": {
119
+ "version": "1.9.7",
120
+ "resolved": "https://registry.npmmirror.com/@noble/curves/-/curves-1.9.7.tgz",
121
+ "integrity": "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==",
122
+ "license": "MIT",
123
+ "dependencies": {
124
+ "@noble/hashes": "1.8.0"
125
+ },
126
+ "engines": {
127
+ "node": "^14.21.3 || >=16"
128
+ },
129
+ "funding": {
130
+ "url": "https://paulmillr.com/funding/"
131
+ }
132
+ },
133
+ "node_modules/@noble/hashes": {
134
+ "version": "1.8.0",
135
+ "resolved": "https://registry.npmmirror.com/@noble/hashes/-/hashes-1.8.0.tgz",
136
+ "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
137
+ "license": "MIT",
138
+ "engines": {
139
+ "node": "^14.21.3 || >=16"
140
+ },
141
+ "funding": {
142
+ "url": "https://paulmillr.com/funding/"
143
+ }
144
+ },
145
+ "node_modules/@scure/base": {
146
+ "version": "1.2.6",
147
+ "resolved": "https://registry.npmmirror.com/@scure/base/-/base-1.2.6.tgz",
148
+ "integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==",
149
+ "license": "MIT",
150
+ "funding": {
151
+ "url": "https://paulmillr.com/funding/"
152
+ }
153
+ },
154
+ "node_modules/@scure/bip32": {
155
+ "version": "1.7.0",
156
+ "resolved": "https://registry.npmmirror.com/@scure/bip32/-/bip32-1.7.0.tgz",
157
+ "integrity": "sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==",
158
+ "license": "MIT",
159
+ "dependencies": {
160
+ "@noble/curves": "~1.9.0",
161
+ "@noble/hashes": "~1.8.0",
162
+ "@scure/base": "~1.2.5"
163
+ },
164
+ "funding": {
165
+ "url": "https://paulmillr.com/funding/"
166
+ }
167
+ },
168
+ "node_modules/@scure/bip39": {
169
+ "version": "1.6.0",
170
+ "resolved": "https://registry.npmmirror.com/@scure/bip39/-/bip39-1.6.0.tgz",
171
+ "integrity": "sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==",
172
+ "license": "MIT",
173
+ "dependencies": {
174
+ "@noble/hashes": "~1.8.0",
175
+ "@scure/base": "~1.2.5"
176
+ },
177
+ "funding": {
178
+ "url": "https://paulmillr.com/funding/"
179
+ }
180
+ },
181
+ "node_modules/@spruceid/siwe-parser": {
182
+ "version": "2.1.2",
183
+ "resolved": "https://registry.npmmirror.com/@spruceid/siwe-parser/-/siwe-parser-2.1.2.tgz",
184
+ "integrity": "sha512-d/r3S1LwJyMaRAKQ0awmo9whfXeE88Qt00vRj91q5uv5ATtWIQEGJ67Yr5eSZw5zp1/fZCXZYuEckt8lSkereQ==",
185
+ "license": "Apache-2.0",
186
+ "dependencies": {
187
+ "@noble/hashes": "^1.1.2",
188
+ "apg-js": "^4.3.0",
189
+ "uri-js": "^4.4.1",
190
+ "valid-url": "^1.0.9"
191
+ }
192
+ },
193
+ "node_modules/@stablelib/binary": {
194
+ "version": "1.0.1",
195
+ "resolved": "https://registry.npmmirror.com/@stablelib/binary/-/binary-1.0.1.tgz",
196
+ "integrity": "sha512-ClJWvmL6UBM/wjkvv/7m5VP3GMr9t0osr4yVgLZsLCOz4hGN9gIAFEqnJ0TsSMAN+n840nf2cHZnA5/KFqHC7Q==",
197
+ "license": "MIT",
198
+ "dependencies": {
199
+ "@stablelib/int": "^1.0.1"
200
+ }
201
+ },
202
+ "node_modules/@stablelib/int": {
203
+ "version": "1.0.1",
204
+ "resolved": "https://registry.npmmirror.com/@stablelib/int/-/int-1.0.1.tgz",
205
+ "integrity": "sha512-byr69X/sDtDiIjIV6m4roLVWnNNlRGzsvxw+agj8CIEazqWGOQp2dTYgQhtyVXV9wpO6WyXRQUzLV/JRNumT2w==",
206
+ "license": "MIT"
207
+ },
208
+ "node_modules/@stablelib/random": {
209
+ "version": "1.0.2",
210
+ "resolved": "https://registry.npmmirror.com/@stablelib/random/-/random-1.0.2.tgz",
211
+ "integrity": "sha512-rIsE83Xpb7clHPVRlBj8qNe5L8ISQOzjghYQm/dZ7VaM2KHYwMW5adjQjrzTZCchFnNCNhkwtnOBa9HTMJCI8w==",
212
+ "license": "MIT",
213
+ "dependencies": {
214
+ "@stablelib/binary": "^1.0.1",
215
+ "@stablelib/wipe": "^1.0.1"
216
+ }
217
+ },
218
+ "node_modules/@stablelib/wipe": {
219
+ "version": "1.0.1",
220
+ "resolved": "https://registry.npmmirror.com/@stablelib/wipe/-/wipe-1.0.1.tgz",
221
+ "integrity": "sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg==",
222
+ "license": "MIT"
223
+ },
224
+ "node_modules/@stellar/js-xdr": {
225
+ "version": "4.0.0",
226
+ "resolved": "https://registry.npmmirror.com/@stellar/js-xdr/-/js-xdr-4.0.0.tgz",
227
+ "integrity": "sha512-+NmNa7Tk5BI5XFdy/6xGTqAN4J9a9KgCrCGhj2uEUTCBhLkch0M+QbKzNH8zEnejWe0p8w+0q5hUVX6L3OzoVA==",
228
+ "license": "Apache-2.0",
229
+ "engines": {
230
+ "node": ">=20.0.0",
231
+ "pnpm": ">=9.0.0"
232
+ }
233
+ },
234
+ "node_modules/@stellar/stellar-base": {
235
+ "version": "15.0.0",
236
+ "resolved": "https://registry.npmmirror.com/@stellar/stellar-base/-/stellar-base-15.0.0.tgz",
237
+ "integrity": "sha512-XQhxUr9BYiEcFcgc4oWcCMR9QJCny/GmmGsuwPKf/ieIcOeb5149KLHYx9mJCA0ea8QbucR2/GzV58QbXOTxQA==",
238
+ "license": "Apache-2.0",
239
+ "dependencies": {
240
+ "@noble/curves": "^1.9.7",
241
+ "@stellar/js-xdr": "^4.0.0",
242
+ "base32.js": "^0.1.0",
243
+ "bignumber.js": "^9.3.1",
244
+ "buffer": "^6.0.3",
245
+ "sha.js": "^2.4.12"
246
+ },
247
+ "engines": {
248
+ "node": ">=20.0.0"
249
+ }
250
+ },
251
+ "node_modules/@stellar/stellar-sdk": {
252
+ "version": "15.0.1",
253
+ "resolved": "https://registry.npmmirror.com/@stellar/stellar-sdk/-/stellar-sdk-15.0.1.tgz",
254
+ "integrity": "sha512-iZjWKXtfohsPh+CX9wRyQNIlXLeA9VyuQB6UMC7AFBD9XnR92eOjnlfeONzk/Bsrkk6+UPlpzSy2MuF+ydHP1A==",
255
+ "license": "Apache-2.0",
256
+ "dependencies": {
257
+ "@stellar/stellar-base": "^15.0.0",
258
+ "axios": "1.14.0",
259
+ "bignumber.js": "^9.3.1",
260
+ "commander": "^14.0.3",
261
+ "eventsource": "^2.0.2",
262
+ "feaxios": "^0.0.23",
263
+ "randombytes": "^2.1.0",
264
+ "toml": "^3.0.0",
265
+ "urijs": "^1.19.11"
266
+ },
267
+ "bin": {
268
+ "stellar-js": "bin/stellar-js"
269
+ },
270
+ "engines": {
271
+ "node": ">=20.0.0"
272
+ }
273
+ },
274
+ "node_modules/@trionlabs/stellar8004": {
275
+ "version": "0.0.11",
276
+ "resolved": "https://registry.npmmirror.com/@trionlabs/stellar8004/-/stellar8004-0.0.11.tgz",
277
+ "integrity": "sha512-LWDhLXPfq1L6u11n10D+ALPmafK6pUCAuKUtVZbe+qi4BadQemPd5R4VvIKbqVqt6Meewn0Xu4ZG6CYFS8PoUA==",
278
+ "dev": true,
279
+ "license": "MIT",
280
+ "dependencies": {
281
+ "@stellar/stellar-sdk": "^15.0.0",
282
+ "buffer": "^6.0.3"
283
+ },
284
+ "engines": {
285
+ "node": ">=18.0.0"
286
+ },
287
+ "peerDependencies": {
288
+ "@stellar/freighter-api": ">=6.0.0"
289
+ },
290
+ "peerDependenciesMeta": {
291
+ "@stellar/freighter-api": {
292
+ "optional": true
293
+ }
294
+ }
295
+ },
296
+ "node_modules/@types/node": {
297
+ "version": "22.7.5",
298
+ "resolved": "https://registry.npmmirror.com/@types/node/-/node-22.7.5.tgz",
299
+ "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==",
300
+ "license": "MIT",
301
+ "peer": true,
302
+ "dependencies": {
303
+ "undici-types": "~6.19.2"
304
+ }
305
+ },
306
+ "node_modules/@x402/core": {
307
+ "version": "2.9.0",
308
+ "resolved": "https://registry.npmmirror.com/@x402/core/-/core-2.9.0.tgz",
309
+ "integrity": "sha512-IqPITHYx6XHlgLPtparuKKwoB+3wQdgt0F+WUH1e3WHMeiWdp+xTtQDy+6yOKuObNFI1S1iVbQFz0GivR/Vv3w==",
310
+ "license": "Apache-2.0",
311
+ "dependencies": {
312
+ "zod": "^3.24.2"
313
+ }
314
+ },
315
+ "node_modules/@x402/express": {
316
+ "version": "2.9.0",
317
+ "resolved": "https://registry.npmmirror.com/@x402/express/-/express-2.9.0.tgz",
318
+ "integrity": "sha512-E236c188p7rkAILnzdd19FQZuTEOM9+DP/y/FG4B0oawiBXx5FGR5ez7EUKCG7V7FxXsGvMEjUFMJ0BjrQx8yw==",
319
+ "license": "Apache-2.0",
320
+ "dependencies": {
321
+ "@x402/core": "~2.9.0",
322
+ "@x402/extensions": "~2.9.0",
323
+ "viem": "^2.39.3",
324
+ "zod": "^3.24.2"
325
+ },
326
+ "peerDependencies": {
327
+ "@x402/paywall": "^2.9.0",
328
+ "express": "^4.0.0 || ^5.0.0"
329
+ },
330
+ "peerDependenciesMeta": {
331
+ "@x402/paywall": {
332
+ "optional": true
333
+ }
334
+ }
335
+ },
336
+ "node_modules/@x402/extensions": {
337
+ "version": "2.9.0",
338
+ "resolved": "https://registry.npmmirror.com/@x402/extensions/-/extensions-2.9.0.tgz",
339
+ "integrity": "sha512-Fk7MJFWSQtsRGGZcNpgwv8V6IG38USNciA5ImkF0InceWDfjMBq6b8GmksM+cVHAXQsMQYxw3HV8uhfwTPEGAQ==",
340
+ "license": "Apache-2.0",
341
+ "dependencies": {
342
+ "@noble/curves": "^1.9.0",
343
+ "@scure/base": "^1.2.6",
344
+ "@x402/core": "~2.9.0",
345
+ "ajv": "^8.17.1",
346
+ "jose": "^5.9.6",
347
+ "siwe": "^2.3.2",
348
+ "tweetnacl": "^1.0.3",
349
+ "viem": "^2.43.5",
350
+ "zod": "^3.24.2"
351
+ }
352
+ },
353
+ "node_modules/@x402/fetch": {
354
+ "version": "2.9.0",
355
+ "resolved": "https://registry.npmmirror.com/@x402/fetch/-/fetch-2.9.0.tgz",
356
+ "integrity": "sha512-/ocFWG5aTftCabW4CWXLZjafzTwkmW+c7u4lzXLegJ7F8Fkciw6yyzrQ+R4Rsm6F6TH0pGzo545Yc7n7z5UNlA==",
357
+ "license": "Apache-2.0",
358
+ "dependencies": {
359
+ "@x402/core": "~2.9.0",
360
+ "viem": "^2.39.3",
361
+ "zod": "^3.24.2"
362
+ }
363
+ },
364
+ "node_modules/@x402/stellar": {
365
+ "version": "2.9.0",
366
+ "resolved": "https://registry.npmmirror.com/@x402/stellar/-/stellar-2.9.0.tgz",
367
+ "integrity": "sha512-VZ77WugghMuSeCsvDpK4cKt5OyDXqAnH2IPBG/FbAvwAkOyhPCPHWK/Q33NbqKDIyV8W2xB/vg12Nj7UMp/qRQ==",
368
+ "license": "Apache-2.0",
369
+ "dependencies": {
370
+ "@stellar/stellar-sdk": "^14.6.1",
371
+ "@x402/core": "2.9.0"
372
+ }
373
+ },
374
+ "node_modules/@x402/stellar/node_modules/@stellar/js-xdr": {
375
+ "version": "3.1.2",
376
+ "resolved": "https://registry.npmmirror.com/@stellar/js-xdr/-/js-xdr-3.1.2.tgz",
377
+ "integrity": "sha512-VVolPL5goVEIsvuGqDc5uiKxV03lzfWdvYg1KikvwheDmTBO68CKDji3bAZ/kppZrx5iTA8z3Ld5yuytcvhvOQ==",
378
+ "license": "Apache-2.0"
379
+ },
380
+ "node_modules/@x402/stellar/node_modules/@stellar/stellar-base": {
381
+ "version": "14.1.0",
382
+ "resolved": "https://registry.npmmirror.com/@stellar/stellar-base/-/stellar-base-14.1.0.tgz",
383
+ "integrity": "sha512-A8kFli6QGy22SRF45IjgPAJfUNGjnI+R7g4DF5NZYVsD1kGf7B4ITyc4OPclLV9tqNI4/lXxafGEw0JEUbHixw==",
384
+ "license": "Apache-2.0",
385
+ "dependencies": {
386
+ "@noble/curves": "^1.9.6",
387
+ "@stellar/js-xdr": "^3.1.2",
388
+ "base32.js": "^0.1.0",
389
+ "bignumber.js": "^9.3.1",
390
+ "buffer": "^6.0.3",
391
+ "sha.js": "^2.4.12"
392
+ },
393
+ "engines": {
394
+ "node": ">=20.0.0"
395
+ }
396
+ },
397
+ "node_modules/@x402/stellar/node_modules/@stellar/stellar-sdk": {
398
+ "version": "14.6.1",
399
+ "resolved": "https://registry.npmmirror.com/@stellar/stellar-sdk/-/stellar-sdk-14.6.1.tgz",
400
+ "integrity": "sha512-A1rQWDLdUasXkMXnYSuhgep+3ZZzyuXJKdt5/KAIc0gkmSp906HTvUpbT4pu+bVr41tu0+J4Ugz9J4BQAGGytg==",
401
+ "license": "Apache-2.0",
402
+ "dependencies": {
403
+ "@stellar/stellar-base": "^14.1.0",
404
+ "axios": "^1.13.3",
405
+ "bignumber.js": "^9.3.1",
406
+ "commander": "^14.0.2",
407
+ "eventsource": "^2.0.2",
408
+ "feaxios": "^0.0.23",
409
+ "randombytes": "^2.1.0",
410
+ "toml": "^3.0.0",
411
+ "urijs": "^1.19.1"
412
+ },
413
+ "bin": {
414
+ "stellar-js": "bin/stellar-js"
415
+ },
416
+ "engines": {
417
+ "node": ">=20.0.0"
418
+ }
419
+ },
420
+ "node_modules/abitype": {
421
+ "version": "1.2.3",
422
+ "resolved": "https://registry.npmmirror.com/abitype/-/abitype-1.2.3.tgz",
423
+ "integrity": "sha512-Ofer5QUnuUdTFsBRwARMoWKOH1ND5ehwYhJ3OJ/BQO+StkwQjHw0XyVh4vDttzHB7QOFhPHa/o413PJ82gU/Tg==",
424
+ "license": "MIT",
425
+ "funding": {
426
+ "url": "https://github.com/sponsors/wevm"
427
+ },
428
+ "peerDependencies": {
429
+ "typescript": ">=5.0.4",
430
+ "zod": "^3.22.0 || ^4.0.0"
431
+ },
432
+ "peerDependenciesMeta": {
433
+ "typescript": {
434
+ "optional": true
435
+ },
436
+ "zod": {
437
+ "optional": true
438
+ }
439
+ }
440
+ },
441
+ "node_modules/accepts": {
442
+ "version": "2.0.0",
443
+ "resolved": "https://registry.npmmirror.com/accepts/-/accepts-2.0.0.tgz",
444
+ "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
445
+ "license": "MIT",
446
+ "dependencies": {
447
+ "mime-types": "^3.0.0",
448
+ "negotiator": "^1.0.0"
449
+ },
450
+ "engines": {
451
+ "node": ">= 0.6"
452
+ }
453
+ },
454
+ "node_modules/aes-js": {
455
+ "version": "4.0.0-beta.5",
456
+ "resolved": "https://registry.npmmirror.com/aes-js/-/aes-js-4.0.0-beta.5.tgz",
457
+ "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==",
458
+ "license": "MIT",
459
+ "peer": true
460
+ },
461
+ "node_modules/ajv": {
462
+ "version": "8.18.0",
463
+ "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.18.0.tgz",
464
+ "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
465
+ "license": "MIT",
466
+ "dependencies": {
467
+ "fast-deep-equal": "^3.1.3",
468
+ "fast-uri": "^3.0.1",
469
+ "json-schema-traverse": "^1.0.0",
470
+ "require-from-string": "^2.0.2"
471
+ },
472
+ "funding": {
473
+ "type": "github",
474
+ "url": "https://github.com/sponsors/epoberezkin"
475
+ }
476
+ },
477
+ "node_modules/ajv-formats": {
478
+ "version": "3.0.1",
479
+ "resolved": "https://registry.npmmirror.com/ajv-formats/-/ajv-formats-3.0.1.tgz",
480
+ "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==",
481
+ "license": "MIT",
482
+ "dependencies": {
483
+ "ajv": "^8.0.0"
484
+ },
485
+ "peerDependencies": {
486
+ "ajv": "^8.0.0"
487
+ },
488
+ "peerDependenciesMeta": {
489
+ "ajv": {
490
+ "optional": true
491
+ }
492
+ }
493
+ },
494
+ "node_modules/apg-js": {
495
+ "version": "4.4.0",
496
+ "resolved": "https://registry.npmmirror.com/apg-js/-/apg-js-4.4.0.tgz",
497
+ "integrity": "sha512-fefmXFknJmtgtNEXfPwZKYkMFX4Fyeyz+fNF6JWp87biGOPslJbCBVU158zvKRZfHBKnJDy8CMM40oLFGkXT8Q==",
498
+ "license": "BSD-2-Clause"
499
+ },
500
+ "node_modules/asynckit": {
501
+ "version": "0.4.0",
502
+ "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
503
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
504
+ "license": "MIT"
505
+ },
506
+ "node_modules/available-typed-arrays": {
507
+ "version": "1.0.7",
508
+ "resolved": "https://registry.npmmirror.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
509
+ "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
510
+ "license": "MIT",
511
+ "dependencies": {
512
+ "possible-typed-array-names": "^1.0.0"
513
+ },
514
+ "engines": {
515
+ "node": ">= 0.4"
516
+ },
517
+ "funding": {
518
+ "url": "https://github.com/sponsors/ljharb"
519
+ }
520
+ },
521
+ "node_modules/axios": {
522
+ "version": "1.14.0",
523
+ "resolved": "https://registry.npmmirror.com/axios/-/axios-1.14.0.tgz",
524
+ "integrity": "sha512-3Y8yrqLSwjuzpXuZ0oIYZ/XGgLwUIBU3uLvbcpb0pidD9ctpShJd43KSlEEkVQg6DS0G9NKyzOvBfUtDKEyHvQ==",
525
+ "license": "MIT",
526
+ "dependencies": {
527
+ "follow-redirects": "^1.15.11",
528
+ "form-data": "^4.0.5",
529
+ "proxy-from-env": "^2.1.0"
530
+ }
531
+ },
532
+ "node_modules/base32.js": {
533
+ "version": "0.1.0",
534
+ "resolved": "https://registry.npmmirror.com/base32.js/-/base32.js-0.1.0.tgz",
535
+ "integrity": "sha512-n3TkB02ixgBOhTvANakDb4xaMXnYUVkNoRFJjQflcqMQhyEKxEHdj3E6N8t8sUQ0mjH/3/JxzlXuz3ul/J90pQ==",
536
+ "license": "MIT",
537
+ "engines": {
538
+ "node": ">=0.12.0"
539
+ }
540
+ },
541
+ "node_modules/base64-js": {
542
+ "version": "1.5.1",
543
+ "resolved": "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz",
544
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
545
+ "funding": [
546
+ {
547
+ "type": "github",
548
+ "url": "https://github.com/sponsors/feross"
549
+ },
550
+ {
551
+ "type": "patreon",
552
+ "url": "https://www.patreon.com/feross"
553
+ },
554
+ {
555
+ "type": "consulting",
556
+ "url": "https://feross.org/support"
557
+ }
558
+ ],
559
+ "license": "MIT"
560
+ },
561
+ "node_modules/bignumber.js": {
562
+ "version": "9.3.1",
563
+ "resolved": "https://registry.npmmirror.com/bignumber.js/-/bignumber.js-9.3.1.tgz",
564
+ "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==",
565
+ "license": "MIT",
566
+ "engines": {
567
+ "node": "*"
568
+ }
569
+ },
570
+ "node_modules/body-parser": {
571
+ "version": "2.2.2",
572
+ "resolved": "https://registry.npmmirror.com/body-parser/-/body-parser-2.2.2.tgz",
573
+ "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==",
574
+ "license": "MIT",
575
+ "dependencies": {
576
+ "bytes": "^3.1.2",
577
+ "content-type": "^1.0.5",
578
+ "debug": "^4.4.3",
579
+ "http-errors": "^2.0.0",
580
+ "iconv-lite": "^0.7.0",
581
+ "on-finished": "^2.4.1",
582
+ "qs": "^6.14.1",
583
+ "raw-body": "^3.0.1",
584
+ "type-is": "^2.0.1"
585
+ },
586
+ "engines": {
587
+ "node": ">=18"
588
+ },
589
+ "funding": {
590
+ "type": "opencollective",
591
+ "url": "https://opencollective.com/express"
592
+ }
593
+ },
594
+ "node_modules/buffer": {
595
+ "version": "6.0.3",
596
+ "resolved": "https://registry.npmmirror.com/buffer/-/buffer-6.0.3.tgz",
597
+ "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
598
+ "funding": [
599
+ {
600
+ "type": "github",
601
+ "url": "https://github.com/sponsors/feross"
602
+ },
603
+ {
604
+ "type": "patreon",
605
+ "url": "https://www.patreon.com/feross"
606
+ },
607
+ {
608
+ "type": "consulting",
609
+ "url": "https://feross.org/support"
610
+ }
611
+ ],
612
+ "license": "MIT",
613
+ "dependencies": {
614
+ "base64-js": "^1.3.1",
615
+ "ieee754": "^1.2.1"
616
+ }
617
+ },
618
+ "node_modules/bytes": {
619
+ "version": "3.1.2",
620
+ "resolved": "https://registry.npmmirror.com/bytes/-/bytes-3.1.2.tgz",
621
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
622
+ "license": "MIT",
623
+ "engines": {
624
+ "node": ">= 0.8"
625
+ }
626
+ },
627
+ "node_modules/call-bind": {
628
+ "version": "1.0.9",
629
+ "resolved": "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.9.tgz",
630
+ "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==",
631
+ "license": "MIT",
632
+ "dependencies": {
633
+ "call-bind-apply-helpers": "^1.0.2",
634
+ "es-define-property": "^1.0.1",
635
+ "get-intrinsic": "^1.3.0",
636
+ "set-function-length": "^1.2.2"
637
+ },
638
+ "engines": {
639
+ "node": ">= 0.4"
640
+ },
641
+ "funding": {
642
+ "url": "https://github.com/sponsors/ljharb"
643
+ }
644
+ },
645
+ "node_modules/call-bind-apply-helpers": {
646
+ "version": "1.0.2",
647
+ "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
648
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
649
+ "license": "MIT",
650
+ "dependencies": {
651
+ "es-errors": "^1.3.0",
652
+ "function-bind": "^1.1.2"
653
+ },
654
+ "engines": {
655
+ "node": ">= 0.4"
656
+ }
657
+ },
658
+ "node_modules/call-bound": {
659
+ "version": "1.0.4",
660
+ "resolved": "https://registry.npmmirror.com/call-bound/-/call-bound-1.0.4.tgz",
661
+ "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
662
+ "license": "MIT",
663
+ "dependencies": {
664
+ "call-bind-apply-helpers": "^1.0.2",
665
+ "get-intrinsic": "^1.3.0"
666
+ },
667
+ "engines": {
668
+ "node": ">= 0.4"
669
+ },
670
+ "funding": {
671
+ "url": "https://github.com/sponsors/ljharb"
672
+ }
673
+ },
674
+ "node_modules/combined-stream": {
675
+ "version": "1.0.8",
676
+ "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
677
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
678
+ "license": "MIT",
679
+ "dependencies": {
680
+ "delayed-stream": "~1.0.0"
681
+ },
682
+ "engines": {
683
+ "node": ">= 0.8"
684
+ }
685
+ },
686
+ "node_modules/commander": {
687
+ "version": "14.0.3",
688
+ "resolved": "https://registry.npmmirror.com/commander/-/commander-14.0.3.tgz",
689
+ "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==",
690
+ "license": "MIT",
691
+ "engines": {
692
+ "node": ">=20"
693
+ }
694
+ },
695
+ "node_modules/content-disposition": {
696
+ "version": "1.1.0",
697
+ "resolved": "https://registry.npmmirror.com/content-disposition/-/content-disposition-1.1.0.tgz",
698
+ "integrity": "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==",
699
+ "license": "MIT",
700
+ "engines": {
701
+ "node": ">=18"
702
+ },
703
+ "funding": {
704
+ "type": "opencollective",
705
+ "url": "https://opencollective.com/express"
706
+ }
707
+ },
708
+ "node_modules/content-type": {
709
+ "version": "1.0.5",
710
+ "resolved": "https://registry.npmmirror.com/content-type/-/content-type-1.0.5.tgz",
711
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
712
+ "license": "MIT",
713
+ "engines": {
714
+ "node": ">= 0.6"
715
+ }
716
+ },
717
+ "node_modules/cookie": {
718
+ "version": "0.7.2",
719
+ "resolved": "https://registry.npmmirror.com/cookie/-/cookie-0.7.2.tgz",
720
+ "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
721
+ "license": "MIT",
722
+ "engines": {
723
+ "node": ">= 0.6"
724
+ }
725
+ },
726
+ "node_modules/cookie-signature": {
727
+ "version": "1.2.2",
728
+ "resolved": "https://registry.npmmirror.com/cookie-signature/-/cookie-signature-1.2.2.tgz",
729
+ "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
730
+ "license": "MIT",
731
+ "engines": {
732
+ "node": ">=6.6.0"
733
+ }
734
+ },
735
+ "node_modules/cors": {
736
+ "version": "2.8.6",
737
+ "resolved": "https://registry.npmmirror.com/cors/-/cors-2.8.6.tgz",
738
+ "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==",
739
+ "license": "MIT",
740
+ "dependencies": {
741
+ "object-assign": "^4",
742
+ "vary": "^1"
743
+ },
744
+ "engines": {
745
+ "node": ">= 0.10"
746
+ },
747
+ "funding": {
748
+ "type": "opencollective",
749
+ "url": "https://opencollective.com/express"
750
+ }
751
+ },
752
+ "node_modules/cross-spawn": {
753
+ "version": "7.0.6",
754
+ "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.6.tgz",
755
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
756
+ "license": "MIT",
757
+ "dependencies": {
758
+ "path-key": "^3.1.0",
759
+ "shebang-command": "^2.0.0",
760
+ "which": "^2.0.1"
761
+ },
762
+ "engines": {
763
+ "node": ">= 8"
764
+ }
765
+ },
766
+ "node_modules/debug": {
767
+ "version": "4.4.3",
768
+ "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz",
769
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
770
+ "license": "MIT",
771
+ "dependencies": {
772
+ "ms": "^2.1.3"
773
+ },
774
+ "engines": {
775
+ "node": ">=6.0"
776
+ },
777
+ "peerDependenciesMeta": {
778
+ "supports-color": {
779
+ "optional": true
780
+ }
781
+ }
782
+ },
783
+ "node_modules/define-data-property": {
784
+ "version": "1.1.4",
785
+ "resolved": "https://registry.npmmirror.com/define-data-property/-/define-data-property-1.1.4.tgz",
786
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
787
+ "license": "MIT",
788
+ "dependencies": {
789
+ "es-define-property": "^1.0.0",
790
+ "es-errors": "^1.3.0",
791
+ "gopd": "^1.0.1"
792
+ },
793
+ "engines": {
794
+ "node": ">= 0.4"
795
+ },
796
+ "funding": {
797
+ "url": "https://github.com/sponsors/ljharb"
798
+ }
799
+ },
800
+ "node_modules/delayed-stream": {
801
+ "version": "1.0.0",
802
+ "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
803
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
804
+ "license": "MIT",
805
+ "engines": {
806
+ "node": ">=0.4.0"
807
+ }
808
+ },
809
+ "node_modules/depd": {
810
+ "version": "2.0.0",
811
+ "resolved": "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz",
812
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
813
+ "license": "MIT",
814
+ "engines": {
815
+ "node": ">= 0.8"
816
+ }
817
+ },
818
+ "node_modules/dotenv": {
819
+ "version": "17.4.2",
820
+ "resolved": "https://registry.npmmirror.com/dotenv/-/dotenv-17.4.2.tgz",
821
+ "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==",
822
+ "license": "BSD-2-Clause",
823
+ "engines": {
824
+ "node": ">=12"
825
+ },
826
+ "funding": {
827
+ "url": "https://dotenvx.com"
828
+ }
829
+ },
830
+ "node_modules/dunder-proto": {
831
+ "version": "1.0.1",
832
+ "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz",
833
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
834
+ "license": "MIT",
835
+ "dependencies": {
836
+ "call-bind-apply-helpers": "^1.0.1",
837
+ "es-errors": "^1.3.0",
838
+ "gopd": "^1.2.0"
839
+ },
840
+ "engines": {
841
+ "node": ">= 0.4"
842
+ }
843
+ },
844
+ "node_modules/ee-first": {
845
+ "version": "1.1.1",
846
+ "resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz",
847
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
848
+ "license": "MIT"
849
+ },
850
+ "node_modules/encodeurl": {
851
+ "version": "2.0.0",
852
+ "resolved": "https://registry.npmmirror.com/encodeurl/-/encodeurl-2.0.0.tgz",
853
+ "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
854
+ "license": "MIT",
855
+ "engines": {
856
+ "node": ">= 0.8"
857
+ }
858
+ },
859
+ "node_modules/es-define-property": {
860
+ "version": "1.0.1",
861
+ "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz",
862
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
863
+ "license": "MIT",
864
+ "engines": {
865
+ "node": ">= 0.4"
866
+ }
867
+ },
868
+ "node_modules/es-errors": {
869
+ "version": "1.3.0",
870
+ "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz",
871
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
872
+ "license": "MIT",
873
+ "engines": {
874
+ "node": ">= 0.4"
875
+ }
876
+ },
877
+ "node_modules/es-object-atoms": {
878
+ "version": "1.1.1",
879
+ "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
880
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
881
+ "license": "MIT",
882
+ "dependencies": {
883
+ "es-errors": "^1.3.0"
884
+ },
885
+ "engines": {
886
+ "node": ">= 0.4"
887
+ }
888
+ },
889
+ "node_modules/es-set-tostringtag": {
890
+ "version": "2.1.0",
891
+ "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
892
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
893
+ "license": "MIT",
894
+ "dependencies": {
895
+ "es-errors": "^1.3.0",
896
+ "get-intrinsic": "^1.2.6",
897
+ "has-tostringtag": "^1.0.2",
898
+ "hasown": "^2.0.2"
899
+ },
900
+ "engines": {
901
+ "node": ">= 0.4"
902
+ }
903
+ },
904
+ "node_modules/escape-html": {
905
+ "version": "1.0.3",
906
+ "resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz",
907
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
908
+ "license": "MIT"
909
+ },
910
+ "node_modules/etag": {
911
+ "version": "1.8.1",
912
+ "resolved": "https://registry.npmmirror.com/etag/-/etag-1.8.1.tgz",
913
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
914
+ "license": "MIT",
915
+ "engines": {
916
+ "node": ">= 0.6"
917
+ }
918
+ },
919
+ "node_modules/ethers": {
920
+ "version": "6.16.0",
921
+ "resolved": "https://registry.npmmirror.com/ethers/-/ethers-6.16.0.tgz",
922
+ "integrity": "sha512-U1wulmetNymijEhpSEQ7Ct/P/Jw9/e7R1j5XIbPRydgV2DjLVMsULDlNksq3RQnFgKoLlZf88ijYtWEXcPa07A==",
923
+ "funding": [
924
+ {
925
+ "type": "individual",
926
+ "url": "https://github.com/sponsors/ethers-io/"
927
+ },
928
+ {
929
+ "type": "individual",
930
+ "url": "https://www.buymeacoffee.com/ricmoo"
931
+ }
932
+ ],
933
+ "license": "MIT",
934
+ "peer": true,
935
+ "dependencies": {
936
+ "@adraffy/ens-normalize": "1.10.1",
937
+ "@noble/curves": "1.2.0",
938
+ "@noble/hashes": "1.3.2",
939
+ "@types/node": "22.7.5",
940
+ "aes-js": "4.0.0-beta.5",
941
+ "tslib": "2.7.0",
942
+ "ws": "8.17.1"
943
+ },
944
+ "engines": {
945
+ "node": ">=14.0.0"
946
+ }
947
+ },
948
+ "node_modules/ethers/node_modules/@noble/curves": {
949
+ "version": "1.2.0",
950
+ "resolved": "https://registry.npmmirror.com/@noble/curves/-/curves-1.2.0.tgz",
951
+ "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==",
952
+ "license": "MIT",
953
+ "peer": true,
954
+ "dependencies": {
955
+ "@noble/hashes": "1.3.2"
956
+ },
957
+ "funding": {
958
+ "url": "https://paulmillr.com/funding/"
959
+ }
960
+ },
961
+ "node_modules/ethers/node_modules/@noble/hashes": {
962
+ "version": "1.3.2",
963
+ "resolved": "https://registry.npmmirror.com/@noble/hashes/-/hashes-1.3.2.tgz",
964
+ "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==",
965
+ "license": "MIT",
966
+ "peer": true,
967
+ "engines": {
968
+ "node": ">= 16"
969
+ },
970
+ "funding": {
971
+ "url": "https://paulmillr.com/funding/"
972
+ }
973
+ },
974
+ "node_modules/eventemitter3": {
975
+ "version": "5.0.1",
976
+ "resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-5.0.1.tgz",
977
+ "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
978
+ "license": "MIT"
979
+ },
980
+ "node_modules/eventsource": {
981
+ "version": "2.0.2",
982
+ "resolved": "https://registry.npmmirror.com/eventsource/-/eventsource-2.0.2.tgz",
983
+ "integrity": "sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==",
984
+ "license": "MIT",
985
+ "engines": {
986
+ "node": ">=12.0.0"
987
+ }
988
+ },
989
+ "node_modules/eventsource-parser": {
990
+ "version": "3.0.6",
991
+ "resolved": "https://registry.npmmirror.com/eventsource-parser/-/eventsource-parser-3.0.6.tgz",
992
+ "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==",
993
+ "license": "MIT",
994
+ "engines": {
995
+ "node": ">=18.0.0"
996
+ }
997
+ },
998
+ "node_modules/express": {
999
+ "version": "5.2.1",
1000
+ "resolved": "https://registry.npmmirror.com/express/-/express-5.2.1.tgz",
1001
+ "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==",
1002
+ "license": "MIT",
1003
+ "dependencies": {
1004
+ "accepts": "^2.0.0",
1005
+ "body-parser": "^2.2.1",
1006
+ "content-disposition": "^1.0.0",
1007
+ "content-type": "^1.0.5",
1008
+ "cookie": "^0.7.1",
1009
+ "cookie-signature": "^1.2.1",
1010
+ "debug": "^4.4.0",
1011
+ "depd": "^2.0.0",
1012
+ "encodeurl": "^2.0.0",
1013
+ "escape-html": "^1.0.3",
1014
+ "etag": "^1.8.1",
1015
+ "finalhandler": "^2.1.0",
1016
+ "fresh": "^2.0.0",
1017
+ "http-errors": "^2.0.0",
1018
+ "merge-descriptors": "^2.0.0",
1019
+ "mime-types": "^3.0.0",
1020
+ "on-finished": "^2.4.1",
1021
+ "once": "^1.4.0",
1022
+ "parseurl": "^1.3.3",
1023
+ "proxy-addr": "^2.0.7",
1024
+ "qs": "^6.14.0",
1025
+ "range-parser": "^1.2.1",
1026
+ "router": "^2.2.0",
1027
+ "send": "^1.1.0",
1028
+ "serve-static": "^2.2.0",
1029
+ "statuses": "^2.0.1",
1030
+ "type-is": "^2.0.1",
1031
+ "vary": "^1.1.2"
1032
+ },
1033
+ "engines": {
1034
+ "node": ">= 18"
1035
+ },
1036
+ "funding": {
1037
+ "type": "opencollective",
1038
+ "url": "https://opencollective.com/express"
1039
+ }
1040
+ },
1041
+ "node_modules/express-rate-limit": {
1042
+ "version": "8.3.2",
1043
+ "resolved": "https://registry.npmmirror.com/express-rate-limit/-/express-rate-limit-8.3.2.tgz",
1044
+ "integrity": "sha512-77VmFeJkO0/rvimEDuUC5H30oqUC4EyOhyGccfqoLebB0oiEYfM7nwPrsDsBL1gsTpwfzX8SFy2MT3TDyRq+bg==",
1045
+ "license": "MIT",
1046
+ "dependencies": {
1047
+ "ip-address": "10.1.0"
1048
+ },
1049
+ "engines": {
1050
+ "node": ">= 16"
1051
+ },
1052
+ "funding": {
1053
+ "url": "https://github.com/sponsors/express-rate-limit"
1054
+ },
1055
+ "peerDependencies": {
1056
+ "express": ">= 4.11"
1057
+ }
1058
+ },
1059
+ "node_modules/fast-deep-equal": {
1060
+ "version": "3.1.3",
1061
+ "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
1062
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
1063
+ "license": "MIT"
1064
+ },
1065
+ "node_modules/fast-uri": {
1066
+ "version": "3.1.0",
1067
+ "resolved": "https://registry.npmmirror.com/fast-uri/-/fast-uri-3.1.0.tgz",
1068
+ "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==",
1069
+ "funding": [
1070
+ {
1071
+ "type": "github",
1072
+ "url": "https://github.com/sponsors/fastify"
1073
+ },
1074
+ {
1075
+ "type": "opencollective",
1076
+ "url": "https://opencollective.com/fastify"
1077
+ }
1078
+ ],
1079
+ "license": "BSD-3-Clause"
1080
+ },
1081
+ "node_modules/feaxios": {
1082
+ "version": "0.0.23",
1083
+ "resolved": "https://registry.npmmirror.com/feaxios/-/feaxios-0.0.23.tgz",
1084
+ "integrity": "sha512-eghR0A21fvbkcQBgZuMfQhrXxJzC0GNUGC9fXhBge33D+mFDTwl0aJ35zoQQn575BhyjQitRc5N4f+L4cP708g==",
1085
+ "license": "MIT",
1086
+ "dependencies": {
1087
+ "is-retry-allowed": "^3.0.0"
1088
+ }
1089
+ },
1090
+ "node_modules/finalhandler": {
1091
+ "version": "2.1.1",
1092
+ "resolved": "https://registry.npmmirror.com/finalhandler/-/finalhandler-2.1.1.tgz",
1093
+ "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==",
1094
+ "license": "MIT",
1095
+ "dependencies": {
1096
+ "debug": "^4.4.0",
1097
+ "encodeurl": "^2.0.0",
1098
+ "escape-html": "^1.0.3",
1099
+ "on-finished": "^2.4.1",
1100
+ "parseurl": "^1.3.3",
1101
+ "statuses": "^2.0.1"
1102
+ },
1103
+ "engines": {
1104
+ "node": ">= 18.0.0"
1105
+ },
1106
+ "funding": {
1107
+ "type": "opencollective",
1108
+ "url": "https://opencollective.com/express"
1109
+ }
1110
+ },
1111
+ "node_modules/follow-redirects": {
1112
+ "version": "1.15.11",
1113
+ "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.11.tgz",
1114
+ "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
1115
+ "funding": [
1116
+ {
1117
+ "type": "individual",
1118
+ "url": "https://github.com/sponsors/RubenVerborgh"
1119
+ }
1120
+ ],
1121
+ "license": "MIT",
1122
+ "engines": {
1123
+ "node": ">=4.0"
1124
+ },
1125
+ "peerDependenciesMeta": {
1126
+ "debug": {
1127
+ "optional": true
1128
+ }
1129
+ }
1130
+ },
1131
+ "node_modules/for-each": {
1132
+ "version": "0.3.5",
1133
+ "resolved": "https://registry.npmmirror.com/for-each/-/for-each-0.3.5.tgz",
1134
+ "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
1135
+ "license": "MIT",
1136
+ "dependencies": {
1137
+ "is-callable": "^1.2.7"
1138
+ },
1139
+ "engines": {
1140
+ "node": ">= 0.4"
1141
+ },
1142
+ "funding": {
1143
+ "url": "https://github.com/sponsors/ljharb"
1144
+ }
1145
+ },
1146
+ "node_modules/form-data": {
1147
+ "version": "4.0.5",
1148
+ "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.5.tgz",
1149
+ "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
1150
+ "license": "MIT",
1151
+ "dependencies": {
1152
+ "asynckit": "^0.4.0",
1153
+ "combined-stream": "^1.0.8",
1154
+ "es-set-tostringtag": "^2.1.0",
1155
+ "hasown": "^2.0.2",
1156
+ "mime-types": "^2.1.12"
1157
+ },
1158
+ "engines": {
1159
+ "node": ">= 6"
1160
+ }
1161
+ },
1162
+ "node_modules/form-data/node_modules/mime-db": {
1163
+ "version": "1.52.0",
1164
+ "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
1165
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
1166
+ "license": "MIT",
1167
+ "engines": {
1168
+ "node": ">= 0.6"
1169
+ }
1170
+ },
1171
+ "node_modules/form-data/node_modules/mime-types": {
1172
+ "version": "2.1.35",
1173
+ "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz",
1174
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
1175
+ "license": "MIT",
1176
+ "dependencies": {
1177
+ "mime-db": "1.52.0"
1178
+ },
1179
+ "engines": {
1180
+ "node": ">= 0.6"
1181
+ }
1182
+ },
1183
+ "node_modules/forwarded": {
1184
+ "version": "0.2.0",
1185
+ "resolved": "https://registry.npmmirror.com/forwarded/-/forwarded-0.2.0.tgz",
1186
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
1187
+ "license": "MIT",
1188
+ "engines": {
1189
+ "node": ">= 0.6"
1190
+ }
1191
+ },
1192
+ "node_modules/fresh": {
1193
+ "version": "2.0.0",
1194
+ "resolved": "https://registry.npmmirror.com/fresh/-/fresh-2.0.0.tgz",
1195
+ "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
1196
+ "license": "MIT",
1197
+ "engines": {
1198
+ "node": ">= 0.8"
1199
+ }
1200
+ },
1201
+ "node_modules/fsevents": {
1202
+ "version": "2.3.2",
1203
+ "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.2.tgz",
1204
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
1205
+ "hasInstallScript": true,
1206
+ "license": "MIT",
1207
+ "optional": true,
1208
+ "os": [
1209
+ "darwin"
1210
+ ],
1211
+ "engines": {
1212
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
1213
+ }
1214
+ },
1215
+ "node_modules/function-bind": {
1216
+ "version": "1.1.2",
1217
+ "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz",
1218
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
1219
+ "license": "MIT",
1220
+ "funding": {
1221
+ "url": "https://github.com/sponsors/ljharb"
1222
+ }
1223
+ },
1224
+ "node_modules/get-intrinsic": {
1225
+ "version": "1.3.0",
1226
+ "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
1227
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
1228
+ "license": "MIT",
1229
+ "dependencies": {
1230
+ "call-bind-apply-helpers": "^1.0.2",
1231
+ "es-define-property": "^1.0.1",
1232
+ "es-errors": "^1.3.0",
1233
+ "es-object-atoms": "^1.1.1",
1234
+ "function-bind": "^1.1.2",
1235
+ "get-proto": "^1.0.1",
1236
+ "gopd": "^1.2.0",
1237
+ "has-symbols": "^1.1.0",
1238
+ "hasown": "^2.0.2",
1239
+ "math-intrinsics": "^1.1.0"
1240
+ },
1241
+ "engines": {
1242
+ "node": ">= 0.4"
1243
+ },
1244
+ "funding": {
1245
+ "url": "https://github.com/sponsors/ljharb"
1246
+ }
1247
+ },
1248
+ "node_modules/get-proto": {
1249
+ "version": "1.0.1",
1250
+ "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz",
1251
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
1252
+ "license": "MIT",
1253
+ "dependencies": {
1254
+ "dunder-proto": "^1.0.1",
1255
+ "es-object-atoms": "^1.0.0"
1256
+ },
1257
+ "engines": {
1258
+ "node": ">= 0.4"
1259
+ }
1260
+ },
1261
+ "node_modules/gopd": {
1262
+ "version": "1.2.0",
1263
+ "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz",
1264
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
1265
+ "license": "MIT",
1266
+ "engines": {
1267
+ "node": ">= 0.4"
1268
+ },
1269
+ "funding": {
1270
+ "url": "https://github.com/sponsors/ljharb"
1271
+ }
1272
+ },
1273
+ "node_modules/has-property-descriptors": {
1274
+ "version": "1.0.2",
1275
+ "resolved": "https://registry.npmmirror.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
1276
+ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
1277
+ "license": "MIT",
1278
+ "dependencies": {
1279
+ "es-define-property": "^1.0.0"
1280
+ },
1281
+ "funding": {
1282
+ "url": "https://github.com/sponsors/ljharb"
1283
+ }
1284
+ },
1285
+ "node_modules/has-symbols": {
1286
+ "version": "1.1.0",
1287
+ "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz",
1288
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
1289
+ "license": "MIT",
1290
+ "engines": {
1291
+ "node": ">= 0.4"
1292
+ },
1293
+ "funding": {
1294
+ "url": "https://github.com/sponsors/ljharb"
1295
+ }
1296
+ },
1297
+ "node_modules/has-tostringtag": {
1298
+ "version": "1.0.2",
1299
+ "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
1300
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
1301
+ "license": "MIT",
1302
+ "dependencies": {
1303
+ "has-symbols": "^1.0.3"
1304
+ },
1305
+ "engines": {
1306
+ "node": ">= 0.4"
1307
+ },
1308
+ "funding": {
1309
+ "url": "https://github.com/sponsors/ljharb"
1310
+ }
1311
+ },
1312
+ "node_modules/hasown": {
1313
+ "version": "2.0.2",
1314
+ "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz",
1315
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
1316
+ "license": "MIT",
1317
+ "dependencies": {
1318
+ "function-bind": "^1.1.2"
1319
+ },
1320
+ "engines": {
1321
+ "node": ">= 0.4"
1322
+ }
1323
+ },
1324
+ "node_modules/hono": {
1325
+ "version": "4.12.12",
1326
+ "resolved": "https://registry.npmmirror.com/hono/-/hono-4.12.12.tgz",
1327
+ "integrity": "sha512-p1JfQMKaceuCbpJKAPKVqyqviZdS0eUxH9v82oWo1kb9xjQ5wA6iP3FNVAPDFlz5/p7d45lO+BpSk1tuSZMF4Q==",
1328
+ "license": "MIT",
1329
+ "engines": {
1330
+ "node": ">=16.9.0"
1331
+ }
1332
+ },
1333
+ "node_modules/http-errors": {
1334
+ "version": "2.0.1",
1335
+ "resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-2.0.1.tgz",
1336
+ "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
1337
+ "license": "MIT",
1338
+ "dependencies": {
1339
+ "depd": "~2.0.0",
1340
+ "inherits": "~2.0.4",
1341
+ "setprototypeof": "~1.2.0",
1342
+ "statuses": "~2.0.2",
1343
+ "toidentifier": "~1.0.1"
1344
+ },
1345
+ "engines": {
1346
+ "node": ">= 0.8"
1347
+ },
1348
+ "funding": {
1349
+ "type": "opencollective",
1350
+ "url": "https://opencollective.com/express"
1351
+ }
1352
+ },
1353
+ "node_modules/iconv-lite": {
1354
+ "version": "0.7.2",
1355
+ "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.7.2.tgz",
1356
+ "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==",
1357
+ "license": "MIT",
1358
+ "dependencies": {
1359
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
1360
+ },
1361
+ "engines": {
1362
+ "node": ">=0.10.0"
1363
+ },
1364
+ "funding": {
1365
+ "type": "opencollective",
1366
+ "url": "https://opencollective.com/express"
1367
+ }
1368
+ },
1369
+ "node_modules/ieee754": {
1370
+ "version": "1.2.1",
1371
+ "resolved": "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz",
1372
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
1373
+ "funding": [
1374
+ {
1375
+ "type": "github",
1376
+ "url": "https://github.com/sponsors/feross"
1377
+ },
1378
+ {
1379
+ "type": "patreon",
1380
+ "url": "https://www.patreon.com/feross"
1381
+ },
1382
+ {
1383
+ "type": "consulting",
1384
+ "url": "https://feross.org/support"
1385
+ }
1386
+ ],
1387
+ "license": "BSD-3-Clause"
1388
+ },
1389
+ "node_modules/inherits": {
1390
+ "version": "2.0.4",
1391
+ "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz",
1392
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
1393
+ "license": "ISC"
1394
+ },
1395
+ "node_modules/ip-address": {
1396
+ "version": "10.1.0",
1397
+ "resolved": "https://registry.npmmirror.com/ip-address/-/ip-address-10.1.0.tgz",
1398
+ "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==",
1399
+ "license": "MIT",
1400
+ "engines": {
1401
+ "node": ">= 12"
1402
+ }
1403
+ },
1404
+ "node_modules/ipaddr.js": {
1405
+ "version": "1.9.1",
1406
+ "resolved": "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
1407
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
1408
+ "license": "MIT",
1409
+ "engines": {
1410
+ "node": ">= 0.10"
1411
+ }
1412
+ },
1413
+ "node_modules/is-callable": {
1414
+ "version": "1.2.7",
1415
+ "resolved": "https://registry.npmmirror.com/is-callable/-/is-callable-1.2.7.tgz",
1416
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
1417
+ "license": "MIT",
1418
+ "engines": {
1419
+ "node": ">= 0.4"
1420
+ },
1421
+ "funding": {
1422
+ "url": "https://github.com/sponsors/ljharb"
1423
+ }
1424
+ },
1425
+ "node_modules/is-promise": {
1426
+ "version": "4.0.0",
1427
+ "resolved": "https://registry.npmmirror.com/is-promise/-/is-promise-4.0.0.tgz",
1428
+ "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
1429
+ "license": "MIT"
1430
+ },
1431
+ "node_modules/is-retry-allowed": {
1432
+ "version": "3.0.0",
1433
+ "resolved": "https://registry.npmmirror.com/is-retry-allowed/-/is-retry-allowed-3.0.0.tgz",
1434
+ "integrity": "sha512-9xH0xvoggby+u0uGF7cZXdrutWiBiaFG8ZT4YFPXL8NzkyAwX3AKGLeFQLvzDpM430+nDFBZ1LHkie/8ocL06A==",
1435
+ "license": "MIT",
1436
+ "engines": {
1437
+ "node": ">=12"
1438
+ },
1439
+ "funding": {
1440
+ "url": "https://github.com/sponsors/sindresorhus"
1441
+ }
1442
+ },
1443
+ "node_modules/is-typed-array": {
1444
+ "version": "1.1.15",
1445
+ "resolved": "https://registry.npmmirror.com/is-typed-array/-/is-typed-array-1.1.15.tgz",
1446
+ "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
1447
+ "license": "MIT",
1448
+ "dependencies": {
1449
+ "which-typed-array": "^1.1.16"
1450
+ },
1451
+ "engines": {
1452
+ "node": ">= 0.4"
1453
+ },
1454
+ "funding": {
1455
+ "url": "https://github.com/sponsors/ljharb"
1456
+ }
1457
+ },
1458
+ "node_modules/isarray": {
1459
+ "version": "2.0.5",
1460
+ "resolved": "https://registry.npmmirror.com/isarray/-/isarray-2.0.5.tgz",
1461
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
1462
+ "license": "MIT"
1463
+ },
1464
+ "node_modules/isexe": {
1465
+ "version": "2.0.0",
1466
+ "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz",
1467
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
1468
+ "license": "ISC"
1469
+ },
1470
+ "node_modules/isows": {
1471
+ "version": "1.0.7",
1472
+ "resolved": "https://registry.npmmirror.com/isows/-/isows-1.0.7.tgz",
1473
+ "integrity": "sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg==",
1474
+ "funding": [
1475
+ {
1476
+ "type": "github",
1477
+ "url": "https://github.com/sponsors/wevm"
1478
+ }
1479
+ ],
1480
+ "license": "MIT",
1481
+ "peerDependencies": {
1482
+ "ws": "*"
1483
+ }
1484
+ },
1485
+ "node_modules/jose": {
1486
+ "version": "5.10.0",
1487
+ "resolved": "https://registry.npmmirror.com/jose/-/jose-5.10.0.tgz",
1488
+ "integrity": "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==",
1489
+ "license": "MIT",
1490
+ "funding": {
1491
+ "url": "https://github.com/sponsors/panva"
1492
+ }
1493
+ },
1494
+ "node_modules/json-schema-traverse": {
1495
+ "version": "1.0.0",
1496
+ "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
1497
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
1498
+ "license": "MIT"
1499
+ },
1500
+ "node_modules/json-schema-typed": {
1501
+ "version": "8.0.2",
1502
+ "resolved": "https://registry.npmmirror.com/json-schema-typed/-/json-schema-typed-8.0.2.tgz",
1503
+ "integrity": "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==",
1504
+ "license": "BSD-2-Clause"
1505
+ },
1506
+ "node_modules/math-intrinsics": {
1507
+ "version": "1.1.0",
1508
+ "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
1509
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
1510
+ "license": "MIT",
1511
+ "engines": {
1512
+ "node": ">= 0.4"
1513
+ }
1514
+ },
1515
+ "node_modules/media-typer": {
1516
+ "version": "1.1.0",
1517
+ "resolved": "https://registry.npmmirror.com/media-typer/-/media-typer-1.1.0.tgz",
1518
+ "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==",
1519
+ "license": "MIT",
1520
+ "engines": {
1521
+ "node": ">= 0.8"
1522
+ }
1523
+ },
1524
+ "node_modules/merge-descriptors": {
1525
+ "version": "2.0.0",
1526
+ "resolved": "https://registry.npmmirror.com/merge-descriptors/-/merge-descriptors-2.0.0.tgz",
1527
+ "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==",
1528
+ "license": "MIT",
1529
+ "engines": {
1530
+ "node": ">=18"
1531
+ },
1532
+ "funding": {
1533
+ "url": "https://github.com/sponsors/sindresorhus"
1534
+ }
1535
+ },
1536
+ "node_modules/mime-db": {
1537
+ "version": "1.54.0",
1538
+ "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.54.0.tgz",
1539
+ "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
1540
+ "license": "MIT",
1541
+ "engines": {
1542
+ "node": ">= 0.6"
1543
+ }
1544
+ },
1545
+ "node_modules/mime-types": {
1546
+ "version": "3.0.2",
1547
+ "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-3.0.2.tgz",
1548
+ "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==",
1549
+ "license": "MIT",
1550
+ "dependencies": {
1551
+ "mime-db": "^1.54.0"
1552
+ },
1553
+ "engines": {
1554
+ "node": ">=18"
1555
+ },
1556
+ "funding": {
1557
+ "type": "opencollective",
1558
+ "url": "https://opencollective.com/express"
1559
+ }
1560
+ },
1561
+ "node_modules/ms": {
1562
+ "version": "2.1.3",
1563
+ "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz",
1564
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
1565
+ "license": "MIT"
1566
+ },
1567
+ "node_modules/negotiator": {
1568
+ "version": "1.0.0",
1569
+ "resolved": "https://registry.npmmirror.com/negotiator/-/negotiator-1.0.0.tgz",
1570
+ "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
1571
+ "license": "MIT",
1572
+ "engines": {
1573
+ "node": ">= 0.6"
1574
+ }
1575
+ },
1576
+ "node_modules/object-assign": {
1577
+ "version": "4.1.1",
1578
+ "resolved": "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz",
1579
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
1580
+ "license": "MIT",
1581
+ "engines": {
1582
+ "node": ">=0.10.0"
1583
+ }
1584
+ },
1585
+ "node_modules/object-inspect": {
1586
+ "version": "1.13.4",
1587
+ "resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.13.4.tgz",
1588
+ "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
1589
+ "license": "MIT",
1590
+ "engines": {
1591
+ "node": ">= 0.4"
1592
+ },
1593
+ "funding": {
1594
+ "url": "https://github.com/sponsors/ljharb"
1595
+ }
1596
+ },
1597
+ "node_modules/on-finished": {
1598
+ "version": "2.4.1",
1599
+ "resolved": "https://registry.npmmirror.com/on-finished/-/on-finished-2.4.1.tgz",
1600
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
1601
+ "license": "MIT",
1602
+ "dependencies": {
1603
+ "ee-first": "1.1.1"
1604
+ },
1605
+ "engines": {
1606
+ "node": ">= 0.8"
1607
+ }
1608
+ },
1609
+ "node_modules/once": {
1610
+ "version": "1.4.0",
1611
+ "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz",
1612
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
1613
+ "license": "ISC",
1614
+ "dependencies": {
1615
+ "wrappy": "1"
1616
+ }
1617
+ },
1618
+ "node_modules/ox": {
1619
+ "version": "0.14.15",
1620
+ "resolved": "https://registry.npmmirror.com/ox/-/ox-0.14.15.tgz",
1621
+ "integrity": "sha512-3TubCmbKen/cuZQzX0qDbOS5lojjdSZ90lqKxWIDWd5siuJ0IJBaTXMYs8eMPLcraqnOwGZazz3apHPGiRCkGQ==",
1622
+ "funding": [
1623
+ {
1624
+ "type": "github",
1625
+ "url": "https://github.com/sponsors/wevm"
1626
+ }
1627
+ ],
1628
+ "license": "MIT",
1629
+ "dependencies": {
1630
+ "@adraffy/ens-normalize": "^1.11.0",
1631
+ "@noble/ciphers": "^1.3.0",
1632
+ "@noble/curves": "1.9.1",
1633
+ "@noble/hashes": "^1.8.0",
1634
+ "@scure/bip32": "^1.7.0",
1635
+ "@scure/bip39": "^1.6.0",
1636
+ "abitype": "^1.2.3",
1637
+ "eventemitter3": "5.0.1"
1638
+ },
1639
+ "peerDependencies": {
1640
+ "typescript": ">=5.4.0"
1641
+ },
1642
+ "peerDependenciesMeta": {
1643
+ "typescript": {
1644
+ "optional": true
1645
+ }
1646
+ }
1647
+ },
1648
+ "node_modules/ox/node_modules/@adraffy/ens-normalize": {
1649
+ "version": "1.11.1",
1650
+ "resolved": "https://registry.npmmirror.com/@adraffy/ens-normalize/-/ens-normalize-1.11.1.tgz",
1651
+ "integrity": "sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ==",
1652
+ "license": "MIT"
1653
+ },
1654
+ "node_modules/ox/node_modules/@noble/curves": {
1655
+ "version": "1.9.1",
1656
+ "resolved": "https://registry.npmmirror.com/@noble/curves/-/curves-1.9.1.tgz",
1657
+ "integrity": "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==",
1658
+ "license": "MIT",
1659
+ "dependencies": {
1660
+ "@noble/hashes": "1.8.0"
1661
+ },
1662
+ "engines": {
1663
+ "node": "^14.21.3 || >=16"
1664
+ },
1665
+ "funding": {
1666
+ "url": "https://paulmillr.com/funding/"
1667
+ }
1668
+ },
1669
+ "node_modules/parseurl": {
1670
+ "version": "1.3.3",
1671
+ "resolved": "https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz",
1672
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
1673
+ "license": "MIT",
1674
+ "engines": {
1675
+ "node": ">= 0.8"
1676
+ }
1677
+ },
1678
+ "node_modules/path-key": {
1679
+ "version": "3.1.1",
1680
+ "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz",
1681
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
1682
+ "license": "MIT",
1683
+ "engines": {
1684
+ "node": ">=8"
1685
+ }
1686
+ },
1687
+ "node_modules/path-to-regexp": {
1688
+ "version": "8.4.2",
1689
+ "resolved": "https://registry.npmmirror.com/path-to-regexp/-/path-to-regexp-8.4.2.tgz",
1690
+ "integrity": "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==",
1691
+ "license": "MIT",
1692
+ "funding": {
1693
+ "type": "opencollective",
1694
+ "url": "https://opencollective.com/express"
1695
+ }
1696
+ },
1697
+ "node_modules/pkce-challenge": {
1698
+ "version": "5.0.1",
1699
+ "resolved": "https://registry.npmmirror.com/pkce-challenge/-/pkce-challenge-5.0.1.tgz",
1700
+ "integrity": "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==",
1701
+ "license": "MIT",
1702
+ "engines": {
1703
+ "node": ">=16.20.0"
1704
+ }
1705
+ },
1706
+ "node_modules/playwright": {
1707
+ "version": "1.59.1",
1708
+ "resolved": "https://registry.npmmirror.com/playwright/-/playwright-1.59.1.tgz",
1709
+ "integrity": "sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==",
1710
+ "license": "Apache-2.0",
1711
+ "dependencies": {
1712
+ "playwright-core": "1.59.1"
1713
+ },
1714
+ "bin": {
1715
+ "playwright": "cli.js"
1716
+ },
1717
+ "engines": {
1718
+ "node": ">=18"
1719
+ },
1720
+ "optionalDependencies": {
1721
+ "fsevents": "2.3.2"
1722
+ }
1723
+ },
1724
+ "node_modules/playwright-core": {
1725
+ "version": "1.59.1",
1726
+ "resolved": "https://registry.npmmirror.com/playwright-core/-/playwright-core-1.59.1.tgz",
1727
+ "integrity": "sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==",
1728
+ "license": "Apache-2.0",
1729
+ "bin": {
1730
+ "playwright-core": "cli.js"
1731
+ },
1732
+ "engines": {
1733
+ "node": ">=18"
1734
+ }
1735
+ },
1736
+ "node_modules/possible-typed-array-names": {
1737
+ "version": "1.1.0",
1738
+ "resolved": "https://registry.npmmirror.com/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
1739
+ "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
1740
+ "license": "MIT",
1741
+ "engines": {
1742
+ "node": ">= 0.4"
1743
+ }
1744
+ },
1745
+ "node_modules/proxy-addr": {
1746
+ "version": "2.0.7",
1747
+ "resolved": "https://registry.npmmirror.com/proxy-addr/-/proxy-addr-2.0.7.tgz",
1748
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
1749
+ "license": "MIT",
1750
+ "dependencies": {
1751
+ "forwarded": "0.2.0",
1752
+ "ipaddr.js": "1.9.1"
1753
+ },
1754
+ "engines": {
1755
+ "node": ">= 0.10"
1756
+ }
1757
+ },
1758
+ "node_modules/proxy-from-env": {
1759
+ "version": "2.1.0",
1760
+ "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
1761
+ "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
1762
+ "license": "MIT",
1763
+ "engines": {
1764
+ "node": ">=10"
1765
+ }
1766
+ },
1767
+ "node_modules/punycode": {
1768
+ "version": "2.3.1",
1769
+ "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz",
1770
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
1771
+ "license": "MIT",
1772
+ "engines": {
1773
+ "node": ">=6"
1774
+ }
1775
+ },
1776
+ "node_modules/qs": {
1777
+ "version": "6.15.1",
1778
+ "resolved": "https://registry.npmmirror.com/qs/-/qs-6.15.1.tgz",
1779
+ "integrity": "sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==",
1780
+ "license": "BSD-3-Clause",
1781
+ "dependencies": {
1782
+ "side-channel": "^1.1.0"
1783
+ },
1784
+ "engines": {
1785
+ "node": ">=0.6"
1786
+ },
1787
+ "funding": {
1788
+ "url": "https://github.com/sponsors/ljharb"
1789
+ }
1790
+ },
1791
+ "node_modules/randombytes": {
1792
+ "version": "2.1.0",
1793
+ "resolved": "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz",
1794
+ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
1795
+ "license": "MIT",
1796
+ "dependencies": {
1797
+ "safe-buffer": "^5.1.0"
1798
+ }
1799
+ },
1800
+ "node_modules/range-parser": {
1801
+ "version": "1.2.1",
1802
+ "resolved": "https://registry.npmmirror.com/range-parser/-/range-parser-1.2.1.tgz",
1803
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
1804
+ "license": "MIT",
1805
+ "engines": {
1806
+ "node": ">= 0.6"
1807
+ }
1808
+ },
1809
+ "node_modules/raw-body": {
1810
+ "version": "3.0.2",
1811
+ "resolved": "https://registry.npmmirror.com/raw-body/-/raw-body-3.0.2.tgz",
1812
+ "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==",
1813
+ "license": "MIT",
1814
+ "dependencies": {
1815
+ "bytes": "~3.1.2",
1816
+ "http-errors": "~2.0.1",
1817
+ "iconv-lite": "~0.7.0",
1818
+ "unpipe": "~1.0.0"
1819
+ },
1820
+ "engines": {
1821
+ "node": ">= 0.10"
1822
+ }
1823
+ },
1824
+ "node_modules/require-from-string": {
1825
+ "version": "2.0.2",
1826
+ "resolved": "https://registry.npmmirror.com/require-from-string/-/require-from-string-2.0.2.tgz",
1827
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
1828
+ "license": "MIT",
1829
+ "engines": {
1830
+ "node": ">=0.10.0"
1831
+ }
1832
+ },
1833
+ "node_modules/router": {
1834
+ "version": "2.2.0",
1835
+ "resolved": "https://registry.npmmirror.com/router/-/router-2.2.0.tgz",
1836
+ "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==",
1837
+ "license": "MIT",
1838
+ "dependencies": {
1839
+ "debug": "^4.4.0",
1840
+ "depd": "^2.0.0",
1841
+ "is-promise": "^4.0.0",
1842
+ "parseurl": "^1.3.3",
1843
+ "path-to-regexp": "^8.0.0"
1844
+ },
1845
+ "engines": {
1846
+ "node": ">= 18"
1847
+ }
1848
+ },
1849
+ "node_modules/safe-buffer": {
1850
+ "version": "5.2.1",
1851
+ "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz",
1852
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
1853
+ "funding": [
1854
+ {
1855
+ "type": "github",
1856
+ "url": "https://github.com/sponsors/feross"
1857
+ },
1858
+ {
1859
+ "type": "patreon",
1860
+ "url": "https://www.patreon.com/feross"
1861
+ },
1862
+ {
1863
+ "type": "consulting",
1864
+ "url": "https://feross.org/support"
1865
+ }
1866
+ ],
1867
+ "license": "MIT"
1868
+ },
1869
+ "node_modules/safer-buffer": {
1870
+ "version": "2.1.2",
1871
+ "resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz",
1872
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
1873
+ "license": "MIT"
1874
+ },
1875
+ "node_modules/send": {
1876
+ "version": "1.2.1",
1877
+ "resolved": "https://registry.npmmirror.com/send/-/send-1.2.1.tgz",
1878
+ "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==",
1879
+ "license": "MIT",
1880
+ "dependencies": {
1881
+ "debug": "^4.4.3",
1882
+ "encodeurl": "^2.0.0",
1883
+ "escape-html": "^1.0.3",
1884
+ "etag": "^1.8.1",
1885
+ "fresh": "^2.0.0",
1886
+ "http-errors": "^2.0.1",
1887
+ "mime-types": "^3.0.2",
1888
+ "ms": "^2.1.3",
1889
+ "on-finished": "^2.4.1",
1890
+ "range-parser": "^1.2.1",
1891
+ "statuses": "^2.0.2"
1892
+ },
1893
+ "engines": {
1894
+ "node": ">= 18"
1895
+ },
1896
+ "funding": {
1897
+ "type": "opencollective",
1898
+ "url": "https://opencollective.com/express"
1899
+ }
1900
+ },
1901
+ "node_modules/serve-static": {
1902
+ "version": "2.2.1",
1903
+ "resolved": "https://registry.npmmirror.com/serve-static/-/serve-static-2.2.1.tgz",
1904
+ "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==",
1905
+ "license": "MIT",
1906
+ "dependencies": {
1907
+ "encodeurl": "^2.0.0",
1908
+ "escape-html": "^1.0.3",
1909
+ "parseurl": "^1.3.3",
1910
+ "send": "^1.2.0"
1911
+ },
1912
+ "engines": {
1913
+ "node": ">= 18"
1914
+ },
1915
+ "funding": {
1916
+ "type": "opencollective",
1917
+ "url": "https://opencollective.com/express"
1918
+ }
1919
+ },
1920
+ "node_modules/set-function-length": {
1921
+ "version": "1.2.2",
1922
+ "resolved": "https://registry.npmmirror.com/set-function-length/-/set-function-length-1.2.2.tgz",
1923
+ "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
1924
+ "license": "MIT",
1925
+ "dependencies": {
1926
+ "define-data-property": "^1.1.4",
1927
+ "es-errors": "^1.3.0",
1928
+ "function-bind": "^1.1.2",
1929
+ "get-intrinsic": "^1.2.4",
1930
+ "gopd": "^1.0.1",
1931
+ "has-property-descriptors": "^1.0.2"
1932
+ },
1933
+ "engines": {
1934
+ "node": ">= 0.4"
1935
+ }
1936
+ },
1937
+ "node_modules/setprototypeof": {
1938
+ "version": "1.2.0",
1939
+ "resolved": "https://registry.npmmirror.com/setprototypeof/-/setprototypeof-1.2.0.tgz",
1940
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
1941
+ "license": "ISC"
1942
+ },
1943
+ "node_modules/sha.js": {
1944
+ "version": "2.4.12",
1945
+ "resolved": "https://registry.npmmirror.com/sha.js/-/sha.js-2.4.12.tgz",
1946
+ "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==",
1947
+ "license": "(MIT AND BSD-3-Clause)",
1948
+ "dependencies": {
1949
+ "inherits": "^2.0.4",
1950
+ "safe-buffer": "^5.2.1",
1951
+ "to-buffer": "^1.2.0"
1952
+ },
1953
+ "bin": {
1954
+ "sha.js": "bin.js"
1955
+ },
1956
+ "engines": {
1957
+ "node": ">= 0.10"
1958
+ },
1959
+ "funding": {
1960
+ "url": "https://github.com/sponsors/ljharb"
1961
+ }
1962
+ },
1963
+ "node_modules/shebang-command": {
1964
+ "version": "2.0.0",
1965
+ "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz",
1966
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
1967
+ "license": "MIT",
1968
+ "dependencies": {
1969
+ "shebang-regex": "^3.0.0"
1970
+ },
1971
+ "engines": {
1972
+ "node": ">=8"
1973
+ }
1974
+ },
1975
+ "node_modules/shebang-regex": {
1976
+ "version": "3.0.0",
1977
+ "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz",
1978
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
1979
+ "license": "MIT",
1980
+ "engines": {
1981
+ "node": ">=8"
1982
+ }
1983
+ },
1984
+ "node_modules/side-channel": {
1985
+ "version": "1.1.0",
1986
+ "resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.1.0.tgz",
1987
+ "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
1988
+ "license": "MIT",
1989
+ "dependencies": {
1990
+ "es-errors": "^1.3.0",
1991
+ "object-inspect": "^1.13.3",
1992
+ "side-channel-list": "^1.0.0",
1993
+ "side-channel-map": "^1.0.1",
1994
+ "side-channel-weakmap": "^1.0.2"
1995
+ },
1996
+ "engines": {
1997
+ "node": ">= 0.4"
1998
+ },
1999
+ "funding": {
2000
+ "url": "https://github.com/sponsors/ljharb"
2001
+ }
2002
+ },
2003
+ "node_modules/side-channel-list": {
2004
+ "version": "1.0.1",
2005
+ "resolved": "https://registry.npmmirror.com/side-channel-list/-/side-channel-list-1.0.1.tgz",
2006
+ "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==",
2007
+ "license": "MIT",
2008
+ "dependencies": {
2009
+ "es-errors": "^1.3.0",
2010
+ "object-inspect": "^1.13.4"
2011
+ },
2012
+ "engines": {
2013
+ "node": ">= 0.4"
2014
+ },
2015
+ "funding": {
2016
+ "url": "https://github.com/sponsors/ljharb"
2017
+ }
2018
+ },
2019
+ "node_modules/side-channel-map": {
2020
+ "version": "1.0.1",
2021
+ "resolved": "https://registry.npmmirror.com/side-channel-map/-/side-channel-map-1.0.1.tgz",
2022
+ "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
2023
+ "license": "MIT",
2024
+ "dependencies": {
2025
+ "call-bound": "^1.0.2",
2026
+ "es-errors": "^1.3.0",
2027
+ "get-intrinsic": "^1.2.5",
2028
+ "object-inspect": "^1.13.3"
2029
+ },
2030
+ "engines": {
2031
+ "node": ">= 0.4"
2032
+ },
2033
+ "funding": {
2034
+ "url": "https://github.com/sponsors/ljharb"
2035
+ }
2036
+ },
2037
+ "node_modules/side-channel-weakmap": {
2038
+ "version": "1.0.2",
2039
+ "resolved": "https://registry.npmmirror.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
2040
+ "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
2041
+ "license": "MIT",
2042
+ "dependencies": {
2043
+ "call-bound": "^1.0.2",
2044
+ "es-errors": "^1.3.0",
2045
+ "get-intrinsic": "^1.2.5",
2046
+ "object-inspect": "^1.13.3",
2047
+ "side-channel-map": "^1.0.1"
2048
+ },
2049
+ "engines": {
2050
+ "node": ">= 0.4"
2051
+ },
2052
+ "funding": {
2053
+ "url": "https://github.com/sponsors/ljharb"
2054
+ }
2055
+ },
2056
+ "node_modules/siwe": {
2057
+ "version": "2.3.2",
2058
+ "resolved": "https://registry.npmmirror.com/siwe/-/siwe-2.3.2.tgz",
2059
+ "integrity": "sha512-aSf+6+Latyttbj5nMu6GF3doMfv2UYj83hhwZgUF20ky6fTS83uVhkQABdIVnEuS8y1bBdk7p6ltb9SmlhTTlA==",
2060
+ "license": "Apache-2.0",
2061
+ "dependencies": {
2062
+ "@spruceid/siwe-parser": "^2.1.2",
2063
+ "@stablelib/random": "^1.0.1",
2064
+ "uri-js": "^4.4.1",
2065
+ "valid-url": "^1.0.9"
2066
+ },
2067
+ "peerDependencies": {
2068
+ "ethers": "^5.6.8 || ^6.0.8"
2069
+ }
2070
+ },
2071
+ "node_modules/statuses": {
2072
+ "version": "2.0.2",
2073
+ "resolved": "https://registry.npmmirror.com/statuses/-/statuses-2.0.2.tgz",
2074
+ "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
2075
+ "license": "MIT",
2076
+ "engines": {
2077
+ "node": ">= 0.8"
2078
+ }
2079
+ },
2080
+ "node_modules/to-buffer": {
2081
+ "version": "1.2.2",
2082
+ "resolved": "https://registry.npmmirror.com/to-buffer/-/to-buffer-1.2.2.tgz",
2083
+ "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==",
2084
+ "license": "MIT",
2085
+ "dependencies": {
2086
+ "isarray": "^2.0.5",
2087
+ "safe-buffer": "^5.2.1",
2088
+ "typed-array-buffer": "^1.0.3"
2089
+ },
2090
+ "engines": {
2091
+ "node": ">= 0.4"
2092
+ }
2093
+ },
2094
+ "node_modules/toidentifier": {
2095
+ "version": "1.0.1",
2096
+ "resolved": "https://registry.npmmirror.com/toidentifier/-/toidentifier-1.0.1.tgz",
2097
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
2098
+ "license": "MIT",
2099
+ "engines": {
2100
+ "node": ">=0.6"
2101
+ }
2102
+ },
2103
+ "node_modules/toml": {
2104
+ "version": "3.0.0",
2105
+ "resolved": "https://registry.npmmirror.com/toml/-/toml-3.0.0.tgz",
2106
+ "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==",
2107
+ "license": "MIT"
2108
+ },
2109
+ "node_modules/tslib": {
2110
+ "version": "2.7.0",
2111
+ "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.7.0.tgz",
2112
+ "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
2113
+ "license": "0BSD",
2114
+ "peer": true
2115
+ },
2116
+ "node_modules/tweetnacl": {
2117
+ "version": "1.0.3",
2118
+ "resolved": "https://registry.npmmirror.com/tweetnacl/-/tweetnacl-1.0.3.tgz",
2119
+ "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==",
2120
+ "license": "Unlicense"
2121
+ },
2122
+ "node_modules/type-is": {
2123
+ "version": "2.0.1",
2124
+ "resolved": "https://registry.npmmirror.com/type-is/-/type-is-2.0.1.tgz",
2125
+ "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==",
2126
+ "license": "MIT",
2127
+ "dependencies": {
2128
+ "content-type": "^1.0.5",
2129
+ "media-typer": "^1.1.0",
2130
+ "mime-types": "^3.0.0"
2131
+ },
2132
+ "engines": {
2133
+ "node": ">= 0.6"
2134
+ }
2135
+ },
2136
+ "node_modules/typed-array-buffer": {
2137
+ "version": "1.0.3",
2138
+ "resolved": "https://registry.npmmirror.com/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
2139
+ "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==",
2140
+ "license": "MIT",
2141
+ "dependencies": {
2142
+ "call-bound": "^1.0.3",
2143
+ "es-errors": "^1.3.0",
2144
+ "is-typed-array": "^1.1.14"
2145
+ },
2146
+ "engines": {
2147
+ "node": ">= 0.4"
2148
+ }
2149
+ },
2150
+ "node_modules/undici-types": {
2151
+ "version": "6.19.8",
2152
+ "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-6.19.8.tgz",
2153
+ "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
2154
+ "license": "MIT",
2155
+ "peer": true
2156
+ },
2157
+ "node_modules/unpipe": {
2158
+ "version": "1.0.0",
2159
+ "resolved": "https://registry.npmmirror.com/unpipe/-/unpipe-1.0.0.tgz",
2160
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
2161
+ "license": "MIT",
2162
+ "engines": {
2163
+ "node": ">= 0.8"
2164
+ }
2165
+ },
2166
+ "node_modules/uri-js": {
2167
+ "version": "4.4.1",
2168
+ "resolved": "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz",
2169
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
2170
+ "license": "BSD-2-Clause",
2171
+ "dependencies": {
2172
+ "punycode": "^2.1.0"
2173
+ }
2174
+ },
2175
+ "node_modules/urijs": {
2176
+ "version": "1.19.11",
2177
+ "resolved": "https://registry.npmmirror.com/urijs/-/urijs-1.19.11.tgz",
2178
+ "integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==",
2179
+ "license": "MIT"
2180
+ },
2181
+ "node_modules/valid-url": {
2182
+ "version": "1.0.9",
2183
+ "resolved": "https://registry.npmmirror.com/valid-url/-/valid-url-1.0.9.tgz",
2184
+ "integrity": "sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA=="
2185
+ },
2186
+ "node_modules/vary": {
2187
+ "version": "1.1.2",
2188
+ "resolved": "https://registry.npmmirror.com/vary/-/vary-1.1.2.tgz",
2189
+ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
2190
+ "license": "MIT",
2191
+ "engines": {
2192
+ "node": ">= 0.8"
2193
+ }
2194
+ },
2195
+ "node_modules/viem": {
2196
+ "version": "2.47.14",
2197
+ "resolved": "https://registry.npmmirror.com/viem/-/viem-2.47.14.tgz",
2198
+ "integrity": "sha512-PHmJF1dfa9HEfrVshFXFkixzh/22Z3VFXN1omeFfjMoOFDGQkghsRdDW+KcE29gzM7KZ+MC04L+xpbm2G/kOkw==",
2199
+ "funding": [
2200
+ {
2201
+ "type": "github",
2202
+ "url": "https://github.com/sponsors/wevm"
2203
+ }
2204
+ ],
2205
+ "license": "MIT",
2206
+ "dependencies": {
2207
+ "@noble/curves": "1.9.1",
2208
+ "@noble/hashes": "1.8.0",
2209
+ "@scure/bip32": "1.7.0",
2210
+ "@scure/bip39": "1.6.0",
2211
+ "abitype": "1.2.3",
2212
+ "isows": "1.0.7",
2213
+ "ox": "0.14.15",
2214
+ "ws": "8.18.3"
2215
+ },
2216
+ "peerDependencies": {
2217
+ "typescript": ">=5.0.4"
2218
+ },
2219
+ "peerDependenciesMeta": {
2220
+ "typescript": {
2221
+ "optional": true
2222
+ }
2223
+ }
2224
+ },
2225
+ "node_modules/viem/node_modules/@noble/curves": {
2226
+ "version": "1.9.1",
2227
+ "resolved": "https://registry.npmmirror.com/@noble/curves/-/curves-1.9.1.tgz",
2228
+ "integrity": "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==",
2229
+ "license": "MIT",
2230
+ "dependencies": {
2231
+ "@noble/hashes": "1.8.0"
2232
+ },
2233
+ "engines": {
2234
+ "node": "^14.21.3 || >=16"
2235
+ },
2236
+ "funding": {
2237
+ "url": "https://paulmillr.com/funding/"
2238
+ }
2239
+ },
2240
+ "node_modules/viem/node_modules/ws": {
2241
+ "version": "8.18.3",
2242
+ "resolved": "https://registry.npmmirror.com/ws/-/ws-8.18.3.tgz",
2243
+ "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
2244
+ "license": "MIT",
2245
+ "engines": {
2246
+ "node": ">=10.0.0"
2247
+ },
2248
+ "peerDependencies": {
2249
+ "bufferutil": "^4.0.1",
2250
+ "utf-8-validate": ">=5.0.2"
2251
+ },
2252
+ "peerDependenciesMeta": {
2253
+ "bufferutil": {
2254
+ "optional": true
2255
+ },
2256
+ "utf-8-validate": {
2257
+ "optional": true
2258
+ }
2259
+ }
2260
+ },
2261
+ "node_modules/which": {
2262
+ "version": "2.0.2",
2263
+ "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz",
2264
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
2265
+ "license": "ISC",
2266
+ "dependencies": {
2267
+ "isexe": "^2.0.0"
2268
+ },
2269
+ "bin": {
2270
+ "node-which": "bin/node-which"
2271
+ },
2272
+ "engines": {
2273
+ "node": ">= 8"
2274
+ }
2275
+ },
2276
+ "node_modules/which-typed-array": {
2277
+ "version": "1.1.20",
2278
+ "resolved": "https://registry.npmmirror.com/which-typed-array/-/which-typed-array-1.1.20.tgz",
2279
+ "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==",
2280
+ "license": "MIT",
2281
+ "dependencies": {
2282
+ "available-typed-arrays": "^1.0.7",
2283
+ "call-bind": "^1.0.8",
2284
+ "call-bound": "^1.0.4",
2285
+ "for-each": "^0.3.5",
2286
+ "get-proto": "^1.0.1",
2287
+ "gopd": "^1.2.0",
2288
+ "has-tostringtag": "^1.0.2"
2289
+ },
2290
+ "engines": {
2291
+ "node": ">= 0.4"
2292
+ },
2293
+ "funding": {
2294
+ "url": "https://github.com/sponsors/ljharb"
2295
+ }
2296
+ },
2297
+ "node_modules/wrappy": {
2298
+ "version": "1.0.2",
2299
+ "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz",
2300
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
2301
+ "license": "ISC"
2302
+ },
2303
+ "node_modules/ws": {
2304
+ "version": "8.17.1",
2305
+ "resolved": "https://registry.npmmirror.com/ws/-/ws-8.17.1.tgz",
2306
+ "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
2307
+ "license": "MIT",
2308
+ "peer": true,
2309
+ "engines": {
2310
+ "node": ">=10.0.0"
2311
+ },
2312
+ "peerDependencies": {
2313
+ "bufferutil": "^4.0.1",
2314
+ "utf-8-validate": ">=5.0.2"
2315
+ },
2316
+ "peerDependenciesMeta": {
2317
+ "bufferutil": {
2318
+ "optional": true
2319
+ },
2320
+ "utf-8-validate": {
2321
+ "optional": true
2322
+ }
2323
+ }
2324
+ },
2325
+ "node_modules/zod": {
2326
+ "version": "3.25.76",
2327
+ "resolved": "https://registry.npmmirror.com/zod/-/zod-3.25.76.tgz",
2328
+ "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
2329
+ "license": "MIT",
2330
+ "funding": {
2331
+ "url": "https://github.com/sponsors/colinhacks"
2332
+ }
2333
+ },
2334
+ "node_modules/zod-to-json-schema": {
2335
+ "version": "3.25.2",
2336
+ "resolved": "https://registry.npmmirror.com/zod-to-json-schema/-/zod-to-json-schema-3.25.2.tgz",
2337
+ "integrity": "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==",
2338
+ "license": "ISC",
2339
+ "peerDependencies": {
2340
+ "zod": "^3.25.28 || ^4"
2341
+ }
2342
+ }
2343
+ }
2344
+ }
package.json ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "rendergate",
3
+ "version": "1.0.0",
4
+ "description": "Pay-per-render headless browser API powered by x402 micropayments on Stellar",
5
+ "main": "server.js",
6
+ "scripts": {
7
+ "start": "node server.js",
8
+ "demo": "node demo-client.js"
9
+ },
10
+ "keywords": [
11
+ "x402",
12
+ "stellar",
13
+ "render",
14
+ "headless-browser",
15
+ "micropayments"
16
+ ],
17
+ "author": "tantk",
18
+ "license": "MIT",
19
+ "type": "module",
20
+ "dependencies": {
21
+ "@modelcontextprotocol/sdk": "^1.29.0",
22
+ "@stellar/stellar-sdk": "^15.0.1",
23
+ "@x402/core": "^2.9.0",
24
+ "@x402/express": "^2.9.0",
25
+ "@x402/fetch": "^2.9.0",
26
+ "@x402/stellar": "^2.9.0",
27
+ "dotenv": "^17.4.2",
28
+ "express": "^5.2.1",
29
+ "playwright": "^1.59.1"
30
+ },
31
+ "devDependencies": {
32
+ "@trionlabs/stellar8004": "^0.0.11"
33
+ }
34
+ }
refund.js ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import {
2
+ Keypair,
3
+ TransactionBuilder,
4
+ Operation,
5
+ Asset,
6
+ Horizon,
7
+ Memo,
8
+ } from "@stellar/stellar-sdk";
9
+ import { NETWORK_PASSPHRASE, HORIZON_URL, USDC_ISSUER } from "./network-config.js";
10
+
11
+ const USDC = new Asset("USDC", USDC_ISSUER);
12
+
13
+ // Per-payer refund rate limit. Throws off attrition attacks (paying $0.001
14
+ // repeatedly to drain XLM via tx fees) without blocking legitimate users.
15
+ // In-memory only β€” fine for single-instance HF Space; revisit if we scale.
16
+ const REFUND_WINDOW_MS = 60 * 60 * 1000; // 1 hour
17
+ const REFUND_MAX_PER_WINDOW = 10;
18
+ const refundLog = new Map(); // payerAddress -> [timestamp, ...]
19
+
20
+ function isRefundRateLimited(payerAddress) {
21
+ const now = Date.now();
22
+ const cutoff = now - REFUND_WINDOW_MS;
23
+ const history = (refundLog.get(payerAddress) || []).filter((t) => t > cutoff);
24
+ if (history.length >= REFUND_MAX_PER_WINDOW) {
25
+ refundLog.set(payerAddress, history);
26
+ return true;
27
+ }
28
+ history.push(now);
29
+ refundLog.set(payerAddress, history);
30
+ return false;
31
+ }
32
+
33
+ // Periodic prune so the map doesn't grow unbounded.
34
+ setInterval(() => {
35
+ const cutoff = Date.now() - REFUND_WINDOW_MS;
36
+ for (const [addr, history] of refundLog) {
37
+ const kept = history.filter((t) => t > cutoff);
38
+ if (kept.length === 0) refundLog.delete(addr);
39
+ else refundLog.set(addr, kept);
40
+ }
41
+ }, REFUND_WINDOW_MS).unref();
42
+
43
+ const BLOCKED_PATTERNS = [
44
+ "you've been blocked",
45
+ "you have been blocked",
46
+ "blocked by network security",
47
+ "access denied",
48
+ "please log in",
49
+ "log in to",
50
+ "sign in to",
51
+ "enable javascript",
52
+ "just a moment...",
53
+ "checking your browser",
54
+ "performing security verification",
55
+ "ray id:",
56
+ "cloudflare",
57
+ "attention required",
58
+ "please verify you are a human",
59
+ "this page doesn't exist",
60
+ ];
61
+
62
+ export function isFailedRender(content, title) {
63
+ if (!content || content.length < 100) return "empty_content";
64
+
65
+ const lower = content.toLowerCase();
66
+ const titleLower = (title || "").toLowerCase();
67
+
68
+ // Check title for block signals
69
+ if (titleLower === "just a moment..." || titleLower === "blocked") {
70
+ return "blocked_page";
71
+ }
72
+
73
+ // Check content for block/login patterns
74
+ for (const pattern of BLOCKED_PATTERNS) {
75
+ // Only flag if the blocked pattern is a large portion of the content
76
+ // (avoid false positives on pages that mention "log in" in a nav bar)
77
+ if (lower.includes(pattern) && content.length < 500) {
78
+ return "blocked_page";
79
+ }
80
+ }
81
+
82
+ return null; // render is good
83
+ }
84
+
85
+ export async function sendRefund(payerAddress, amount, memo) {
86
+ const serverSecret = process.env.SERVER_SECRET;
87
+ if (!serverSecret) {
88
+ console.error("SERVER_SECRET not set β€” cannot send refund");
89
+ return null;
90
+ }
91
+
92
+ if (isRefundRateLimited(payerAddress)) {
93
+ console.warn(
94
+ `Refund rate-limited for ${payerAddress} (>${REFUND_MAX_PER_WINDOW}/hr) β€” skipping`,
95
+ );
96
+ return null;
97
+ }
98
+
99
+ try {
100
+ const server = new Horizon.Server(HORIZON_URL);
101
+ const keypair = Keypair.fromSecret(serverSecret);
102
+ const account = await server.loadAccount(keypair.publicKey());
103
+
104
+ const tx = new TransactionBuilder(account, {
105
+ fee: "100",
106
+ networkPassphrase: NETWORK_PASSPHRASE,
107
+ })
108
+ .addOperation(
109
+ Operation.payment({
110
+ destination: payerAddress,
111
+ asset: USDC,
112
+ amount: amount,
113
+ }),
114
+ )
115
+ .addMemo(new Memo("text", (memo || "RenderGate refund").slice(0, 28)))
116
+ .setTimeout(30)
117
+ .build();
118
+
119
+ tx.sign(keypair);
120
+ const result = await server.submitTransaction(tx);
121
+ console.log(`Refund sent to ${payerAddress}: ${result.hash}`);
122
+ return result.hash;
123
+ } catch (err) {
124
+ console.error(`Refund failed for ${payerAddress}:`, err.message);
125
+ return null;
126
+ }
127
+ }
renderer.js ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { chromium } from "playwright";
2
+ import { isAllowedUrl } from "./url-policy.js";
3
+
4
+ const MAX_CONCURRENT = 3;
5
+ const MAX_CONTENT_LENGTH = 100_000;
6
+ let browserPromise = null;
7
+ let activeRenders = 0;
8
+
9
+ async function getBrowser() {
10
+ if (!browserPromise) {
11
+ browserPromise = chromium.launch({ headless: true }).catch((err) => {
12
+ browserPromise = null;
13
+ throw err;
14
+ });
15
+ }
16
+ return browserPromise;
17
+ }
18
+
19
+ export async function renderUrl(url, { timeout = 30000, scroll = true } = {}) {
20
+ if (activeRenders >= MAX_CONCURRENT) {
21
+ throw new Error("Too many concurrent renders, try again later");
22
+ }
23
+ activeRenders++;
24
+
25
+ let page;
26
+ try {
27
+ const b = await getBrowser();
28
+ page = await b.newPage();
29
+ } catch (err) {
30
+ activeRenders--;
31
+ browserPromise = null; // Reset on browser failure
32
+ throw new Error(`Browser launch failed: ${err.message}`);
33
+ }
34
+
35
+ try {
36
+ await page.setExtraHTTPHeaders({
37
+ "User-Agent":
38
+ "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
39
+ });
40
+
41
+ // Block requests to private/loopback addresses (catches redirects that
42
+ // would bypass the entry-point URL check). Each subresource β€” main
43
+ // navigation, iframes, fetch/XHR, images β€” runs through isAllowedUrl.
44
+ await page.route("**", (route) => {
45
+ const reqUrl = route.request().url();
46
+ // Allow data:, blob:, about: β€” non-network schemes
47
+ if (!/^https?:/i.test(reqUrl)) {
48
+ return route.continue();
49
+ }
50
+ if (!isAllowedUrl(reqUrl)) {
51
+ return route.abort("blockedbyclient");
52
+ }
53
+ return route.continue();
54
+ });
55
+
56
+ await page.goto(url, { waitUntil: "domcontentloaded", timeout });
57
+
58
+ // Smart wait: poll until content stabilizes
59
+ let prevLen = 0;
60
+ let stableCount = 0;
61
+ for (let i = 0; i < 20; i++) {
62
+ await page.waitForTimeout(250);
63
+ const curLen = await page.evaluate(() => document.body.innerText.length);
64
+ if (curLen === prevLen && curLen > 100) {
65
+ stableCount++;
66
+ if (stableCount >= 2) break;
67
+ } else {
68
+ stableCount = 0;
69
+ }
70
+ prevLen = curLen;
71
+ }
72
+
73
+ // Scroll to trigger lazy-loaded content
74
+ if (scroll) {
75
+ for (let i = 0; i < 3; i++) {
76
+ await page.evaluate(() => window.scrollBy(0, 1000));
77
+ await page.waitForTimeout(500);
78
+ }
79
+ await page.waitForTimeout(500);
80
+ }
81
+
82
+ const extracted = await page.evaluate(() => {
83
+ const remove = document.querySelectorAll(
84
+ 'script, style, nav[aria-label="Footer"], [role="complementary"]',
85
+ );
86
+ remove.forEach((el) => el.remove());
87
+
88
+ const title = document.title;
89
+ const description =
90
+ document.querySelector('meta[name="description"]')?.content ||
91
+ document.querySelector('meta[property="og:description"]')?.content ||
92
+ "";
93
+ const headings = Array.from(
94
+ document.querySelectorAll("h1, h2, h3"),
95
+ (el) => ({ level: el.tagName, text: el.innerText.trim() }),
96
+ ).filter((h) => h.text.length > 0);
97
+ const links = Array.from(
98
+ document.querySelectorAll("a[href]"),
99
+ (el) => ({ text: el.innerText.trim(), href: el.href }),
100
+ )
101
+ .filter((l) => l.text.length > 0 && l.href.startsWith("http"))
102
+ .slice(0, 50);
103
+ const content = document.body.innerText;
104
+
105
+ return { title, description, headings, links, content };
106
+ });
107
+
108
+ if (extracted.content.length > MAX_CONTENT_LENGTH) {
109
+ extracted.content = extracted.content.slice(0, MAX_CONTENT_LENGTH);
110
+ }
111
+
112
+ return {
113
+ title: extracted.title,
114
+ description: extracted.description,
115
+ headings: extracted.headings,
116
+ links: extracted.links,
117
+ content: extracted.content,
118
+ url,
119
+ renderedAt: new Date().toISOString(),
120
+ };
121
+ } catch (err) {
122
+ // If page interaction fails, browser may be dead
123
+ if (err.message?.includes("Target closed") || err.message?.includes("Browser closed")) {
124
+ browserPromise = null;
125
+ }
126
+ throw err;
127
+ } finally {
128
+ activeRenders--;
129
+ await page.close().catch(() => {});
130
+ }
131
+ }
132
+
133
+ export async function closeBrowser() {
134
+ if (browserPromise) {
135
+ const b = await browserPromise.catch(() => null);
136
+ if (b) await b.close().catch(() => {});
137
+ browserPromise = null;
138
+ }
139
+ }
save-demo.js ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import "dotenv/config";
2
+ import { writeFileSync } from "fs";
3
+ import { Transaction, TransactionBuilder } from "@stellar/stellar-sdk";
4
+ import { x402Client, x402HTTPClient } from "@x402/fetch";
5
+ import { createEd25519Signer, getNetworkPassphrase } from "@x402/stellar";
6
+ import { ExactStellarScheme } from "@x402/stellar/exact/client";
7
+
8
+ const SERVER_URL = process.env.SERVER_URL || "https://tantk-rendergate.hf.space";
9
+ const NETWORK = "stellar:testnet";
10
+
11
+ const signer = createEd25519Signer(process.env.DEMO_PRIVATE_KEY, NETWORK);
12
+ const client = new x402Client().register(
13
+ "stellar:*",
14
+ new ExactStellarScheme(signer, { url: "https://soroban-testnet.stellar.org" }),
15
+ );
16
+ const httpClient = new x402HTTPClient(client);
17
+
18
+ async function paidRender(targetUrl) {
19
+ const endpoint = `${SERVER_URL}/render?url=${encodeURIComponent(targetUrl)}`;
20
+ const r1 = await fetch(endpoint);
21
+ if (r1.status !== 402) return await r1.json();
22
+
23
+ const pr = httpClient.getPaymentRequiredResponse((n) => r1.headers.get(n));
24
+ let pp = await client.createPaymentPayload(pr);
25
+ const np = getNetworkPassphrase(NETWORK);
26
+ const tx = new Transaction(pp.payload.transaction, np);
27
+ const sd = tx.toEnvelope().v1()?.tx()?.ext()?.sorobanData();
28
+ if (sd) {
29
+ pp = {
30
+ ...pp,
31
+ payload: {
32
+ ...pp.payload,
33
+ transaction: TransactionBuilder.cloneFrom(tx, {
34
+ fee: "1", sorobanData: sd, networkPassphrase: np,
35
+ }).build().toXDR(),
36
+ },
37
+ };
38
+ }
39
+ const headers = httpClient.encodePaymentSignatureHeader(pp);
40
+ const r2 = await fetch(endpoint, { headers });
41
+ return await r2.json();
42
+ }
43
+
44
+ function formatOutput(data, targetUrl) {
45
+ let out = `=== RenderGate: ${targetUrl} ===\n`;
46
+ out += `Payment: ${data.payment?.price} USDC on ${data.payment?.network}\n`;
47
+ out += `Render time: ${data.renderTimeMs}ms\n\n`;
48
+
49
+ out += `Title: ${data.title}\n`;
50
+ if (data.description) out += `Description: ${data.description}\n`;
51
+ out += `\n`;
52
+
53
+ if (data.headings?.length > 0) {
54
+ out += `Headings (${data.headings.length}):\n`;
55
+ data.headings.slice(0, 15).forEach((h) => {
56
+ out += ` ${h.level}: ${h.text}\n`;
57
+ });
58
+ out += `\n`;
59
+ }
60
+
61
+ if (data.links?.length > 0) {
62
+ out += `Links (${data.links.length}):\n`;
63
+ data.links.slice(0, 15).forEach((l) => {
64
+ out += ` ${l.text.substring(0, 50)} β†’ ${l.href}\n`;
65
+ });
66
+ out += `\n`;
67
+ }
68
+
69
+ if (data.refund) {
70
+ out += `*** AUTO-REFUND ***\n`;
71
+ out += `Reason: ${data.refund.reason}\n`;
72
+ out += `Refund amount: ${data.refund.amount}\n`;
73
+ out += `Refund transaction: ${data.refund.transaction}\n`;
74
+ out += `Verify: https://stellar.expert/explorer/testnet/tx/${data.refund.transaction}\n\n`;
75
+ }
76
+
77
+ out += `Content (${data.content?.length} chars):\n`;
78
+ out += data.content || "(empty)";
79
+ return out;
80
+ }
81
+
82
+ const sites = [
83
+ { name: "1-twitter", url: "https://x.com/stellarorg" },
84
+ { name: "2-linkedin", url: "https://www.linkedin.com/company/stellar-development-foundation" },
85
+ { name: "3-soroswap", url: "https://soroswap.finance" },
86
+ { name: "4-producthunt", url: "https://www.producthunt.com" },
87
+ ];
88
+
89
+ for (const site of sites) {
90
+ console.log(`Rendering ${site.name}...`);
91
+ try {
92
+ const data = await paidRender(site.url);
93
+ const output = formatOutput(data, site.url);
94
+ const path = `demo-output/${site.name}-with.txt`;
95
+ writeFileSync(path, output);
96
+ console.log(` Saved: ${path} (${data.content?.length} chars, refund: ${!!data.refund})`);
97
+ } catch (err) {
98
+ console.error(` Failed: ${err.message}`);
99
+ }
100
+ }
101
+
102
+ console.log("Done!");
scripts/register-8004.js ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // One-time script: register RenderGate as an 8004 agent on Stellar testnet.
2
+ // Re-run safely β€” if metadata changes, use updateAgentUri() instead (see bottom).
3
+ //
4
+ // Usage: node scripts/register-8004.js
5
+ // Requires: AGENT_OWNER_SECRET_TESTNET in .env
6
+
7
+ import "dotenv/config";
8
+ import { Keypair } from "@stellar/stellar-sdk";
9
+ import {
10
+ createClients,
11
+ TESTNET_CONFIG,
12
+ wrapBasicSigner,
13
+ buildMetadataJson,
14
+ toDataUri,
15
+ validateMetadataJson,
16
+ ExplorerClient,
17
+ } from "@trionlabs/stellar8004";
18
+
19
+ const SECRET = process.env.AGENT_OWNER_SECRET_TESTNET;
20
+ if (!SECRET) {
21
+ console.error("ERROR: AGENT_OWNER_SECRET_TESTNET not set in .env");
22
+ process.exit(1);
23
+ }
24
+
25
+ // 1. Build metadata
26
+ const metadata = buildMetadataJson({
27
+ name: "RenderGate",
28
+ description:
29
+ "Pay-per-render headless browser API for AI agents. Renders JS-heavy pages (Twitter, LinkedIn, SPAs) and returns structured content. Auto-refunds when pages are blocked.",
30
+ imageUrl: "https://tantk.github.io/rendergate-githubpage/logo.png",
31
+ services: [
32
+ {
33
+ name: "x402",
34
+ endpoint: "https://tantk-rendergate.hf.space/render",
35
+ version: "1.0",
36
+ description:
37
+ "Render a JS-heavy webpage and return title, description, headings, links, and full text content. $0.001 USDC per render.",
38
+ inputExample: '{"url": "https://x.com/stellarorg"}',
39
+ },
40
+ {
41
+ name: "mcp",
42
+ endpoint: "https://tantk-rendergate.hf.space/render",
43
+ },
44
+ ],
45
+ supportedTrust: ["reputation"],
46
+ x402Enabled: true,
47
+ });
48
+
49
+ console.log("Metadata to register:");
50
+ console.log(JSON.stringify(metadata, null, 2));
51
+ console.log();
52
+
53
+ validateMetadataJson(metadata);
54
+ const dataUri = toDataUri(metadata);
55
+ console.log(`Data URI size: ${dataUri.length} bytes (limit 8KB)\n`);
56
+
57
+ // 2. Set up signer + clients
58
+ const keypair = Keypair.fromSecret(SECRET);
59
+ const signer = wrapBasicSigner(keypair, TESTNET_CONFIG.networkPassphrase);
60
+ const { identity } = createClients(TESTNET_CONFIG, signer);
61
+
62
+ console.log(`Owner address: ${keypair.publicKey()}`);
63
+ console.log("Submitting register_with_uri to testnet Identity Registry...\n");
64
+
65
+ // 3. Register on-chain
66
+ const tx = await identity.register_with_uri({
67
+ caller: keypair.publicKey(),
68
+ agent_uri: dataUri,
69
+ });
70
+ const sent = await tx.signAndSend();
71
+ const agentId = sent.result;
72
+
73
+ console.log(`βœ“ Registered! Agent ID: ${agentId}`);
74
+ console.log(` Tx hash: ${sent.getTransactionResponse?.hash || "(see logs)"}`);
75
+ console.log();
76
+ console.log("Save this ID β€” it's your agent's permanent identifier:");
77
+ console.log(` AGENT_ID=${agentId}`);
78
+ console.log();
79
+ console.log(
80
+ `Explorer page (allow ~30-60s for indexing): https://stellar8004.com/agents/${agentId}`,
81
+ );
82
+
83
+ // 4. Optional: verify via explorer once indexed
84
+ const explorer = new ExplorerClient();
85
+ console.log("\nWaiting 5s, then querying explorer...");
86
+ await new Promise((r) => setTimeout(r, 5000));
87
+ try {
88
+ const agent = await explorer.getAgent(agentId);
89
+ console.log("Explorer record:", agent ? "found" : "not yet indexed");
90
+ } catch (err) {
91
+ console.log("Explorer query:", err.message);
92
+ }
scripts/setup-agent-keypair.js ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // One-time: generate a fresh Stellar testnet keypair, fund it via friendbot,
2
+ // and print the keys so you can save them to .env.
3
+
4
+ import { Keypair } from "@stellar/stellar-sdk";
5
+
6
+ const kp = Keypair.random();
7
+ const pub = kp.publicKey();
8
+ const sec = kp.secret();
9
+
10
+ console.log("Generated new testnet keypair:");
11
+ console.log(` Public: ${pub}`);
12
+ console.log(` Secret: ${sec}`);
13
+ console.log();
14
+
15
+ console.log("Funding via friendbot...");
16
+ const res = await fetch(`https://friendbot.stellar.org?addr=${pub}`);
17
+ if (!res.ok) {
18
+ console.error(`Friendbot failed: ${res.status}`);
19
+ console.error(await res.text());
20
+ process.exit(1);
21
+ }
22
+ console.log("βœ“ Funded with 10,000 testnet XLM");
23
+ console.log();
24
+
25
+ console.log("Add to .env:");
26
+ console.log(` AGENT_OWNER_SECRET_TESTNET=${sec}`);
27
+ console.log();
28
+ console.log(`Verify: https://stellar.expert/explorer/testnet/account/${pub}`);
scripts/verify-8004.js ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Query the testnet Identity Registry to confirm our agent ID and owner.
2
+ import {
3
+ TESTNET_CONFIG,
4
+ createClients,
5
+ wrapBasicSigner,
6
+ } from "@trionlabs/stellar8004";
7
+ import { Keypair } from "@stellar/stellar-sdk";
8
+
9
+ const SECRET = process.env.AGENT_OWNER_SECRET_TESTNET;
10
+ if (!SECRET) {
11
+ console.error("Set AGENT_OWNER_SECRET_TESTNET");
12
+ process.exit(1);
13
+ }
14
+
15
+ const kp = Keypair.fromSecret(SECRET);
16
+ const signer = wrapBasicSigner(kp, TESTNET_CONFIG.networkPassphrase);
17
+ const { identity } = createClients(TESTNET_CONFIG, signer);
18
+
19
+ console.log(`My address: ${kp.publicKey()}`);
20
+
21
+ // Total agents
22
+ const totalTx = await identity.total_agents();
23
+ console.log(`total_agents(): ${totalTx.result}`);
24
+
25
+ // Walk back from total_agents()-1 to find ones we own
26
+ const total = Number(totalTx.result);
27
+ console.log(`\nScanning agents [0..${total - 1}] for ownership...`);
28
+
29
+ for (let id = Math.max(0, total - 5); id < total; id++) {
30
+ try {
31
+ const ownerTx = await identity.find_owner({ agent_id: id });
32
+ const uriTx = await identity.agent_uri({ agent_id: id });
33
+ const owner = ownerTx.result;
34
+ const uri = uriTx.result;
35
+ const mine = owner === kp.publicKey() ? " ← OWNED BY ME" : "";
36
+ console.log(
37
+ ` agent ${id}: owner=${owner?.slice(0, 8) || "?"}... uri=${(uri || "").slice(0, 60)}...${mine}`,
38
+ );
39
+ } catch (err) {
40
+ console.log(` agent ${id}: ${err.message}`);
41
+ }
42
+ }
server.js ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import "dotenv/config";
2
+ import express from "express";
3
+ import { paymentMiddlewareFromConfig } from "@x402/express";
4
+ import { HTTPFacilitatorClient } from "@x402/core/server";
5
+ import { ExactStellarScheme } from "@x402/stellar/exact/server";
6
+ import { Transaction, Address } from "@stellar/stellar-sdk";
7
+ import { renderUrl, closeBrowser } from "./renderer.js";
8
+ import { isFailedRender, sendRefund } from "./refund.js";
9
+ import { NETWORK, NETWORK_PASSPHRASE, FACILITATOR_URL } from "./network-config.js";
10
+ import { isAllowedUrl } from "./url-policy.js";
11
+
12
+ const PORT = process.env.PORT || 3001;
13
+ const PRICE = "$0.001";
14
+ const REFUND_AMOUNT = "0.001";
15
+ const PAY_TO = process.env.PAY_TO;
16
+
17
+ if (!PAY_TO) {
18
+ console.error("ERROR: PAY_TO not set in .env");
19
+ process.exit(1);
20
+ }
21
+
22
+ // Extract payer from the payment-signature request header.
23
+ // x402 payments are exactly one InvokeHostFunction op calling USDC.transfer
24
+ // with one auth entry whose address is the payer. Reject anything that doesn't
25
+ // match this exact shape β€” we don't want to refund ambiguous transactions.
26
+ function getPayerAddress(req) {
27
+ try {
28
+ const header = req.get("payment-signature") || req.get("x-payment");
29
+ if (!header) return null;
30
+ const decoded = JSON.parse(Buffer.from(header, "base64").toString());
31
+ const txXdr = decoded?.payload?.transaction;
32
+ if (!txXdr) return null;
33
+ const tx = new Transaction(txXdr, NETWORK_PASSPHRASE);
34
+ if (tx.operations.length !== 1) return null;
35
+ const op = tx.operations[0];
36
+ if (op.type !== "invokeHostFunction") return null;
37
+ if (!op.auth || op.auth.length !== 1) return null;
38
+ const creds = op.auth[0].credentials();
39
+ if (creds.switch().name !== "sorobanCredentialsAddress") return null;
40
+ return Address.fromScAddress(creds.address().address()).toString();
41
+ } catch {
42
+ return null;
43
+ }
44
+ }
45
+
46
+ const app = express();
47
+
48
+ // Info endpoint (free)
49
+ app.get("/", (_, res) =>
50
+ res.json({
51
+ service: "RenderGate",
52
+ description: "Pay-per-render headless browser API on Stellar x402",
53
+ price: PRICE,
54
+ network: NETWORK,
55
+ usage: "GET /render?url=<encoded_url>",
56
+ }),
57
+ );
58
+
59
+ // Health check (free)
60
+ app.get("/health", (_, res) => res.json({ status: "ok" }));
61
+
62
+ // URL validation β€” runs before payment to reject SSRF attempts early
63
+ app.use("/render", (req, res, next) => {
64
+ const url = req.query.url;
65
+ if (!url) return res.status(400).json({ error: "Missing ?url= parameter" });
66
+ let decoded;
67
+ try {
68
+ decoded = decodeURIComponent(url);
69
+ } catch {
70
+ return res.status(400).json({ error: "Malformed URL encoding" });
71
+ }
72
+ if (!isAllowedUrl(decoded)) {
73
+ return res
74
+ .status(400)
75
+ .json({ error: "URL not allowed β€” only public http/https URLs" });
76
+ }
77
+ req.decodedUrl = decoded;
78
+ next();
79
+ });
80
+
81
+ // x402 payment middleware β€” protects /render
82
+ app.use(
83
+ paymentMiddlewareFromConfig(
84
+ {
85
+ "GET /render": {
86
+ accepts: {
87
+ scheme: "exact",
88
+ price: PRICE,
89
+ network: NETWORK,
90
+ payTo: PAY_TO,
91
+ maxTimeoutSeconds: 60,
92
+ },
93
+ description: "Render a JS-heavy webpage and return extracted content",
94
+ },
95
+ },
96
+ new HTTPFacilitatorClient({ url: FACILITATOR_URL }),
97
+ [{ network: NETWORK, server: new ExactStellarScheme() }],
98
+ ),
99
+ );
100
+
101
+ // Protected render endpoint
102
+ app.get("/render", async (req, res) => {
103
+ const decoded = req.decodedUrl;
104
+
105
+ try {
106
+ console.log(`Rendering: ${decoded}`);
107
+ const start = Date.now();
108
+ const result = await renderUrl(decoded);
109
+ const elapsed = Date.now() - start;
110
+
111
+ const failReason = isFailedRender(result.content, result.title);
112
+ if (failReason) {
113
+ const payerAddress = getPayerAddress(req);
114
+ let refund = null;
115
+ if (payerAddress) {
116
+ console.log(`Bad render (${failReason}) for ${decoded} β€” refunding ${payerAddress}`);
117
+ const refundHash = await sendRefund(payerAddress, REFUND_AMOUNT, `refund:${failReason}`);
118
+ refund = refundHash
119
+ ? { transaction: refundHash, amount: `${REFUND_AMOUNT} USDC`, reason: failReason }
120
+ : { error: "Refund failed β€” contact support", reason: failReason };
121
+ }
122
+
123
+ return res.json({
124
+ ...result,
125
+ renderTimeMs: elapsed,
126
+ payment: { price: PRICE, network: NETWORK },
127
+ refund,
128
+ });
129
+ }
130
+
131
+ res.json({
132
+ ...result,
133
+ renderTimeMs: elapsed,
134
+ payment: { price: PRICE, network: NETWORK },
135
+ });
136
+ } catch (err) {
137
+ console.error(`Render failed for ${decoded}:`, err.message);
138
+ if (err.message.includes("Too many concurrent")) {
139
+ return res.status(503).json({ error: err.message });
140
+ }
141
+ // Attempt refund on crash
142
+ const payerAddress = getPayerAddress(req);
143
+ let refund = null;
144
+ if (payerAddress) {
145
+ const refundHash = await sendRefund(payerAddress, REFUND_AMOUNT, "refund:render_crash");
146
+ refund = refundHash
147
+ ? { transaction: refundHash, amount: `${REFUND_AMOUNT} USDC`, reason: "render_crash" }
148
+ : { error: "Refund failed β€” contact support" };
149
+ }
150
+ res.status(500).json({ error: "Render failed", message: err.message, refund });
151
+ }
152
+ });
153
+
154
+ const server = app.listen(Number(PORT), () => {
155
+ console.log(`RenderGate listening on http://localhost:${PORT}`);
156
+ console.log(` Pay ${PRICE} USDC on ${NETWORK} per render`);
157
+ console.log(` Payments go to ${PAY_TO}`);
158
+ });
159
+
160
+ for (const sig of ["SIGTERM", "SIGINT"]) {
161
+ process.on(sig, async () => {
162
+ console.log(`${sig} received, shutting down...`);
163
+ server.close();
164
+ await closeBrowser();
165
+ process.exit(0);
166
+ });
167
+ }
url-policy.js ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Shared URL policy. Used both at request entry (server.js) and per-request
2
+ // inside the renderer (renderer.js) so redirects to private IPs are blocked.
3
+
4
+ const PRIVATE_HOSTNAMES = new Set([
5
+ "localhost",
6
+ "127.0.0.1",
7
+ "0.0.0.0",
8
+ "[::1]",
9
+ "::1",
10
+ ]);
11
+
12
+ /**
13
+ * Returns true if `urlStr` is a public http(s) URL we're willing to fetch.
14
+ * Rejects: non-http(s) schemes, localhost, IPv6 literals, RFC1918 IPv4,
15
+ * link-local, and anything that fails to parse.
16
+ */
17
+ export function isAllowedUrl(urlStr) {
18
+ let parsed;
19
+ try {
20
+ parsed = new URL(urlStr);
21
+ } catch {
22
+ return false;
23
+ }
24
+ if (!["http:", "https:"].includes(parsed.protocol)) return false;
25
+
26
+ const host = parsed.hostname;
27
+ if (PRIVATE_HOSTNAMES.has(host)) return false;
28
+ if (host.startsWith("[")) return false; // any IPv6 literal β€” overly cautious by design
29
+ if (host === "::1") return false;
30
+
31
+ // RFC1918 + link-local IPv4 ranges
32
+ const parts = host.split(".");
33
+ if (parts[0] === "10") return false;
34
+ if (parts[0] === "172" && +parts[1] >= 16 && +parts[1] <= 31) return false;
35
+ if (parts[0] === "192" && parts[1] === "168") return false;
36
+ if (parts[0] === "169" && parts[1] === "254") return false;
37
+
38
+ return true;
39
+ }