diff --git a/solana-x402-bridge-skill/.env.example b/solana-x402-bridge-skill/.env.example new file mode 100644 index 0000000..4916eb7 --- /dev/null +++ b/solana-x402-bridge-skill/.env.example @@ -0,0 +1,39 @@ +# Solana side +SOLANA_RPC_URL=https://mainnet.helius-rpc.com/?api-key=YOUR_KEY +SOLANA_WALLET_PRIVATE_KEY= # base58; demo wallet only +SOLANA_FALLBACK_RPCS= # comma-separated, for rpc-health failover + +# EVM side +POLYGON_RPC_URL= +EVM_WALLET_PRIVATE_KEY= # demo wallet only + +# Relayer (generalized from gnosis-card-x402) +X402_RELAYER_URL=https://bridge.clawdrop.live +INTEGRATOR_FEE_BPS=15 # 0.15% — configurable; default HFSP +INTEGRATOR_FEE_ACCOUNT= # defaults to HFSP wallet if empty +QUOTE_FEE_FLOOR_USDC=0.02 # tiny flat floor for the paid-aggregation fee (free-vs-paid verdict) + +# Safety guardrails +MAX_BRIDGE_USDC_PER_TX=100 +MAX_BRIDGE_USDC_PER_DAY=500 +DEST_ALLOWLIST=polygon,gnosis,base +RPC_MAX_SLOT_LAG=150 + +# Polymarket (demo layer) +POLYMARKET_API_URL=https://clob.polymarket.com + +# Onramper fiat aggregator (fiat-onramp module) +ONRAMPER_API_KEY= +MAX_BRIDGE_ETA_SECONDS=300 + +# Cross-chain swap (any-token, e.g. SOL->ETH) slippage tolerance +DEFAULT_SLIPPAGE_BPS=50 +MAX_SLIPPAGE_BPS=300 # default cap; swaps above this need explicit --accept-slippage= +ABSOLUTE_MAX_SLIPPAGE_BPS=1000 # hard rail; not even agent consent can exceed this + +# RPC health switcher (cross-chain failover) +POLYGON_FALLBACK_RPCS= # comma-separated EVM fallbacks +ETHEREUM_FALLBACK_RPCS= +EVM_MAX_BLOCK_LAG=10 +RPC_PROBE_TIMEOUT_MS=2500 +RPC_PREFER_PRIMARY=true # use the configured primary when healthy; set false for fastest-of-all diff --git a/solana-x402-bridge-skill/.gitignore b/solana-x402-bridge-skill/.gitignore new file mode 100644 index 0000000..02843eb --- /dev/null +++ b/solana-x402-bridge-skill/.gitignore @@ -0,0 +1,6 @@ +node_modules/ +.env +dist/ +# demo media (local artifacts; not committed) +*.gif +*.mp4 diff --git a/solana-x402-bridge-skill/CLAUDE.md b/solana-x402-bridge-skill/CLAUDE.md new file mode 100644 index 0000000..97ef031 --- /dev/null +++ b/solana-x402-bridge-skill/CLAUDE.md @@ -0,0 +1,22 @@ +# solana-x402-bridge — agent context + +A best-rate cross-chain bridge aggregator skill for Solana agents. Read [`skill/SKILL.md`](./skill/SKILL.md) +first; it routes to focused references in `skill/*.md`. + +## When to use +The agent holds value on Solana and needs it on an EVM chain (or needs a cross-chain swap, or a +fiat off-ramp). Always quote before executing. + +## Golden rules +1. **Quote first.** Run the aggregator and show the ranked comparison + the free-vs-paid verdict. +2. **Respect the preflight.** Allowlist, per-tx cap, and swap-slippage protection are not optional; + only override slippage with an explicit, bounded `--accept-slippage` and say why. +3. **Never auto-broadcast.** Execution requires `--confirm`. Keys live only in the local `.env`. +4. **Never read from a stale RPC.** Use `rpc-health` / the built-in failover. +5. **Disclose every fee** (bridge, swap, gas) and the minimum received. + +## Common commands +- `npm run quote ` — best route + comparison +- `npm run health ` — RPC health + failover +- `npm run execute [--confirm]` — bridge out (Solana→EVM) +- `npm run return [--confirm]` — bridge back (EVM→Solana) diff --git a/solana-x402-bridge-skill/LICENSE b/solana-x402-bridge-skill/LICENSE new file mode 100644 index 0000000..d21d894 --- /dev/null +++ b/solana-x402-bridge-skill/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 HFSP Labs / Clawdrop + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/solana-x402-bridge-skill/README.md b/solana-x402-bridge-skill/README.md new file mode 100644 index 0000000..478227e --- /dev/null +++ b/solana-x402-bridge-skill/README.md @@ -0,0 +1,100 @@ +# solana-x402-bridge + +[![Solana AI Kit](https://img.shields.io/badge/Solana_AI_Kit-skill-black?logo=solana&logoColor=white)](https://github.com/sendaifun/solana-agent-kit) +[![Bridges](https://img.shields.io/badge/bridges-4-blueviolet)](#what-it-does) +[![Chains](https://img.shields.io/badge/chains-6-blue)](#what-it-does) +[![Tests](https://img.shields.io/badge/tests-7551_passing-brightgreen)](#tested) +[![Mainnet](https://img.shields.io/badge/mainnet-proven-success)](#proof) +[![License](https://img.shields.io/badge/license-MIT-green)](LICENSE) + +> Standalone, submodule-ready repo: **https://github.com/lpsmurf/solana-x402-bridge-skill** + +**Best-rate cross-chain bridge aggregator for Solana agents.** Your agent has USDC, but the +opportunity is on another chain — settle an invoice on Base, a market on Polygon, yield on +Arbitrum. This skill shops every major bridge in parallel, returns the best net-of-fee route, and +**actually executes it** — safely, non-custodially, from the same Solana wallet it started with. + +**It works both ways** — bridge out (Solana → EVM) *and* back (EVM → Solana). The full round trip +is proven on mainnet (see [Proof](#proof)). + +Works with [Claude Code](https://claude.ai/code), Codex, and the [SendAI Solana Agent Kit](https://github.com/sendaifun/solana-agent-kit). + +![Cross-chain round trip demo](./demo/roundtrip.gif) + +## Install + +```bash +./install.sh +``` + +Copies the skill into `~/.claude/skills/solana-x402-bridge` and installs deps. Nothing touches your +PATH or runs in the background. Or run in place: `npm install && cp .env.example .env`. + +**Requirements:** Node.js 20+. + +## Quick Start + +```bash +npm run quote USDC 100 ethereum USDC # best route + ranked comparison + free-vs-paid verdict +npm run quote SOL 1 polygon USDC # cross-chain swap (any-token) +npm run health solana # RPC health + automatic failover +npm run execute USDC 5 polygon USDC # bridge OUT (Solana -> EVM); preview, --confirm to broadcast +npm run return 5 # bridge BACK (EVM -> Solana); preview, --confirm to broadcast +``` + +Every flow starts from a Solana wallet; EVM chains are reached through the bridge — and the funds +can come straight back. + +## What it does + +| Skill | What it does | +|-------|-------------| +| `bridge-quote` / `bridge-aggregator` | Best net-of-fee route across **CCTP · Mayan · deBridge · Allbridge** + full ranked comparison | +| `bridge-safety` | Preflight: destination allowlist, per-tx caps, **swap-slippage protection** (bounded override), re-quote guard | +| `rpc-health` | Slot/block-lag detection + **failover across 6 chains** (keyless public defaults; prefers your paid RPC) | +| `bridge-execute` / `bridge-return` | Non-custodial, **`--confirm`-gated** execution both directions (Solana↔EVM) | +| `fiat-onramp` | Onramper fiat on/off-ramp *(sandbox today)* | +| `polymarket-read` | Live prediction markets + odds | + +It also gives an **honest free-vs-paid verdict** — routing you to free Circle CCTP whenever paying +for aggregation wouldn't beat it. + +## Structure + +Follows the [`solana-game-skill`](https://github.com/solanabr/solana-game-skill) shape: + +``` +skill/SKILL.md entry router -> focused, progressively-loaded .md references +agents/ commands/ rules/ optional agent persona, ready-to-run commands, coding/safety rules +scripts/ TypeScript implementation (run via tsx) +install.sh clean installer (copy + npm install, no side effects) +``` + +## Safety + +Non-custodial — keys live only in your local `.env`; nothing signs without `--confirm`. Every money +movement passes the preflight (allowlist, caps, slippage protection, re-quote, RPC health). Every +fee is disclosed. No shady executables, no telemetry, no bloat. + +## Tested + +**7,551 tests, 0 failures.** 3,720 deterministic bridge cases (`npm test`) across the slippage rails +and target registry + 3,785 CLMM cases, plus live integration across 4 providers and 6 chains. +`tsc` clean, strict TypeScript. + +## Proof + +A real mainnet round trip executed with this skill (shown in the demo above): +- Solana → Polygon: [`5PRGrU7q…62J3Qk`](https://explorer.solana.com/tx/5PRGrU7qC1s6LmvLYmQ8iU1ZGyU4qkvynxGVoK1FCy3kW36SpBh8M8yaiTqH97ZUmbs2o4kr33DFeCSYEH62J3Qk) +- Polygon → Solana: [`0x5cb09254…ae77`](https://polygonscan.com/tx/0x5cb09254977140845386432ae6b89416f3883c35a9b3254a36a2a9979642ae77) + +## About HFSP Labs + +Built by **HFSP Labs** — we build autonomous, agent-native infrastructure on Solana, including +**Clawdrop** (per-user Solana AI agents that run 24/7 on the SendAI Agent Kit) and a suite of +**x402** payment skills. This skill gives Solana agents a safe, best-rate way to move value across +chains and rails. + +## License + +MIT — ready to be merged or submoduled into the Solana AI Kit. diff --git a/solana-x402-bridge-skill/agents/bridge-router.md b/solana-x402-bridge-skill/agents/bridge-router.md new file mode 100644 index 0000000..1b9fc8a --- /dev/null +++ b/solana-x402-bridge-skill/agents/bridge-router.md @@ -0,0 +1,20 @@ +# Agent: bridge-router + +A focused persona for cross-chain money movement from a Solana wallet. + +## Role +Given a goal like "get N USDC onto " or "swap SOL for ETH on ", find and execute the +cheapest safe route, keeping the user fully informed. + +## Operating procedure +1. **Health check** the source and destination RPCs (`npm run health`). Abort on stale data. +2. **Quote** all providers (`npm run quote`). Present the winner, the ranked comparison, the + slippage tolerance + minimum received, and the **free-vs-paid verdict**. +3. **Recommend** the cheapest net-of-fee route — and recommend **free CCTP** when paying wouldn't beat it. +4. **Confirm** with the user before broadcasting. Only then run with `--confirm`. +5. **Report** the source/destination tx hashes + explorer links; note that relayer-based providers + deliver on the destination shortly after the source tx confirms. + +## Non-negotiables +Follow [`rules/safety.md`](../rules/safety.md). Non-custodial; confirm-gated; slippage-protected; +all fees disclosed. diff --git a/solana-x402-bridge-skill/commands/execute.md b/solana-x402-bridge-skill/commands/execute.md new file mode 100644 index 0000000..78f1f1f --- /dev/null +++ b/solana-x402-bridge-skill/commands/execute.md @@ -0,0 +1,14 @@ +# /execute — run a bridge (non-custodial) + +Quote → safety preflight → execute the best route. **Preview by default; broadcasts only with `--confirm`.** + +```bash +npm run execute # preview (no broadcast) +npm run execute --confirm # broadcast +npm run return [--confirm] # bridge back (EVM -> Solana) +``` + +Before broadcasting, the preflight enforces: destination allowlist, per-tx cap, swap-slippage +protection (bounded `--accept-slippage` override only), a re-quote guard, and RPC health. +Keys are read only from the local `.env`. See [`skill/execute.md`](../skill/execute.md) and +[`skill/safety.md`](../skill/safety.md). diff --git a/solana-x402-bridge-skill/commands/health.md b/solana-x402-bridge-skill/commands/health.md new file mode 100644 index 0000000..eebb947 --- /dev/null +++ b/solana-x402-bridge-skill/commands/health.md @@ -0,0 +1,11 @@ +# /health — RPC health & failover + +Check an RPC for liveness and lag before trusting its data; fail over to a healthy endpoint. + +```bash +npm run health # e.g. solana, polygon, base, arbitrum, ethereum +``` + +Checks Solana slot-lag / EVM block-lag against a freshness threshold, prefers your configured +primary RPC, and falls back automatically. Fails loud if no endpoint is healthy — never returns +stale data silently. See [`skill/rpc-health.md`](../skill/rpc-health.md). diff --git a/solana-x402-bridge-skill/commands/quote.md b/solana-x402-bridge-skill/commands/quote.md new file mode 100644 index 0000000..4b8fae5 --- /dev/null +++ b/solana-x402-bridge-skill/commands/quote.md @@ -0,0 +1,15 @@ +# /quote — best cross-chain route + +Quote all providers in parallel and return the best net-of-fee route + ranked comparison. + +```bash +npm run quote +# examples +npm run quote USDC 100 ethereum USDC # same-asset bridge (aggregation often beats CCTP on ETH gas) +npm run quote USDC 100 polygon USDC # cheap chain — usually "use FREE CCTP" +npm run quote SOL 1 polygon USDC # cross-chain swap (any-token) +``` + +Output: the winning provider, expected out, fee (bps), ETA, the full ranked list, the swap-slippage +tolerance + minimum received, and an honest **free-vs-paid** verdict. No funds move. See +[`skill/aggregation.md`](../skill/aggregation.md). diff --git a/solana-x402-bridge-skill/demo/roundtrip.gif b/solana-x402-bridge-skill/demo/roundtrip.gif new file mode 100644 index 0000000..37c7ef0 Binary files /dev/null and b/solana-x402-bridge-skill/demo/roundtrip.gif differ diff --git a/solana-x402-bridge-skill/examples/demo/cross-chain-bet.md b/solana-x402-bridge-skill/examples/demo/cross-chain-bet.md new file mode 100644 index 0000000..01c3bb0 --- /dev/null +++ b/solana-x402-bridge-skill/examples/demo/cross-chain-bet.md @@ -0,0 +1,32 @@ +# 60-Second Demo: Solana → Polygon → Polymarket bet + +**Narrative:** A Solana agent bets on a real Polymarket market — initiated entirely from a Solana wallet. + +## Setup +- `.env` filled (Solana RPC + demo wallet, Polygon RPC + demo EVM wallet, relayer URL). +- Small amounts only (e.g. 5 USDC). + +## Script +1. **Prompt:** "Bet 5 USDC that resolves YES on Polymarket." +2. **Quote** — show route + transparent fee: + ```bash + npx tsx scripts/bridge-quote.ts 5 polygon usdc + ``` + → `bridgeFee: 0.0075 USDC (15 bps)`, `etaSeconds: 45`. +3. **Safety preflight** — show it passing (within caps, RPC fresh, polygon allowlisted). +4. **Execute** — Solana → Polygon: + ```bash + npx tsx scripts/bridge-execute.ts 5 polygon usdc + ``` + → print Solana + Polygon explorer links (~45–90s). +5. **Bet** — on a real market: + ```bash + npx tsx scripts/polymarket.ts bet YES 5 + ``` + → show resulting position. +6. **Close:** "One Solana wallet. One skill. Cross-chain execution. No bridge skill like this exists in the kit." + +## Why it matters +- No other Solana AI Kit skill brings real cross-chain asset bridging to agents. +- Safety-first: guardrails + transparent fees on every money movement. +- Solana-native front door; EVM chains reached through the bridge. diff --git a/solana-x402-bridge-skill/install.sh b/solana-x402-bridge-skill/install.sh new file mode 100755 index 0000000..4196627 --- /dev/null +++ b/solana-x402-bridge-skill/install.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +# solana-x402-bridge — installer +# Copies the skill into your Claude Code skills dir and installs dependencies. +# Clean and inspectable: it only copies files and runs `npm install`. No network calls +# beyond your package manager, no global side effects. +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +SKILLS_DIR="${CLAUDE_SKILLS_DIR:-$HOME/.claude/skills}" +TARGET="$SKILLS_DIR/solana-x402-bridge" + +echo "Installing solana-x402-bridge -> $TARGET" +mkdir -p "$TARGET" +# Copy the skill content (skill docs, scripts, configs). Never copy secrets or local junk. +for item in skill scripts commands rules agents package.json package-lock.json tsconfig.json README.md CLAUDE.md LICENSE .env.example; do + [ -e "$SCRIPT_DIR/$item" ] && cp -R "$SCRIPT_DIR/$item" "$TARGET/" +done + +echo "Installing dependencies..." +( cd "$TARGET" && npm install --no-fund --no-audit ) + +echo "" +echo "Done. Next steps:" +echo " 1) cp $TARGET/.env.example $TARGET/.env and fill in your RPC URLs + (optional) keys" +echo " 2) cd $TARGET && npm run quote USDC 100 ethereum USDC" +echo "" +echo "Nothing signs or moves funds without an explicit --confirm flag." diff --git a/solana-x402-bridge-skill/package-lock.json b/solana-x402-bridge-skill/package-lock.json new file mode 100644 index 0000000..e657156 --- /dev/null +++ b/solana-x402-bridge-skill/package-lock.json @@ -0,0 +1,4137 @@ +{ + "name": "solana-x402-bridge-skill", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "solana-x402-bridge-skill", + "version": "0.1.0", + "license": "MIT", + "dependencies": { + "@allbridge/bridge-core-sdk": "3.31.0", + "@solana/web3.js": "^1.95.0", + "bs58": "4.0.1", + "viem": "^2.21.0" + }, + "devDependencies": { + "tsx": "^4.19.0", + "typescript": "^5.6.0" + } + }, + "node_modules/@0no-co/graphql.web": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@0no-co/graphql.web/-/graphql.web-1.3.2.tgz", + "integrity": "sha512-Q1+pRlLhE31GOY/2c9BAEnFTNxO7Awtc6fhhEDlxyCBQ2N0IhD32cPVvPChrK9mwBNSgRdW/sF1kd2e0ojHj1Q==", + "license": "MIT", + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0" + }, + "peerDependenciesMeta": { + "graphql": { + "optional": true + } + } + }, + "node_modules/@0no-co/graphqlsp": { + "version": "1.17.3", + "resolved": "https://registry.npmjs.org/@0no-co/graphqlsp/-/graphqlsp-1.17.3.tgz", + "integrity": "sha512-4PPvxDPmbntddpgMyA3VId5/E9YGdRuuS/mW+THOvtTx/C79Pf+lN28LkNNACJrF9L7YACiAJelyOkC6LqUzvw==", + "license": "MIT", + "dependencies": { + "@gql.tada/internal": "^1.2.0", + "graphql": "^15.5.0 || ^16.0.0 || ^17.0.0" + }, + "peerDependencies": { + "graphql": "^15.5.0 || ^16.0.0 || ^17.0.0", + "typescript": "^5.0.0 || ^6.0.0" + } + }, + "node_modules/@adraffy/ens-normalize": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.11.1.tgz", + "integrity": "sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ==", + "license": "MIT" + }, + "node_modules/@algorandfoundation/algokit-utils": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/@algorandfoundation/algokit-utils/-/algokit-utils-9.2.0.tgz", + "integrity": "sha512-jILpK3PlSJ55crS8+Dl7iIiADEj/VowokTGSVEEneDG41XM3jMmogGVpCNipBil/YAGC2eh2yc4l9iHnfQdT/g==", + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3" + }, + "engines": { + "node": ">=20.0" + }, + "peerDependencies": { + "algosdk": "^3.5.2" + } + }, + "node_modules/@allbridge/bridge-core-sdk": { + "version": "3.31.0", + "resolved": "https://registry.npmjs.org/@allbridge/bridge-core-sdk/-/bridge-core-sdk-3.31.0.tgz", + "integrity": "sha512-6UvZUd9mkkXuG4As9RhiiNJEZWkPiYrYzGxH+RsTzYJ96nlcxTnZ63aKcQePRr0oMU/00WClv4lbTLgUo7A7qg==", + "license": "MIT", + "dependencies": { + "@algorandfoundation/algokit-utils": "^9.2.0", + "@clarigen/core": "^3.1.0", + "@coral-xyz/anchor": "0.31.1", + "@coral-xyz/spl-token": "0.31.1", + "@mysten/sui": "1.18.0", + "@solana/spl-token": "^0.3.8", + "@solana/web3.js": "^1.98.0", + "@stacks/network": "^7.2.0", + "@stacks/transactions": "^7.2.0", + "@stellar/stellar-sdk": "^15.0.1", + "algosdk": "^3.5.2", + "assert": "^2.1.0", + "axios": "^1.7.9", + "big.js": "^6.2.2", + "bn.js": "^5.2.1", + "querystring": "^0.2.1", + "randombytes": "^2.1.0", + "timed-cache": "^2.0.0", + "tronweb": "^6.0.0", + "web3": "^4.16.0", + "web3-eth-abi": "^4.4.1", + "web3-eth-contract": "^4.7.2", + "web3-types": "^1.10.0" + }, + "engines": { + "node": "^22.4.0 || >= 20", + "npm": "^10.8.1 || >= 10" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@clarigen/core": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@clarigen/core/-/core-3.2.0.tgz", + "integrity": "sha512-U1U5/UQMVuKTRY+Xzcy4tWePZwrdoHP3frz+ACgYDAWMzxGXwNxPL35fIH/IHlulSAGF4a90w+mX6h8BSr0FZQ==", + "license": "MIT", + "dependencies": { + "@scure/base": "^1.1.6", + "@stacks/blockchain-api-client": "7.10.0", + "@stacks/common": "^7.0.2", + "@stacks/network": "^7.0.2", + "@stacks/stacks-blockchain-api-types": "7.10.0", + "@stacks/transactions": "7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@clarigen/core/node_modules/@noble/hashes": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.5.tgz", + "integrity": "sha512-LTMZiiLc+V4v1Yi16TD6aX2gmtKszNye0pQgbaLqkvhIqP7nVsSaJsWloGQjJfJ8offaoP5GtX3yY5swbcJxxQ==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT" + }, + "node_modules/@clarigen/core/node_modules/@stacks/transactions": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-7.1.0.tgz", + "integrity": "sha512-/4n5h+ka5N3mq16f1Zo0O0g2gyOYhaXFdGN8ifLz38NJmkjnCDXqi/ogB6NFNpSKGonyqyF5Vz1UPaQHwO8+IA==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.1.5", + "@noble/secp256k1": "1.7.1", + "@stacks/common": "^7.0.2", + "@stacks/network": "^7.0.2", + "c32check": "^2.0.0", + "lodash.clonedeep": "^4.5.0" + } + }, + "node_modules/@coral-xyz/anchor": { + "version": "0.31.1", + "resolved": "https://registry.npmjs.org/@coral-xyz/anchor/-/anchor-0.31.1.tgz", + "integrity": "sha512-QUqpoEK+gi2S6nlYc2atgT2r41TT3caWr/cPUEL8n8Md9437trZ68STknq897b82p5mW0XrTBNOzRbmIRJtfsA==", + "license": "(MIT OR Apache-2.0)", + "dependencies": { + "@coral-xyz/anchor-errors": "^0.31.1", + "@coral-xyz/borsh": "^0.31.1", + "@noble/hashes": "^1.3.1", + "@solana/web3.js": "^1.69.0", + "bn.js": "^5.1.2", + "bs58": "^4.0.1", + "buffer-layout": "^1.2.2", + "camelcase": "^6.3.0", + "cross-fetch": "^3.1.5", + "eventemitter3": "^4.0.7", + "pako": "^2.0.3", + "superstruct": "^0.15.4", + "toml": "^3.0.0" + }, + "engines": { + "node": ">=17" + } + }, + "node_modules/@coral-xyz/anchor-errors": { + "version": "0.31.1", + "resolved": "https://registry.npmjs.org/@coral-xyz/anchor-errors/-/anchor-errors-0.31.1.tgz", + "integrity": "sha512-NhNEku4F3zzUSBtrYz84FzYWm48+9OvmT1Hhnwr6GnPQry2dsEqH/ti/7ASjjpoFTWRnPXrjAIT1qM6Isop+LQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=10" + } + }, + "node_modules/@coral-xyz/anchor/node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" + }, + "node_modules/@coral-xyz/anchor/node_modules/superstruct": { + "version": "0.15.5", + "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-0.15.5.tgz", + "integrity": "sha512-4AOeU+P5UuE/4nOUkmcQdW5y7i9ndt1cQd/3iUe+LTz3RxESf/W/5lg4B74HbDMMv8PHnPnGCQFH45kBcrQYoQ==", + "license": "MIT" + }, + "node_modules/@coral-xyz/borsh": { + "version": "0.31.1", + "resolved": "https://registry.npmjs.org/@coral-xyz/borsh/-/borsh-0.31.1.tgz", + "integrity": "sha512-9N8AU9F0ubriKfNE3g1WF0/4dtlGXoBN/hd1PvbNBamBNwRgHxH4P+o3Zt7rSEloW1HUs6LfZEchlx9fW7POYw==", + "license": "Apache-2.0", + "dependencies": { + "bn.js": "^5.1.2", + "buffer-layout": "^1.2.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@solana/web3.js": "^1.69.0" + } + }, + "node_modules/@coral-xyz/spl-token": { + "version": "0.31.1", + "resolved": "https://registry.npmjs.org/@coral-xyz/spl-token/-/spl-token-0.31.1.tgz", + "integrity": "sha512-DqDbXNH87YtBvDXMd+FDK+K/EOZ8F83JU/VPt42KwoT8i56YBXwinffUfbefkV8j3/kSHCD6TTR+2B9F0IddxA==", + "license": "Apache-2.0", + "dependencies": { + "@coral-xyz/anchor": "=0.31.1", + "@native-to-anchor/buffer-layout": "=0.1.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@ethereumjs/rlp": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-4.0.1.tgz", + "integrity": "sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==", + "license": "MPL-2.0", + "bin": { + "rlp": "bin/rlp" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@gql.tada/cli-utils": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@gql.tada/cli-utils/-/cli-utils-1.9.2.tgz", + "integrity": "sha512-cVNs4v8ewLRYJfyAsaHbiAmd5Hm+zXEMvMhBksH58ZU87d6f8crsp2CQG6QtIqnJJw1q0CBWfWTZepGWNcL3QA==", + "license": "MIT", + "dependencies": { + "@0no-co/graphqlsp": "^1.17.3", + "@gql.tada/internal": "1.2.1", + "graphql": "^15.5.0 || ^16.0.0 || ^17.0.0" + }, + "peerDependencies": { + "@0no-co/graphqlsp": "^1.16.0", + "@gql.tada/svelte-support": "1.0.3", + "@gql.tada/vue-support": "1.0.3", + "graphql": "^15.5.0 || ^16.0.0 || ^17.0.0", + "typescript": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@gql.tada/svelte-support": { + "optional": true + }, + "@gql.tada/vue-support": { + "optional": true + } + } + }, + "node_modules/@gql.tada/internal": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@gql.tada/internal/-/internal-1.2.1.tgz", + "integrity": "sha512-1kPMv9KRpD6mfVwtXK+iy43U/gi4bpr4ganfhPLD0TjxpbuVJm7CtZ9wMFdwy3FjLBFN2QhwscNnL7lRPHg4vg==", + "license": "MIT", + "dependencies": { + "@0no-co/graphql.web": "^1.3.1" + }, + "peerDependencies": { + "graphql": "^15.5.0 || ^16.0.0 || ^17.0.0", + "typescript": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@graphql-typed-document-node/core": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", + "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", + "license": "MIT", + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@mysten/bcs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@mysten/bcs/-/bcs-1.2.0.tgz", + "integrity": "sha512-LuKonrGdGW7dq/EM6U2L9/as7dFwnhZnsnINzB/vu08Xfrj0qzWwpLOiXagAa5yZOPLK7anRZydMonczFkUPzA==", + "license": "Apache-2.0", + "dependencies": { + "bs58": "^6.0.0" + } + }, + "node_modules/@mysten/bcs/node_modules/base-x": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-5.0.1.tgz", + "integrity": "sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg==", + "license": "MIT" + }, + "node_modules/@mysten/bcs/node_modules/bs58": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-6.0.0.tgz", + "integrity": "sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==", + "license": "MIT", + "dependencies": { + "base-x": "^5.0.0" + } + }, + "node_modules/@mysten/sui": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/@mysten/sui/-/sui-1.18.0.tgz", + "integrity": "sha512-cFh5LxXZrXb/ZAD1dkKeQxzhgRYFXreyFGmI7w/JQWwdl+/0FrHJBwaWyTmGxJ/6ZC9SlaOPOk63flN7DbUurg==", + "license": "Apache-2.0", + "dependencies": { + "@graphql-typed-document-node/core": "^3.2.0", + "@mysten/bcs": "1.2.0", + "@noble/curves": "^1.4.2", + "@noble/hashes": "^1.4.0", + "@scure/bip32": "^1.4.0", + "@scure/bip39": "^1.3.0", + "@simplewebauthn/typescript-types": "^7.4.0", + "@suchipi/femver": "^1.0.0", + "bech32": "^2.0.0", + "gql.tada": "^1.8.2", + "graphql": "^16.9.0", + "jose": "^5.6.3", + "poseidon-lite": "^0.2.0", + "valibot": "^0.36.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@native-to-anchor/buffer-layout": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@native-to-anchor/buffer-layout/-/buffer-layout-0.1.0.tgz", + "integrity": "sha512-7Ykz9KRAm53XqHj5blDUKPX+OXAPO4GZBW4zJhfHGIAbzmqsUFh9kMqR66Bak3mp6wyv1OVTwSr8ZGHKswPxDg==", + "license": "MIT", + "dependencies": { + "@solana/buffer-layout": "=4.0.0", + "@solana/buffer-layout-utils": "=0.2.0" + } + }, + "node_modules/@native-to-anchor/buffer-layout/node_modules/@solana/buffer-layout": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@solana/buffer-layout/-/buffer-layout-4.0.0.tgz", + "integrity": "sha512-lR0EMP2HC3+Mxwd4YcnZb0smnaDw7Bl2IQWZiTevRH5ZZBZn6VRWn3/92E3qdU4SSImJkA6IDHawOHAnx/qUvQ==", + "license": "MIT", + "dependencies": { + "buffer": "~6.0.3" + }, + "engines": { + "node": ">=5.10" + } + }, + "node_modules/@noble/ciphers": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.3.0.tgz", + "integrity": "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/curves": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz", + "integrity": "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/secp256k1": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz", + "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT" + }, + "node_modules/@scure/base": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz", + "integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.7.0.tgz", + "integrity": "sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==", + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.9.0", + "@noble/hashes": "~1.8.0", + "@scure/base": "~1.2.5" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.6.0.tgz", + "integrity": "sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.8.0", + "@scure/base": "~1.2.5" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@simplewebauthn/typescript-types": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@simplewebauthn/typescript-types/-/typescript-types-7.4.0.tgz", + "integrity": "sha512-8/ZjHeUPe210Bt5oyaOIGx4h8lHdsQs19BiOT44gi/jBEgK7uBGA0Fy7NRsyh777al3m6WM0mBf0UR7xd4R7WQ==", + "deprecated": "This package has been renamed to @simplewebauthn/types. Please install @simplewebauthn/types instead to ensure you receive future updates.", + "license": "MIT" + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", + "license": "MIT" + }, + "node_modules/@solana/buffer-layout": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz", + "integrity": "sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA==", + "license": "MIT", + "dependencies": { + "buffer": "~6.0.3" + }, + "engines": { + "node": ">=5.10" + } + }, + "node_modules/@solana/buffer-layout-utils": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@solana/buffer-layout-utils/-/buffer-layout-utils-0.2.0.tgz", + "integrity": "sha512-szG4sxgJGktbuZYDg2FfNmkMi0DYQoVjN2h7ta1W1hPrwzarcFLBq9UpX1UjNXsNpT9dn+chgprtWGioUAr4/g==", + "license": "Apache-2.0", + "dependencies": { + "@solana/buffer-layout": "^4.0.0", + "@solana/web3.js": "^1.32.0", + "bigint-buffer": "^1.1.5", + "bignumber.js": "^9.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@solana/codecs": { + "version": "2.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@solana/codecs/-/codecs-2.0.0-rc.1.tgz", + "integrity": "sha512-qxoR7VybNJixV51L0G1RD2boZTcxmwUWnKCaJJExQ5qNKwbpSyDdWfFJfM5JhGyKe9DnPVOZB+JHWXnpbZBqrQ==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.0.0-rc.1", + "@solana/codecs-data-structures": "2.0.0-rc.1", + "@solana/codecs-numbers": "2.0.0-rc.1", + "@solana/codecs-strings": "2.0.0-rc.1", + "@solana/options": "2.0.0-rc.1" + }, + "peerDependencies": { + "typescript": ">=5" + } + }, + "node_modules/@solana/codecs-core": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-core/-/codecs-core-2.3.0.tgz", + "integrity": "sha512-oG+VZzN6YhBHIoSKgS5ESM9VIGzhWjEHEGNPSibiDTxFhsFWxNaz8LbMDPjBUE69r9wmdGLkrQ+wVPbnJcZPvw==", + "license": "MIT", + "dependencies": { + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/codecs-data-structures": { + "version": "2.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@solana/codecs-data-structures/-/codecs-data-structures-2.0.0-rc.1.tgz", + "integrity": "sha512-rinCv0RrAVJ9rE/rmaibWJQxMwC5lSaORSZuwjopSUE6T0nb/MVg6Z1siNCXhh/HFTOg0l8bNvZHgBcN/yvXog==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.0.0-rc.1", + "@solana/codecs-numbers": "2.0.0-rc.1", + "@solana/errors": "2.0.0-rc.1" + }, + "peerDependencies": { + "typescript": ">=5" + } + }, + "node_modules/@solana/codecs-data-structures/node_modules/@solana/codecs-core": { + "version": "2.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@solana/codecs-core/-/codecs-core-2.0.0-rc.1.tgz", + "integrity": "sha512-bauxqMfSs8EHD0JKESaNmNuNvkvHSuN3bbWAF5RjOfDu2PugxHrvRebmYauvSumZ3cTfQ4HJJX6PG5rN852qyQ==", + "license": "MIT", + "dependencies": { + "@solana/errors": "2.0.0-rc.1" + }, + "peerDependencies": { + "typescript": ">=5" + } + }, + "node_modules/@solana/codecs-data-structures/node_modules/@solana/codecs-numbers": { + "version": "2.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@solana/codecs-numbers/-/codecs-numbers-2.0.0-rc.1.tgz", + "integrity": "sha512-J5i5mOkvukXn8E3Z7sGIPxsThRCgSdgTWJDQeZvucQ9PT6Y3HiVXJ0pcWiOWAoQ3RX8e/f4I3IC+wE6pZiJzDQ==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.0.0-rc.1", + "@solana/errors": "2.0.0-rc.1" + }, + "peerDependencies": { + "typescript": ">=5" + } + }, + "node_modules/@solana/codecs-data-structures/node_modules/@solana/errors": { + "version": "2.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@solana/errors/-/errors-2.0.0-rc.1.tgz", + "integrity": "sha512-ejNvQ2oJ7+bcFAYWj225lyRkHnixuAeb7RQCixm+5mH4n1IA4Qya/9Bmfy5RAAHQzxK43clu3kZmL5eF9VGtYQ==", + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "commander": "^12.1.0" + }, + "bin": { + "errors": "bin/cli.mjs" + }, + "peerDependencies": { + "typescript": ">=5" + } + }, + "node_modules/@solana/codecs-data-structures/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@solana/codecs-numbers": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-numbers/-/codecs-numbers-2.3.0.tgz", + "integrity": "sha512-jFvvwKJKffvG7Iz9dmN51OGB7JBcy2CJ6Xf3NqD/VP90xak66m/Lg48T01u5IQ/hc15mChVHiBm+HHuOFDUrQg==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/codecs-strings": { + "version": "2.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@solana/codecs-strings/-/codecs-strings-2.0.0-rc.1.tgz", + "integrity": "sha512-9/wPhw8TbGRTt6mHC4Zz1RqOnuPTqq1Nb4EyuvpZ39GW6O2t2Q7Q0XxiB3+BdoEjwA2XgPw6e2iRfvYgqty44g==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.0.0-rc.1", + "@solana/codecs-numbers": "2.0.0-rc.1", + "@solana/errors": "2.0.0-rc.1" + }, + "peerDependencies": { + "fastestsmallesttextencoderdecoder": "^1.0.22", + "typescript": ">=5" + } + }, + "node_modules/@solana/codecs-strings/node_modules/@solana/codecs-core": { + "version": "2.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@solana/codecs-core/-/codecs-core-2.0.0-rc.1.tgz", + "integrity": "sha512-bauxqMfSs8EHD0JKESaNmNuNvkvHSuN3bbWAF5RjOfDu2PugxHrvRebmYauvSumZ3cTfQ4HJJX6PG5rN852qyQ==", + "license": "MIT", + "dependencies": { + "@solana/errors": "2.0.0-rc.1" + }, + "peerDependencies": { + "typescript": ">=5" + } + }, + "node_modules/@solana/codecs-strings/node_modules/@solana/codecs-numbers": { + "version": "2.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@solana/codecs-numbers/-/codecs-numbers-2.0.0-rc.1.tgz", + "integrity": "sha512-J5i5mOkvukXn8E3Z7sGIPxsThRCgSdgTWJDQeZvucQ9PT6Y3HiVXJ0pcWiOWAoQ3RX8e/f4I3IC+wE6pZiJzDQ==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.0.0-rc.1", + "@solana/errors": "2.0.0-rc.1" + }, + "peerDependencies": { + "typescript": ">=5" + } + }, + "node_modules/@solana/codecs-strings/node_modules/@solana/errors": { + "version": "2.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@solana/errors/-/errors-2.0.0-rc.1.tgz", + "integrity": "sha512-ejNvQ2oJ7+bcFAYWj225lyRkHnixuAeb7RQCixm+5mH4n1IA4Qya/9Bmfy5RAAHQzxK43clu3kZmL5eF9VGtYQ==", + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "commander": "^12.1.0" + }, + "bin": { + "errors": "bin/cli.mjs" + }, + "peerDependencies": { + "typescript": ">=5" + } + }, + "node_modules/@solana/codecs-strings/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@solana/codecs/node_modules/@solana/codecs-core": { + "version": "2.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@solana/codecs-core/-/codecs-core-2.0.0-rc.1.tgz", + "integrity": "sha512-bauxqMfSs8EHD0JKESaNmNuNvkvHSuN3bbWAF5RjOfDu2PugxHrvRebmYauvSumZ3cTfQ4HJJX6PG5rN852qyQ==", + "license": "MIT", + "dependencies": { + "@solana/errors": "2.0.0-rc.1" + }, + "peerDependencies": { + "typescript": ">=5" + } + }, + "node_modules/@solana/codecs/node_modules/@solana/codecs-numbers": { + "version": "2.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@solana/codecs-numbers/-/codecs-numbers-2.0.0-rc.1.tgz", + "integrity": "sha512-J5i5mOkvukXn8E3Z7sGIPxsThRCgSdgTWJDQeZvucQ9PT6Y3HiVXJ0pcWiOWAoQ3RX8e/f4I3IC+wE6pZiJzDQ==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.0.0-rc.1", + "@solana/errors": "2.0.0-rc.1" + }, + "peerDependencies": { + "typescript": ">=5" + } + }, + "node_modules/@solana/codecs/node_modules/@solana/errors": { + "version": "2.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@solana/errors/-/errors-2.0.0-rc.1.tgz", + "integrity": "sha512-ejNvQ2oJ7+bcFAYWj225lyRkHnixuAeb7RQCixm+5mH4n1IA4Qya/9Bmfy5RAAHQzxK43clu3kZmL5eF9VGtYQ==", + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "commander": "^12.1.0" + }, + "bin": { + "errors": "bin/cli.mjs" + }, + "peerDependencies": { + "typescript": ">=5" + } + }, + "node_modules/@solana/codecs/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@solana/errors": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/errors/-/errors-2.3.0.tgz", + "integrity": "sha512-66RI9MAbwYV0UtP7kGcTBVLxJgUxoZGm8Fbc0ah+lGiAw17Gugco6+9GrJCV83VyF2mDWyYnYM9qdI3yjgpnaQ==", + "license": "MIT", + "dependencies": { + "chalk": "^5.4.1", + "commander": "^14.0.0" + }, + "bin": { + "errors": "bin/cli.mjs" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/options": { + "version": "2.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@solana/options/-/options-2.0.0-rc.1.tgz", + "integrity": "sha512-mLUcR9mZ3qfHlmMnREdIFPf9dpMc/Bl66tLSOOWxw4ml5xMT2ohFn7WGqoKcu/UHkT9CrC6+amEdqCNvUqI7AA==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.0.0-rc.1", + "@solana/codecs-data-structures": "2.0.0-rc.1", + "@solana/codecs-numbers": "2.0.0-rc.1", + "@solana/codecs-strings": "2.0.0-rc.1", + "@solana/errors": "2.0.0-rc.1" + }, + "peerDependencies": { + "typescript": ">=5" + } + }, + "node_modules/@solana/options/node_modules/@solana/codecs-core": { + "version": "2.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@solana/codecs-core/-/codecs-core-2.0.0-rc.1.tgz", + "integrity": "sha512-bauxqMfSs8EHD0JKESaNmNuNvkvHSuN3bbWAF5RjOfDu2PugxHrvRebmYauvSumZ3cTfQ4HJJX6PG5rN852qyQ==", + "license": "MIT", + "dependencies": { + "@solana/errors": "2.0.0-rc.1" + }, + "peerDependencies": { + "typescript": ">=5" + } + }, + "node_modules/@solana/options/node_modules/@solana/codecs-numbers": { + "version": "2.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@solana/codecs-numbers/-/codecs-numbers-2.0.0-rc.1.tgz", + "integrity": "sha512-J5i5mOkvukXn8E3Z7sGIPxsThRCgSdgTWJDQeZvucQ9PT6Y3HiVXJ0pcWiOWAoQ3RX8e/f4I3IC+wE6pZiJzDQ==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.0.0-rc.1", + "@solana/errors": "2.0.0-rc.1" + }, + "peerDependencies": { + "typescript": ">=5" + } + }, + "node_modules/@solana/options/node_modules/@solana/errors": { + "version": "2.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@solana/errors/-/errors-2.0.0-rc.1.tgz", + "integrity": "sha512-ejNvQ2oJ7+bcFAYWj225lyRkHnixuAeb7RQCixm+5mH4n1IA4Qya/9Bmfy5RAAHQzxK43clu3kZmL5eF9VGtYQ==", + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "commander": "^12.1.0" + }, + "bin": { + "errors": "bin/cli.mjs" + }, + "peerDependencies": { + "typescript": ">=5" + } + }, + "node_modules/@solana/options/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@solana/spl-token": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@solana/spl-token/-/spl-token-0.3.11.tgz", + "integrity": "sha512-bvohO3rIMSVL24Pb+I4EYTJ6cL82eFpInEXD/I8K8upOGjpqHsKUoAempR/RnUlI1qSFNyFlWJfu6MNUgfbCQQ==", + "license": "Apache-2.0", + "dependencies": { + "@solana/buffer-layout": "^4.0.0", + "@solana/buffer-layout-utils": "^0.2.0", + "@solana/spl-token-metadata": "^0.1.2", + "buffer": "^6.0.3" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@solana/web3.js": "^1.88.0" + } + }, + "node_modules/@solana/spl-token-metadata": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@solana/spl-token-metadata/-/spl-token-metadata-0.1.6.tgz", + "integrity": "sha512-7sMt1rsm/zQOQcUWllQX9mD2O6KhSAtY1hFR2hfFwgqfFWzSY9E9GDvFVNYUI1F0iQKcm6HmePU9QbKRXTEBiA==", + "license": "Apache-2.0", + "dependencies": { + "@solana/codecs": "2.0.0-rc.1" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@solana/web3.js": "^1.95.3" + } + }, + "node_modules/@solana/web3.js": { + "version": "1.98.4", + "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.98.4.tgz", + "integrity": "sha512-vv9lfnvjUsRiq//+j5pBdXig0IQdtzA0BRZ3bXEP4KaIyF1CcaydWqgyzQgfZMNIsWNWmG+AUHwPy4AHOD6gpw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.0", + "@noble/curves": "^1.4.2", + "@noble/hashes": "^1.4.0", + "@solana/buffer-layout": "^4.0.1", + "@solana/codecs-numbers": "^2.1.0", + "agentkeepalive": "^4.5.0", + "bn.js": "^5.2.1", + "borsh": "^0.7.0", + "bs58": "^4.0.1", + "buffer": "6.0.3", + "fast-stable-stringify": "^1.0.0", + "jayson": "^4.1.1", + "node-fetch": "^2.7.0", + "rpc-websockets": "^9.0.2", + "superstruct": "^2.0.2" + } + }, + "node_modules/@stacks/blockchain-api-client": { + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/@stacks/blockchain-api-client/-/blockchain-api-client-7.10.0.tgz", + "integrity": "sha512-VQbJDJuHrj2TWDmYE2Tymqa6yMCvNkc8SXPeHgX1k1BuNKFe7HUHv1r4wA24cRpoTSpM14URJOscKLBaDyklpg==", + "license": "GPL-3.0", + "dependencies": { + "@stacks/stacks-blockchain-api-types": "*", + "@types/ws": "7.4.7", + "cross-fetch": "3.1.5", + "eventemitter3": "4.0.7", + "jsonrpc-lite": "2.2.0", + "socket.io-client": "4.7.3", + "ws": "8.16.0" + } + }, + "node_modules/@stacks/blockchain-api-client/node_modules/cross-fetch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", + "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "license": "MIT", + "dependencies": { + "node-fetch": "2.6.7" + } + }, + "node_modules/@stacks/blockchain-api-client/node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" + }, + "node_modules/@stacks/blockchain-api-client/node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/@stacks/blockchain-api-client/node_modules/ws": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/@stacks/common": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@stacks/common/-/common-7.5.0.tgz", + "integrity": "sha512-UkKM3J7VufGEEuHLYRAFZQFbiQeACMpMMzGbBL6qo/6YLXvPPXA8MBffeCsXE65/a0bJSbh+0Q7rfdio9IvZ1w==", + "license": "MIT" + }, + "node_modules/@stacks/network": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@stacks/network/-/network-7.5.0.tgz", + "integrity": "sha512-FKfw864+ipj0RBa0kXBCKp+6Bm/8IS1pk+jg5NJhi//NzG8fZsC4MsER1F8qvzVoFrLfZjqxo+3sJDYfvHbVOQ==", + "license": "MIT", + "dependencies": { + "@stacks/common": "^7.5.0", + "cross-fetch": "^3.1.5" + } + }, + "node_modules/@stacks/stacks-blockchain-api-types": { + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/@stacks/stacks-blockchain-api-types/-/stacks-blockchain-api-types-7.10.0.tgz", + "integrity": "sha512-LfDishvEsmDJ6OXfgohkOIIsLTwvKVn3NKELaWTaZndN2Pucsk3Uz8NPDhVM5Ij1rGjFGT2bwcHNoGE7k3GhxQ==", + "license": "ISC" + }, + "node_modules/@stacks/transactions": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-7.5.0.tgz", + "integrity": "sha512-PhKe8ZIaVWvTbsTDE/26z9Dm6oYYZ2Cfhpg7xabE97bCE59KwuujBkvLVCJKEdlUn/P187120Go79UbGf9BywA==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.1.5", + "@noble/secp256k1": "1.7.1", + "@stacks/common": "^7.5.0", + "@stacks/network": "^7.5.0", + "c32check": "^2.0.0", + "lodash.clonedeep": "^4.5.0" + } + }, + "node_modules/@stacks/transactions/node_modules/@noble/hashes": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.5.tgz", + "integrity": "sha512-LTMZiiLc+V4v1Yi16TD6aX2gmtKszNye0pQgbaLqkvhIqP7nVsSaJsWloGQjJfJ8offaoP5GtX3yY5swbcJxxQ==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT" + }, + "node_modules/@stellar/js-xdr": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@stellar/js-xdr/-/js-xdr-4.0.0.tgz", + "integrity": "sha512-+NmNa7Tk5BI5XFdy/6xGTqAN4J9a9KgCrCGhj2uEUTCBhLkch0M+QbKzNH8zEnejWe0p8w+0q5hUVX6L3OzoVA==", + "license": "Apache-2.0", + "engines": { + "node": ">=20.0.0", + "pnpm": ">=9.0.0" + } + }, + "node_modules/@stellar/stellar-base": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/@stellar/stellar-base/-/stellar-base-15.0.0.tgz", + "integrity": "sha512-XQhxUr9BYiEcFcgc4oWcCMR9QJCny/GmmGsuwPKf/ieIcOeb5149KLHYx9mJCA0ea8QbucR2/GzV58QbXOTxQA==", + "deprecated": "This package is now rolled into @stellar/stellar-sdk. Please use @stellar/stellar-sdk to continue receiving updates and support.", + "license": "Apache-2.0", + "dependencies": { + "@noble/curves": "^1.9.7", + "@stellar/js-xdr": "^4.0.0", + "base32.js": "^0.1.0", + "bignumber.js": "^9.3.1", + "buffer": "^6.0.3", + "sha.js": "^2.4.12" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@stellar/stellar-sdk": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/@stellar/stellar-sdk/-/stellar-sdk-15.1.0.tgz", + "integrity": "sha512-GsJUcWx2yboVzYdhTe/LHS3V1wVLSHkUkglC5bBoYWGJt31vzIhbSGno60NP9CdCTNkLJdnrsLJ63oA58Zvh5A==", + "license": "Apache-2.0", + "dependencies": { + "@stellar/stellar-base": "^15.0.0", + "axios": "1.15.0", + "bignumber.js": "^9.3.1", + "commander": "^14.0.3", + "eventsource": "^2.0.2", + "feaxios": "^0.0.23", + "randombytes": "^2.1.0", + "toml": "^3.0.0", + "urijs": "^1.19.11" + }, + "bin": { + "stellar-js": "bin/stellar-js" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@stellar/stellar-sdk/node_modules/axios": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.15.0.tgz", + "integrity": "sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.11", + "form-data": "^4.0.5", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/@suchipi/femver": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@suchipi/femver/-/femver-1.0.0.tgz", + "integrity": "sha512-bprE8+K5V+DPX7q2e2K57ImqNBdfGHDIWaGI5xHxZoxbKOuQZn4wzPiUxOAHnsUr3w3xHrWXwN7gnG/iIuEMIg==", + "license": "MIT" + }, + "node_modules/@swc/helpers": { + "version": "0.5.23", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz", + "integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", + "license": "MIT" + }, + "node_modules/@types/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", + "license": "MIT" + }, + "node_modules/@types/ws": { + "version": "7.4.7", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", + "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/abitype": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.2.3.tgz", + "integrity": "sha512-Ofer5QUnuUdTFsBRwARMoWKOH1ND5ehwYhJ3OJ/BQO+StkwQjHw0XyVh4vDttzHB7QOFhPHa/o413PJ82gU/Tg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/wevm" + }, + "peerDependencies": { + "typescript": ">=5.0.4", + "zod": "^3.22.0 || ^4.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, + "node_modules/aes-js": { + "version": "4.0.0-beta.5", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", + "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==", + "license": "MIT" + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agentkeepalive": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", + "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", + "license": "MIT", + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/algorand-msgpack": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/algorand-msgpack/-/algorand-msgpack-1.1.0.tgz", + "integrity": "sha512-08k7pBQnkaUB5p+jL7f1TRaUIlTSDE0cesFu1mD7llLao+1cAhtvvZmGE3OnisTd0xOn118QMw74SRqddqaYvw==", + "license": "ISC", + "engines": { + "node": ">= 14" + } + }, + "node_modules/algosdk": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/algosdk/-/algosdk-3.6.0.tgz", + "integrity": "sha512-pdM0neCgR3DasvpSPfgQKc5/hlhkSYmXjcUChePLGegA0kqA0AoLmcfMDyeREcsvHcu7rrv3Wa+RZnGa5kINwQ==", + "license": "MIT", + "dependencies": { + "algorand-msgpack": "^1.1.0", + "hi-base32": "^0.5.1", + "js-sha256": "^0.9.0", + "js-sha3": "^0.8.0", + "js-sha512": "^0.8.0", + "json-bigint": "^1.0.0", + "tweetnacl": "^1.0.3", + "vlq": "^2.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/assert": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", + "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "is-nan": "^1.3.2", + "object-is": "^1.1.5", + "object.assign": "^4.1.4", + "util": "^0.12.5" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axios": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.18.1.tgz", + "integrity": "sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.5", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/base-x": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz", + "integrity": "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/base32.js": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/base32.js/-/base32.js-0.1.0.tgz", + "integrity": "sha512-n3TkB02ixgBOhTvANakDb4xaMXnYUVkNoRFJjQflcqMQhyEKxEHdj3E6N8t8sUQ0mjH/3/JxzlXuz3ul/J90pQ==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bech32": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", + "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==", + "license": "MIT" + }, + "node_modules/big.js": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-6.2.2.tgz", + "integrity": "sha512-y/ie+Faknx7sZA5MfGA2xKlu0GDv8RWrXGsmlteyJQ2lvoKv9GBK/fpRMc2qlSoBAgNxrixICFCBefIq8WCQpQ==", + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/bigjs" + } + }, + "node_modules/bigint-buffer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bigint-buffer/-/bigint-buffer-1.1.5.tgz", + "integrity": "sha512-trfYco6AoZ+rKhKnxA0hgX0HAbVP/s808/EuDSe2JDzUnCp/xAsli35Orvk67UrTEcwuxZqYZDmfA2RXJgxVvA==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "bindings": "^1.3.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/bignumber.js": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", + "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "license": "MIT", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bn.js": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.4.tgz", + "integrity": "sha512-QL7sb18rJ1PbdsKsqPA0guxL563vIMwRHgzNrW/uzQuRGN1Cjqd/wonUBAVqHox9KwzHA6vCbM0lXx3k4iQMow==", + "license": "MIT" + }, + "node_modules/borsh": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/borsh/-/borsh-0.7.0.tgz", + "integrity": "sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==", + "license": "Apache-2.0", + "dependencies": { + "bn.js": "^5.2.0", + "bs58": "^4.0.0", + "text-encoding-utf-8": "^1.0.2" + } + }, + "node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "license": "MIT", + "dependencies": { + "base-x": "^3.0.2" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-layout": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/buffer-layout/-/buffer-layout-1.2.2.tgz", + "integrity": "sha512-kWSuLN694+KTk8SrYvCqwP2WcgQjoRCiF5b4QDvkkz8EmgD+aWAIceGFKMIAdmF/pH+vpgNV3d3kAKorcdAmWA==", + "license": "MIT", + "engines": { + "node": ">=4.5" + } + }, + "node_modules/bufferutil": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.1.0.tgz", + "integrity": "sha512-ZMANVnAixE6AWWnPzlW2KpUrxhm9woycYvPOo67jWHyFowASTEd9s+QN1EIMsSDtwhIxN4sWE1jotpuDUIgyIw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, + "node_modules/c32check": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/c32check/-/c32check-2.0.0.tgz", + "integrity": "sha512-rpwfAcS/CMqo0oCqDf3r9eeLgScRE3l/xHDCXhM3UyrfvIn7PrLq63uHh7yYbv8NzaZn5MVsVhIRpQ+5GZ5HyA==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "^1.1.2", + "base-x": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/c32check/node_modules/base-x": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.1.tgz", + "integrity": "sha512-uAZ8x6r6S3aUM9rbHGVOIsR15U/ZSc82b3ymnCPsT45Gk1DDvhDPdIgB5MrhirZWt+5K0EEPQH985kNqZgNPFw==", + "license": "MIT" + }, + "node_modules/call-bind": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "license": "Apache-2.0", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/cross-fetch": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", + "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.7.0" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delay": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", + "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/engine.io-client": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.4.tgz", + "integrity": "sha512-GeZeeRjpD2qf49cZQ0Wvh/8NJNfeXkXXcoGh+F77oEAgo9gUHwT1fCRxSNU+YEEaysOJTnsFHmM5oAcPy4ntvQ==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1", + "xmlhttprequest-ssl": "~2.0.0" + } + }, + "node_modules/engine.io-client/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/engine.io-client/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", + "license": "MIT" + }, + "node_modules/es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==", + "license": "MIT", + "dependencies": { + "es6-promise": "^4.0.3" + } + }, + "node_modules/esbuild": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" + } + }, + "node_modules/ethereum-cryptography": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", + "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", + "license": "MIT", + "dependencies": { + "@noble/curves": "1.4.2", + "@noble/hashes": "1.4.0", + "@scure/bip32": "1.4.0", + "@scure/bip39": "1.3.0" + } + }, + "node_modules/ethereum-cryptography/node_modules/@noble/curves": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ethereum-cryptography/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ethereum-cryptography/node_modules/@scure/base": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", + "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ethereum-cryptography/node_modules/@scure/bip32": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", + "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.4.0", + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ethereum-cryptography/node_modules/@scure/bip39": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", + "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ethers": { + "version": "6.13.5", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.5.tgz", + "integrity": "sha512-+knKNieu5EKRThQJWwqaJ10a6HE9sSehGeqWN65//wE7j47ZpFhKAnHB/JJFibwwg61I/koxaPsXbXpD/skNOQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/ethers-io/" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@adraffy/ens-normalize": "1.10.1", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@types/node": "22.7.5", + "aes-js": "4.0.0-beta.5", + "tslib": "2.7.0", + "ws": "8.17.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/ethers/node_modules/@adraffy/ens-normalize": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==", + "license": "MIT" + }, + "node_modules/ethers/node_modules/@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ethers/node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ethers/node_modules/@types/node": { + "version": "22.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", + "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/ethers/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "license": "0BSD" + }, + "node_modules/ethers/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "license": "MIT" + }, + "node_modules/eventsource": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-2.0.2.tgz", + "integrity": "sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==", + "engines": { + "node": "> 0.1.90" + } + }, + "node_modules/fast-stable-stringify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-stable-stringify/-/fast-stable-stringify-1.0.0.tgz", + "integrity": "sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag==", + "license": "MIT" + }, + "node_modules/fastestsmallesttextencoderdecoder": { + "version": "1.0.22", + "resolved": "https://registry.npmjs.org/fastestsmallesttextencoderdecoder/-/fastestsmallesttextencoderdecoder-1.0.22.tgz", + "integrity": "sha512-Pb8d48e+oIuY4MaM64Cd7OW1gt4nxCHs7/ddPPZ/Ic3sg8yVGM7O9wDvZ7us6ScaUupzM+pfBolwtYhN1IxBIw==", + "license": "CC0-1.0", + "peer": true + }, + "node_modules/feaxios": { + "version": "0.0.23", + "resolved": "https://registry.npmjs.org/feaxios/-/feaxios-0.0.23.tgz", + "integrity": "sha512-eghR0A21fvbkcQBgZuMfQhrXxJzC0GNUGC9fXhBge33D+mFDTwl0aJ35zoQQn575BhyjQitRc5N4f+L4cP708g==", + "license": "MIT", + "dependencies": { + "is-retry-allowed": "^3.0.0" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "license": "MIT" + }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/google-protobuf": { + "version": "3.21.4", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.4.tgz", + "integrity": "sha512-MnG7N936zcKTco4Jd2PX2U96Kf9PxygAPKBug+74LHzmHXmceN16MmRcdgZv+DGef/S9YvQAfRsNCn4cjf9yyQ==", + "license": "(BSD-3-Clause AND Apache-2.0)" + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gql.tada": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/gql.tada/-/gql.tada-1.11.2.tgz", + "integrity": "sha512-oBr7ShA5/TmcwOO7BZgN1SynX2rBU+/ltysB0zXc+NCBF+9YOg6MRzJcTfLjIqDKdcE3LGxpOl0l9hBbxmyzmA==", + "license": "MIT", + "dependencies": { + "@0no-co/graphql.web": "^1.3.2", + "@0no-co/graphqlsp": "^1.17.3", + "@gql.tada/cli-utils": "1.9.2", + "@gql.tada/internal": "1.2.1" + }, + "bin": { + "gql-tada": "bin/cli.js", + "gql.tada": "bin/cli.js" + }, + "peerDependencies": { + "typescript": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/graphql": { + "version": "16.14.2", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.14.2.tgz", + "integrity": "sha512-Chq1s4CY7jmh8gO2qvLIJyfCDIN+EHLFW/9iShnp1z8FjBQMoodWP1kDC36VAMXXIvAjj4ARa7ntfAV2BrjsbA==", + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hi-base32": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/hi-base32/-/hi-base32-0.5.1.tgz", + "integrity": "sha512-EmBBpvdYh/4XxsnUybsPag6VikPYnN30td+vQk+GI3qpahVEG9+gTkG0aXVxTjBqQ5T6ijbWIu77O+C5WFWsnA==", + "license": "MIT" + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/is-arguments": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-retry-allowed": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-3.0.0.tgz", + "integrity": "sha512-9xH0xvoggby+u0uGF7cZXdrutWiBiaFG8ZT4YFPXL8NzkyAwX3AKGLeFQLvzDpM430+nDFBZ1LHkie/8ocL06A==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "license": "MIT" + }, + "node_modules/isomorphic-ws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", + "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/isows": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.7.tgz", + "integrity": "sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/jayson": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/jayson/-/jayson-4.3.0.tgz", + "integrity": "sha512-AauzHcUcqs8OBnCHOkJY280VaTiCm57AbuO7lqzcw7JapGj50BisE3xhksye4zlTSR1+1tAz67wLTl8tEH1obQ==", + "license": "MIT", + "dependencies": { + "@types/connect": "^3.4.33", + "@types/node": "^12.12.54", + "@types/ws": "^7.4.4", + "commander": "^2.20.3", + "delay": "^5.0.0", + "es6-promisify": "^5.0.0", + "eyes": "^0.1.8", + "isomorphic-ws": "^4.0.1", + "json-stringify-safe": "^5.0.1", + "stream-json": "^1.9.1", + "uuid": "^8.3.2", + "ws": "^7.5.10" + }, + "bin": { + "jayson": "bin/jayson.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jayson/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" + }, + "node_modules/jose": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/jose/-/jose-5.10.0.tgz", + "integrity": "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/js-sha256": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz", + "integrity": "sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==", + "license": "MIT" + }, + "node_modules/js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", + "license": "MIT" + }, + "node_modules/js-sha512": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha512/-/js-sha512-0.8.0.tgz", + "integrity": "sha512-PWsmefG6Jkodqt+ePTvBZCSMFgN7Clckjd0O7su3I0+BW2QWUTJNzjktHsztGLhncP2h8mcF9V9Y2Ha59pAViQ==", + "license": "MIT" + }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "license": "MIT", + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "license": "ISC" + }, + "node_modules/jsonrpc-lite": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/jsonrpc-lite/-/jsonrpc-lite-2.2.0.tgz", + "integrity": "sha512-/cbbSxtZWs1O7R4tWqabrCM/t3N8qKUZMAg9IUqpPvUs6UyRvm6pCNYkskyKN/XU0UgffW+NY2ZRr8t0AknX7g==", + "license": "MIT" + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", + "license": "MIT" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-gyp-build": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "license": "MIT", + "optional": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ox": { + "version": "0.14.29", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.14.29.tgz", + "integrity": "sha512-M5j87Ec4V99MQdRct/g09eWXW60g6zhHTUs1lr4deUtrPDnezBdCJTgKd7pxqTpSZBFveV0ALi9jMMuT1qKyNg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@adraffy/ens-normalize": "^1.11.0", + "@noble/ciphers": "^1.3.0", + "@noble/curves": "1.9.1", + "@noble/hashes": "^1.8.0", + "@scure/bip32": "^1.7.0", + "@scure/bip39": "^1.6.0", + "abitype": "^1.2.3", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/ox/node_modules/@noble/curves": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.1.tgz", + "integrity": "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ox/node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" + }, + "node_modules/pako": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.2.0.tgz", + "integrity": "sha512-zJq6RP/5q+TO2OpFV3FHzlPnFjmkb7Nc99a5SNjJE+uu/PkpChs+NIZSSzbBoD+6kjiISXjfYdwj1ZRQ81dz/w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "(MIT AND Zlib)" + }, + "node_modules/poseidon-lite": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/poseidon-lite/-/poseidon-lite-0.2.1.tgz", + "integrity": "sha512-xIr+G6HeYfOhCuswdqcFpSX47SPhm0EpisWJ6h7fHlWwaVIvH3dLnejpatrtw6Xc6HaLrpq05y7VRfvDmDGIog==", + "license": "MIT" + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/querystring": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz", + "integrity": "sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "license": "MIT", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "license": "MIT" + }, + "node_modules/rpc-websockets": { + "version": "9.3.9", + "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-9.3.9.tgz", + "integrity": "sha512-2iQDaTB4g5fDB2ihrTFSJSibCEuxaRi1q7qTW7ZO9/M5/TC+ToHA4D9/ffNLEbAoHNNrcdeP05oATNk44SKZXA==", + "license": "LGPL-3.0-only", + "dependencies": { + "@swc/helpers": "^0.5.11", + "@types/uuid": "^10.0.0", + "@types/ws": "^8.2.2", + "buffer": "^6.0.3", + "eventemitter3": "^5.0.1", + "uuid": "^14.0.0", + "ws": "^8.5.0" + }, + "funding": { + "type": "paypal", + "url": "https://paypal.me/kozjak" + }, + "optionalDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^6.0.0" + } + }, + "node_modules/rpc-websockets/node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/rpc-websockets/node_modules/utf-8-validate": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-6.0.6.tgz", + "integrity": "sha512-q3l3P9UtEEiAHcsgsqTgf9PPjctrDWoIXW3NpOHFdRDbLvu4DLIcxHangJ4RLrWkBcKjmcs/6NkerI8T/rE4LA==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, + "node_modules/rpc-websockets/node_modules/uuid": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.1.tgz", + "integrity": "sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist-node/bin/uuid" + } + }, + "node_modules/rpc-websockets/node_modules/ws": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "license": "MIT" + }, + "node_modules/sha.js": { + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz", + "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==", + "license": "(MIT AND BSD-3-Clause)", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.0" + }, + "bin": { + "sha.js": "bin.js" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/socket.io-client": { + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.3.tgz", + "integrity": "sha512-nU+ywttCyBitXIl9Xe0RSEfek4LneYkJxCeNnKCuhwoH4jGXO1ipIUw/VA/+Vvv2G1MTym11fzFC0SxkrcfXDw==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.5.2", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-client/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.6.tgz", + "integrity": "sha512-asJqbVBDsBCJx0pTqw3WfesSY0iRX+2xzWEWzrpcH7L6fLzrhyF8WPI8UaeM4YCuDfpwA/cgsdugMsmtz8EJeg==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.4.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/stream-chain": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/stream-chain/-/stream-chain-2.2.5.tgz", + "integrity": "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==", + "license": "BSD-3-Clause" + }, + "node_modules/stream-json": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/stream-json/-/stream-json-1.9.1.tgz", + "integrity": "sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw==", + "license": "BSD-3-Clause", + "dependencies": { + "stream-chain": "^2.2.5" + } + }, + "node_modules/superstruct": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-2.0.2.tgz", + "integrity": "sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/text-encoding-utf-8": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz", + "integrity": "sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==" + }, + "node_modules/timed-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/timed-cache/-/timed-cache-2.0.0.tgz", + "integrity": "sha512-9owe3VtDCtZKo8bfk5bSC4tSzIRP65doXI0i2oFWNP4VjQDwoRIsADynZQZz6XXK7exL7bOuI3HExFQ9LGi3tQ==", + "license": "MIT" + }, + "node_modules/to-buffer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz", + "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==", + "license": "MIT", + "dependencies": { + "isarray": "^2.0.5", + "safe-buffer": "^5.2.1", + "typed-array-buffer": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/toml": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz", + "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==", + "license": "MIT" + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/tronweb": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/tronweb/-/tronweb-6.4.0.tgz", + "integrity": "sha512-WyrjHKN6YSnV/Dvc4cdULDyXVKJfj4bqQ/8dib6FlOaQ1T/EiOjLtOx24hDgcn8lY/iVMy4Axchzurk1wGcRJg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "7.26.10", + "axios": "1.18.0", + "bignumber.js": "9.1.2", + "ethereum-cryptography": "2.2.1", + "ethers": "6.13.5", + "eventemitter3": "5.0.1", + "google-protobuf": "3.21.4", + "semver": "7.7.1", + "validator": "13.15.23" + } + }, + "node_modules/tronweb/node_modules/@babel/runtime": { + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.10.tgz", + "integrity": "sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw==", + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/tronweb/node_modules/axios": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.18.0.tgz", + "integrity": "sha512-E32NzpYKp++W7XRe52rHiXV2ehxmh3wbdgO7MHeFM+vqxLBYHzt0ElkiImtOBxtOmyp0yoC8C6uESVV84Y2/hw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.5", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/tronweb/node_modules/bignumber.js": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", + "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/tronweb/node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tsx": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.22.4.tgz", + "integrity": "sha512-X8EX+XV4QR5xCsrgxaED954zTDfY8KqlDtskKEL0cHhyS/P8b4IFOvGDQpsC9Q1XnLq915wEfwwY/zzskCtmhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.28.0" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", + "license": "Unlicense" + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "license": "MIT" + }, + "node_modules/urijs": { + "version": "1.19.11", + "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.11.tgz", + "integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==", + "license": "MIT" + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/valibot": { + "version": "0.36.0", + "resolved": "https://registry.npmjs.org/valibot/-/valibot-0.36.0.tgz", + "integrity": "sha512-CjF1XN4sUce8sBK9TixrDqFM7RwNkuXdJu174/AwmQUB62QbCQADg5lLe8ldBalFgtj1uKj+pKwDJiNo4Mn+eQ==", + "license": "MIT" + }, + "node_modules/validator": { + "version": "13.15.23", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.23.tgz", + "integrity": "sha512-4yoz1kEWqUjzi5zsPbAS/903QXSYp0UOtHsPpp7p9rHAw/W+dkInskAE386Fat3oKRROwO98d9ZB0G4cObgUyw==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/viem": { + "version": "2.54.0", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.54.0.tgz", + "integrity": "sha512-DW6KW3m89+3MLozFNPuI9Nhz2hJw375hUo1bpbo3qXipBvjdjF26B/d3U5adVyLGKOfqK4XeA1wPDWQTFQ/ltA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@noble/curves": "1.9.1", + "@noble/hashes": "1.8.0", + "@scure/bip32": "1.7.0", + "@scure/bip39": "1.6.0", + "abitype": "1.2.3", + "isows": "1.0.7", + "ox": "0.14.29", + "ws": "8.20.1" + }, + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/viem/node_modules/@noble/curves": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.1.tgz", + "integrity": "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/viem/node_modules/ws": { + "version": "8.20.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz", + "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/vlq": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-2.0.4.tgz", + "integrity": "sha512-aodjPa2wPQFkra1G8CzJBTHXhgk3EVSwxSWXNPr1fgdFLUb8kvLV1iEb6rFgasIsjP82HWI6dsb5Io26DDnasA==", + "license": "MIT" + }, + "node_modules/web3": { + "version": "4.16.0", + "resolved": "https://registry.npmjs.org/web3/-/web3-4.16.0.tgz", + "integrity": "sha512-SgoMSBo6EsJ5GFCGar2E/pR2lcR/xmUSuQ61iK6yDqzxmm42aPPxSqZfJz2z/UCR6pk03u77pU8TGV6lgMDdIQ==", + "license": "LGPL-3.0", + "dependencies": { + "web3-core": "^4.7.1", + "web3-errors": "^1.3.1", + "web3-eth": "^4.11.1", + "web3-eth-abi": "^4.4.1", + "web3-eth-accounts": "^4.3.1", + "web3-eth-contract": "^4.7.2", + "web3-eth-ens": "^4.4.0", + "web3-eth-iban": "^4.0.7", + "web3-eth-personal": "^4.1.0", + "web3-net": "^4.1.0", + "web3-providers-http": "^4.2.0", + "web3-providers-ws": "^4.0.8", + "web3-rpc-methods": "^1.3.0", + "web3-rpc-providers": "^1.0.0-rc.4", + "web3-types": "^1.10.0", + "web3-utils": "^4.3.3", + "web3-validator": "^2.0.6" + }, + "engines": { + "node": ">=14.0.0", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-core": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-4.7.1.tgz", + "integrity": "sha512-9KSeASCb/y6BG7rwhgtYC4CvYY66JfkmGNEYb7q1xgjt9BWfkf09MJPaRyoyT5trdOxYDHkT9tDlypvQWaU8UQ==", + "license": "LGPL-3.0", + "dependencies": { + "web3-errors": "^1.3.1", + "web3-eth-accounts": "^4.3.1", + "web3-eth-iban": "^4.0.7", + "web3-providers-http": "^4.2.0", + "web3-providers-ws": "^4.0.8", + "web3-types": "^1.10.0", + "web3-utils": "^4.3.3", + "web3-validator": "^2.0.6" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + }, + "optionalDependencies": { + "web3-providers-ipc": "^4.0.7" + } + }, + "node_modules/web3-errors": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/web3-errors/-/web3-errors-1.3.1.tgz", + "integrity": "sha512-w3NMJujH+ZSW4ltIZZKtdbkbyQEvBzyp3JRn59Ckli0Nz4VMsVq8aF1bLWM7A2kuQ+yVEm3ySeNU+7mSRwx7RQ==", + "license": "LGPL-3.0", + "dependencies": { + "web3-types": "^1.10.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-eth": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-4.11.1.tgz", + "integrity": "sha512-q9zOkzHnbLv44mwgLjLXuyqszHuUgZWsQayD2i/rus2uk0G7hMn11bE2Q3hOVnJS4ws4VCtUznlMxwKQ+38V2w==", + "license": "LGPL-3.0", + "dependencies": { + "setimmediate": "^1.0.5", + "web3-core": "^4.7.1", + "web3-errors": "^1.3.1", + "web3-eth-abi": "^4.4.1", + "web3-eth-accounts": "^4.3.1", + "web3-net": "^4.1.0", + "web3-providers-ws": "^4.0.8", + "web3-rpc-methods": "^1.3.0", + "web3-types": "^1.10.0", + "web3-utils": "^4.3.3", + "web3-validator": "^2.0.6" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-eth-abi": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-4.4.1.tgz", + "integrity": "sha512-60ecEkF6kQ9zAfbTY04Nc9q4eEYM0++BySpGi8wZ2PD1tw/c0SDvsKhV6IKURxLJhsDlb08dATc3iD6IbtWJmg==", + "license": "LGPL-3.0", + "dependencies": { + "abitype": "0.7.1", + "web3-errors": "^1.3.1", + "web3-types": "^1.10.0", + "web3-utils": "^4.3.3", + "web3-validator": "^2.0.6" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-eth-abi/node_modules/abitype": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/abitype/-/abitype-0.7.1.tgz", + "integrity": "sha512-VBkRHTDZf9Myaek/dO3yMmOzB/y2s3Zo6nVU7yaw1G+TvCHAjwaJzNGN9yo4K5D8bU/VZXKP1EJpRhFr862PlQ==", + "license": "MIT", + "peerDependencies": { + "typescript": ">=4.9.4", + "zod": "^3 >=3.19.1" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } + } + }, + "node_modules/web3-eth-accounts": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-4.3.1.tgz", + "integrity": "sha512-rTXf+H9OKze6lxi7WMMOF1/2cZvJb2AOnbNQxPhBDssKOllAMzLhg1FbZ4Mf3lWecWfN6luWgRhaeSqO1l+IBQ==", + "license": "LGPL-3.0", + "dependencies": { + "@ethereumjs/rlp": "^4.0.1", + "crc-32": "^1.2.2", + "ethereum-cryptography": "^2.0.0", + "web3-errors": "^1.3.1", + "web3-types": "^1.10.0", + "web3-utils": "^4.3.3", + "web3-validator": "^2.0.6" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-eth-contract": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-4.7.2.tgz", + "integrity": "sha512-3ETqs2pMNPEAc7BVY/C3voOhTUeJdkf2aM3X1v+edbngJLHAxbvxKpOqrcO0cjXzC4uc2Q8Zpf8n8zT5r0eLnA==", + "license": "LGPL-3.0", + "dependencies": { + "@ethereumjs/rlp": "^5.0.2", + "web3-core": "^4.7.1", + "web3-errors": "^1.3.1", + "web3-eth": "^4.11.1", + "web3-eth-abi": "^4.4.1", + "web3-types": "^1.10.0", + "web3-utils": "^4.3.3", + "web3-validator": "^2.0.6" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-eth-contract/node_modules/@ethereumjs/rlp": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-5.0.2.tgz", + "integrity": "sha512-DziebCdg4JpGlEqEdGgXmjqcFoJi+JGulUXwEjsZGAscAQ7MyD/7LE/GVCP29vEQxKc7AAwjT3A2ywHp2xfoCA==", + "license": "MPL-2.0", + "bin": { + "rlp": "bin/rlp.cjs" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/web3-eth-ens": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-4.4.0.tgz", + "integrity": "sha512-DeyVIS060hNV9g8dnTx92syqvgbvPricE3MerCxe/DquNZT3tD8aVgFfq65GATtpCgDDJffO2bVeHp3XBemnSQ==", + "license": "LGPL-3.0", + "dependencies": { + "@adraffy/ens-normalize": "^1.8.8", + "web3-core": "^4.5.0", + "web3-errors": "^1.2.0", + "web3-eth": "^4.8.0", + "web3-eth-contract": "^4.5.0", + "web3-net": "^4.1.0", + "web3-types": "^1.7.0", + "web3-utils": "^4.3.0", + "web3-validator": "^2.0.6" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-eth-iban": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-4.0.7.tgz", + "integrity": "sha512-8weKLa9KuKRzibC87vNLdkinpUE30gn0IGY027F8doeJdcPUfsa4IlBgNC4k4HLBembBB2CTU0Kr/HAOqMeYVQ==", + "license": "LGPL-3.0", + "dependencies": { + "web3-errors": "^1.1.3", + "web3-types": "^1.3.0", + "web3-utils": "^4.0.7", + "web3-validator": "^2.0.3" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-eth-personal": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-4.1.0.tgz", + "integrity": "sha512-RFN83uMuvA5cu1zIwwJh9A/bAj0OBxmGN3tgx19OD/9ygeUZbifOL06jgFzN0t+1ekHqm3DXYQM8UfHpXi7yDQ==", + "license": "LGPL-3.0", + "dependencies": { + "web3-core": "^4.6.0", + "web3-eth": "^4.9.0", + "web3-rpc-methods": "^1.3.0", + "web3-types": "^1.8.0", + "web3-utils": "^4.3.1", + "web3-validator": "^2.0.6" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-net": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-4.1.0.tgz", + "integrity": "sha512-WWmfvHVIXWEoBDWdgKNYKN8rAy6SgluZ0abyRyXOL3ESr7ym7pKWbfP4fjApIHlYTh8tNqkrdPfM4Dyi6CA0SA==", + "license": "LGPL-3.0", + "dependencies": { + "web3-core": "^4.4.0", + "web3-rpc-methods": "^1.3.0", + "web3-types": "^1.6.0", + "web3-utils": "^4.3.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-providers-http": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-4.2.0.tgz", + "integrity": "sha512-IPMnDtHB7dVwaB7/mMxAZzyq7d5ezfO1+Vw0bNfAeIi7gaDlJiggp85SdyAfOgov8AMUA/dyiY72kQ0KmjXKvQ==", + "license": "LGPL-3.0", + "dependencies": { + "cross-fetch": "^4.0.0", + "web3-errors": "^1.3.0", + "web3-types": "^1.7.0", + "web3-utils": "^4.3.1" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-providers-http/node_modules/cross-fetch": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.1.0.tgz", + "integrity": "sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw==", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.7.0" + } + }, + "node_modules/web3-providers-ipc": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-4.0.7.tgz", + "integrity": "sha512-YbNqY4zUvIaK2MHr1lQFE53/8t/ejHtJchrWn9zVbFMGXlTsOAbNoIoZWROrg1v+hCBvT2c9z8xt7e/+uz5p1g==", + "license": "LGPL-3.0", + "optional": true, + "dependencies": { + "web3-errors": "^1.1.3", + "web3-types": "^1.3.0", + "web3-utils": "^4.0.7" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-providers-ws": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-4.0.8.tgz", + "integrity": "sha512-goJdgata7v4pyzHRsg9fSegUG4gVnHZSHODhNnn6J93ykHkBI1nz4fjlGpcQLUMi4jAMz6SHl9Ibzs2jj9xqPw==", + "license": "LGPL-3.0", + "dependencies": { + "@types/ws": "8.5.3", + "isomorphic-ws": "^5.0.0", + "web3-errors": "^1.2.0", + "web3-types": "^1.7.0", + "web3-utils": "^4.3.1", + "ws": "^8.17.1" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-providers-ws/node_modules/@types/ws": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", + "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/web3-providers-ws/node_modules/isomorphic-ws": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", + "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/web3-providers-ws/node_modules/ws": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/web3-rpc-methods": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/web3-rpc-methods/-/web3-rpc-methods-1.3.0.tgz", + "integrity": "sha512-/CHmzGN+IYgdBOme7PdqzF+FNeMleefzqs0LVOduncSaqsppeOEoskLXb2anSpzmQAP3xZJPaTrkQPWSJMORig==", + "license": "LGPL-3.0", + "dependencies": { + "web3-core": "^4.4.0", + "web3-types": "^1.6.0", + "web3-validator": "^2.0.6" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-rpc-providers": { + "version": "1.0.0-rc.4", + "resolved": "https://registry.npmjs.org/web3-rpc-providers/-/web3-rpc-providers-1.0.0-rc.4.tgz", + "integrity": "sha512-PXosCqHW0EADrYzgmueNHP3Y5jcSmSwH+Dkqvn7EYD0T2jcsdDAIHqk6szBiwIdhumM7gv9Raprsu/s/f7h1fw==", + "license": "LGPL-3.0", + "dependencies": { + "web3-errors": "^1.3.1", + "web3-providers-http": "^4.2.0", + "web3-providers-ws": "^4.0.8", + "web3-types": "^1.10.0", + "web3-utils": "^4.3.3", + "web3-validator": "^2.0.6" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-types": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/web3-types/-/web3-types-1.10.0.tgz", + "integrity": "sha512-0IXoaAFtFc8Yin7cCdQfB9ZmjafrbP6BO0f0KT/khMhXKUpoJ6yShrVhiNpyRBo8QQjuOagsWzwSK2H49I7sbw==", + "license": "LGPL-3.0", + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-utils": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.3.3.tgz", + "integrity": "sha512-kZUeCwaQm+RNc2Bf1V3BYbF29lQQKz28L0y+FA4G0lS8IxtJVGi5SeDTUkpwqqkdHHC7JcapPDnyyzJ1lfWlOw==", + "license": "LGPL-3.0", + "dependencies": { + "ethereum-cryptography": "^2.0.0", + "eventemitter3": "^5.0.1", + "web3-errors": "^1.3.1", + "web3-types": "^1.10.0", + "web3-validator": "^2.0.6" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-validator": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/web3-validator/-/web3-validator-2.0.6.tgz", + "integrity": "sha512-qn9id0/l1bWmvH4XfnG/JtGKKwut2Vokl6YXP5Kfg424npysmtRLe9DgiNBM9Op7QL/aSiaA0TVXibuIuWcizg==", + "license": "LGPL-3.0", + "dependencies": { + "ethereum-cryptography": "^2.0.0", + "util": "^0.12.5", + "web3-errors": "^1.2.0", + "web3-types": "^1.6.0", + "zod": "^3.21.4" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.22", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.22.tgz", + "integrity": "sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==", + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ws": { + "version": "7.5.11", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.11.tgz", + "integrity": "sha512-zS54Oen9bITtp7kp2XM3AydrCIq1D+HwJOuH+c+e4LfpL/lotP5osijd+UoMnxwAam1GN8R4KtLAyIrIcBNpiA==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xmlhttprequest-ssl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", + "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/solana-x402-bridge-skill/package.json b/solana-x402-bridge-skill/package.json new file mode 100644 index 0000000..d04897d --- /dev/null +++ b/solana-x402-bridge-skill/package.json @@ -0,0 +1,29 @@ +{ + "name": "solana-x402-bridge-skill", + "version": "0.1.0", + "private": true, + "description": "Best-rate cross-chain bridge aggregator for Solana agents — quote CCTP/Mayan/deBridge/Allbridge in parallel, pick the cheapest safe route, and execute non-custodially from a Solana wallet.", + "type": "module", + "license": "MIT", + "scripts": { + "quote": "tsx scripts/bridge-quote.ts", + "auto": "tsx scripts/auto-bridge.ts", + "execute": "tsx scripts/bridge-execute.ts", + "return": "tsx scripts/bridge-return.ts", + "targets": "tsx scripts/evm-targets.ts", + "health": "tsx scripts/rpc-health.ts", + "onramp": "tsx scripts/onramp.ts", + "polymarket": "tsx scripts/polymarket.ts", + "test": "tsx scripts/test.ts" + }, + "dependencies": { + "@allbridge/bridge-core-sdk": "3.31.0", + "@solana/web3.js": "^1.95.0", + "bs58": "4.0.1", + "viem": "^2.21.0" + }, + "devDependencies": { + "tsx": "^4.19.0", + "typescript": "^5.6.0" + } +} diff --git a/solana-x402-bridge-skill/rules/safety.md b/solana-x402-bridge-skill/rules/safety.md new file mode 100644 index 0000000..0d18f8c --- /dev/null +++ b/solana-x402-bridge-skill/rules/safety.md @@ -0,0 +1,14 @@ +# Safety rules (money movement) + +These are hard rules for any agent using or extending this skill. + +1. **Quote before execute.** Always show the ranked comparison and the free-vs-paid verdict. +2. **Non-custodial only.** Private keys are read from the local `.env` and never logged, printed, + committed, or transmitted. Redact RPC URLs containing API keys in any output. +3. **Confirm gate.** Nothing broadcasts without an explicit `--confirm`. +4. **Slippage protection is mandatory.** Reject swaps whose minimum-received breaches the configured + tolerance. Allow an override only via an explicit, bounded `--accept-slippage`, and state why. +5. **Per-tx cap + destination allowlist** are enforced; do not bypass them in code. +6. **No stale reads.** Use `rpc-health` / failover; fail loud rather than act on lagging data. +7. **Disclose all costs** (bridge, swap, gas) and the minimum received before any execution. +8. **Never weaken these controls** to "make it work." Escalate to the user instead. diff --git a/solana-x402-bridge-skill/rules/typescript.md b/solana-x402-bridge-skill/rules/typescript.md new file mode 100644 index 0000000..db81cf6 --- /dev/null +++ b/solana-x402-bridge-skill/rules/typescript.md @@ -0,0 +1,14 @@ +# TypeScript rules + +Conventions for extending this skill's `scripts/`. + +- **Strict TypeScript**, ESM modules, run via `tsx`. Keep `tsc --noEmit` clean. +- **Adapters implement one interface** (`scripts/types.ts`) and return a normalized quote + (`amountOut`, `fee`, `etaSeconds`, provider id). Add a provider by adding an adapter and + registering it in `scripts/providers.ts` — nothing else should need to change. +- **No new heavy dependencies** without reason; prefer the platform `fetch` and small, audited libs. +- **Fail loud, not silent.** Throw with a clear message; never swallow errors that affect funds. +- **No secrets in code.** Read config from `env.ts` / `.env`. Never hardcode keys or addresses + that should be configurable. +- **CLI entrypoints are guarded** (`import.meta.url === ...`) so importing a module never triggers + its CLI. diff --git a/solana-x402-bridge-skill/scripts/adapters/allbridge.ts b/solana-x402-bridge-skill/scripts/adapters/allbridge.ts new file mode 100644 index 0000000..846be13 --- /dev/null +++ b/solana-x402-bridge-skill/scripts/adapters/allbridge.ts @@ -0,0 +1,145 @@ +// Allbridge Core adapter — stablecoin (USDC/USDT) Solana <-> EVM pools. +// Uses the official @allbridge/bridge-core-sdk (getAmountToBeReceived). The SDK is +// imported LAZILY inside quote() so a load/network failure is isolated to this +// provider — the aggregator simply skips it (it catches throwing providers). +// NOTE: the SDK fetches pool data from Allbridge's Core API; if that host is +// unreachable, this adapter throws and is skipped (the other providers still work). +import type { EvmChain, BridgeResult } from "../types.js"; +import type { BridgeProvider, ProviderQuote } from "../providers.js"; + +// Allbridge ChainSymbol per supported EVM chain. Gnosis is NOT supported by Allbridge Core. +const CHAIN_SYMBOL: Partial> = { + polygon: "POL", ethereum: "ETH", base: "BAS", arbitrum: "ARB", +}; + +const isStable = (t: string) => ["usdc", "usdt"].includes(t.toLowerCase()); + +// Build the SDK node-url map from env (only chains we have RPCs for). +function nodeUrls(): Record { + const urls: Record = {}; + if (process.env.SOLANA_RPC_URL) urls.SOL = process.env.SOLANA_RPC_URL; + if (process.env.POLYGON_RPC_URL) urls.POL = process.env.POLYGON_RPC_URL; + if (process.env.ETHEREUM_RPC_URL) urls.ETH = process.env.ETHEREUM_RPC_URL; + if (process.env.BASE_RPC_URL) urls.BAS = process.env.BASE_RPC_URL; + if (process.env.ARBITRUM_RPC_URL) urls.ARB = process.env.ARBITRUM_RPC_URL; + return urls; +} + +export const allbridge: BridgeProvider = { + name: "allbridge", + // Stablecoin pools only (USDC/USDT), and only on Allbridge-supported EVM chains. + supportsPair: (s, c, d) => isStable(s) && isStable(d) && !!CHAIN_SYMBOL[c], + + async quote(srcToken, amountIn, chain, destToken): Promise { + const sym = CHAIN_SYMBOL[chain]; + if (!sym) throw new Error(`allbridge: chain '${chain}' not supported`); + + // Lazy import keeps a heavy/optional dep out of the module graph. + const mod: any = await import("@allbridge/bridge-core-sdk"); + const sdk = new mod.AllbridgeCoreSdk(nodeUrls()); + + // tokens() hits Allbridge's Core API — throws here if unreachable (-> aggregator skips). + const tokens: any[] = await sdk.tokens(); + const eq = (a: string, b: string) => a?.toUpperCase() === b?.toUpperCase(); + const source = tokens.find((t) => t.chainSymbol === "SOL" && eq(t.symbol, srcToken)); + const dest = tokens.find((t) => t.chainSymbol === sym && eq(t.symbol, destToken)); + if (!source || !dest) throw new Error(`allbridge: no pool for ${srcToken} (SOL) -> ${destToken} (${sym})`); + + const amountOut = Number(await sdk.getAmountToBeReceived(String(amountIn), source, dest)); + if (!Number.isFinite(amountOut) || amountOut <= 0) throw new Error("allbridge: invalid quote"); + + // Stablecoin pool transfer: net of pool + bridge fee, ~no price impact for balanced pools. + const bridgeFeeUSDC = Math.max(0, amountIn - amountOut); + const bridgeFeeBps = amountIn > 0 ? (bridgeFeeUSDC / amountIn) * 10000 : 0; + const slippageBps = Number(process.env.DEFAULT_SLIPPAGE_BPS ?? 50); + + let etaSeconds = 120; + try { + const ms = await sdk.getAverageTransferTime(source, dest, mod.Messenger?.ALLBRIDGE); + if (Number.isFinite(ms) && ms > 0) etaSeconds = Math.round(ms / 1000); + } catch { /* fall back to default eta */ } + + return { + kind: "bridge", + route: "Allbridge Core", + srcChain: "solana", + srcToken, + destChain: chain, + destToken, + amountIn, + amountOut, + bridgeFeeUSDC, + bridgeFeeBps, + networkFeesUSDC: 0, // gas paid separately in the native token + priceImpactBps: 0, + minAmountOut: amountOut * (1 - slippageBps / 10000), + slippageBps, + etaSeconds, + feeRecipient: process.env.INTEGRATOR_FEE_ACCOUNT ?? "HFSP", + relayer: process.env.X402_RELAYER_URL ?? "https://bridge.clawdrop.live", + provider: "allbridge", + reliabilityScore: 0.85, + }; + }, + + // Real execution: build the Solana send tx via the SDK, sign locally, broadcast. + // Non-custodial — the agent's own Solana key signs; Allbridge's relayer delivers on the + // destination. Only ever called by bridge-execute AFTER preflight + requote + --confirm. + async execute(srcToken, amountIn, chain, destToken): Promise { + const sym = CHAIN_SYMBOL[chain]; + if (!sym) throw new Error(`allbridge: chain '${chain}' not supported`); + const sk = process.env.SOLANA_WALLET_PRIVATE_KEY; + if (!sk) throw new Error("allbridge.execute: SOLANA_WALLET_PRIVATE_KEY not set in .env"); + const evmPk = process.env.EVM_WALLET_PRIVATE_KEY; + if (!evmPk) throw new Error("allbridge.execute: EVM_WALLET_PRIVATE_KEY (recipient) not set in .env"); + + const mod: any = await import("@allbridge/bridge-core-sdk"); + const web3: any = await import("@solana/web3.js"); + const bs58 = (await import("bs58")).default; + const { privateKeyToAccount } = await import("viem/accounts"); + + const sdk = new mod.AllbridgeCoreSdk(nodeUrls()); + const tokens: any[] = await sdk.tokens(); + const eq = (a: string, b: string) => a?.toUpperCase() === b?.toUpperCase(); + const source = tokens.find((t) => t.chainSymbol === "SOL" && eq(t.symbol, srcToken)); + const dest = tokens.find((t) => t.chainSymbol === sym && eq(t.symbol, destToken)); + if (!source || !dest) throw new Error(`allbridge: no pool for ${srcToken} (SOL) -> ${destToken} (${sym})`); + + const keypair = web3.Keypair.fromSecretKey(bs58.decode(sk)); + const fromAddress = keypair.publicKey.toBase58(); + const toAddress = privateKeyToAccount(evmPk as `0x${string}`).address; + + // Build (validates the route; throws here if unsupported — before any broadcast). + const rawTx: any = await sdk.bridge.rawTxBuilder.send({ + amount: String(amountIn), + fromAccountAddress: fromAddress, + toAccountAddress: toAddress, + sourceToken: source, + destinationToken: dest, + messenger: mod.Messenger.ALLBRIDGE, + txFeeParams: { solana: mod.SolanaAutoTxFee }, + }); + + rawTx.sign([keypair]); + const connection = new web3.Connection(process.env.SOLANA_RPC_URL!, "confirmed"); + const sig = await connection.sendTransaction(rawTx); + await connection.confirmTransaction(sig, "confirmed"); + + return { + sourceTx: sig, + destTx: "pending — Allbridge relayer delivers on destination (poll status)", + statusId: sig, + sourceExplorer: `https://explorer.solana.com/tx/${sig}`, + destExplorer: `https://polygonscan.com/address/${toAddress}`, + }; + }, + + async status(id: string): Promise { + try { + const mod: any = await import("@allbridge/bridge-core-sdk"); + const sdk = new mod.AllbridgeCoreSdk(nodeUrls()); + const st = await sdk.getTransferStatus?.("SOL", id); + return st ? JSON.stringify(st) : `submitted: ${id}`; + } catch { return `submitted: ${id}`; } + }, +}; diff --git a/solana-x402-bridge-skill/scripts/adapters/cctp.ts b/solana-x402-bridge-skill/scripts/adapters/cctp.ts new file mode 100644 index 0000000..8ef793f --- /dev/null +++ b/solana-x402-bridge-skill/scripts/adapters/cctp.ts @@ -0,0 +1,142 @@ +// Circle CCTP (Cross-Chain Transfer Protocol) adapter — DEFAULT BENCHMARK provider. +// +// CCTP is USDC->USDC ONLY: native 1:1 burn-and-mint with NO slippage and the lowest +// cost of any route. Every other provider is judged against this baseline. +// +// There is NO price API for CCTP — it is a protocol, not a marketplace. So the quote is +// COMPUTED LOCALLY here (we do not call an external quote endpoint). The Iris attestation +// service (https://iris-api.circle.com) is only needed for the execute/status path later. +// +// Flow (for the later execute phase, NOT used by quote()): +// depositForBurn on Solana TokenMessenger -> poll Iris for attestation -> receiveMessage mint on EVM. +// +// NOTE: CCTP delivers NATIVE USDC on Polygon +// (0x3c499c542cEF5E3811e1192ce70d8cc03d5c3359), but Polymarket settles in USDC.e +// (0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174). So a downstream swap may be needed for +// the Polymarket leg even though CCTP itself is 1:1. + +import type { EvmChain, BridgeResult } from "../types.js"; +import type { BridgeProvider, ProviderQuote } from "../providers.js"; + +// Solana USDC mint (reference; used by the execute path, kept here for documentation). +const SOLANA_USDC_MINT = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"; + +// EVM chain IDs (reference for the execute path). +const CHAIN_IDS: Record = { + polygon: 137, + ethereum: 1, + base: 8453, + arbitrum: 42161, + gnosis: 100, +}; + +// Honest, small estimate of the destination mint (receiveMessage) gas cost expressed in USD. +// These are rough, conservative numbers — gas is paid in the destination native token and +// converted to USD here purely so the aggregator can rank net amount-out consistently. +const DEST_GAS_USD: Record = { + polygon: 0.01, // very cheap + base: 0.02, // L2, cheap + arbitrum: 0.02, // L2, cheap + ethereum: 2.0, // L1 mint is the expensive case + gnosis: 0.01, // xDai, very cheap +}; + +// CCTP v2 "fast transfer" is available on these chains. Fast transfers settle in ~30s and +// (optionally) carry a tiny fast-transfer fee. Chains not in this set use the STANDARD +// transfer, which waits for source finality (minutes) and is free (0 bps). +const FAST_TRANSFER_CHAINS: ReadonlySet = new Set([ + "base", + "arbitrum", + "ethereum", +]); + +// CCTP standard transfer = 0 bps. We model CCTP v2 fast transfer with a tiny ~1 bp fee. +// Toggle modeling fast transfers via env; default is fast where supported (matches the +// "lowest cost, fastest" benchmark intent) but the fee stays honest and disclosed. +const FAST_TRANSFER_FEE_BPS = 1; // ~0.01% +const STANDARD_TRANSFER_FEE_BPS = 0; + +// ETAs (seconds). Documented, reasonable values: +// - CCTP v2 fast transfer: ~30s on supported chains. +// - Standard CCTP: source finality before attestation, on the order of minutes — use ~120s. +const FAST_ETA_SECONDS = 30; +const STANDARD_ETA_SECONDS = 120; + +const isUsdc = (t: string) => t.toLowerCase() === "usdc"; + +export const cctp: BridgeProvider = { + name: "cctp", + + // USDC->USDC only (case-insensitive). chain is irrelevant to eligibility here. + supportsPair(srcToken: string, _chain: EvmChain, destToken: string): boolean { + return isUsdc(srcToken) && isUsdc(destToken); + }, + + async quote( + srcToken: string, + amountIn: number, + chain: EvmChain, + destToken: string, + ): Promise { + if (!(isUsdc(srcToken) && isUsdc(destToken))) { + throw new Error( + `cctp.quote: unsupported pair ${srcToken}->${destToken} (CCTP is USDC->USDC only)`, + ); + } + + const isFast = FAST_TRANSFER_CHAINS.has(chain); + const bridgeFeeBps = isFast ? FAST_TRANSFER_FEE_BPS : STANDARD_TRANSFER_FEE_BPS; + const etaSeconds = isFast ? FAST_ETA_SECONDS : STANDARD_ETA_SECONDS; + + // Destination gas (USD) — the only meaningful cost on a native 1:1 burn/mint route. + const networkFeesUSDC = DEST_GAS_USD[chain] ?? 0.02; + + // Protocol fee (0 for standard, ~1 bp if modeling CCTP v2 fast). Disclosed honestly. + const bridgeFeeUSDC = amountIn * (bridgeFeeBps / 10000); + + // Native 1:1 burn-and-mint: out = in minus protocol fee minus destination gas. No slippage. + const amountOut = amountIn - bridgeFeeUSDC - networkFeesUSDC; + + return { + kind: "bridge", + route: "CCTP (burn/mint)", + srcChain: "solana", + srcToken, + destChain: chain, + destToken, + amountIn, + amountOut, + bridgeFeeUSDC, + bridgeFeeBps, + networkFeesUSDC, + priceImpactBps: 0, // native 1:1, no AMM, no impact + minAmountOut: amountOut, // no slippage => min == expected + slippageBps: 0, + etaSeconds, + feeRecipient: process.env.INTEGRATOR_FEE_ACCOUNT ?? "HFSP", + relayer: process.env.X402_RELAYER_URL ?? "https://bridge.clawdrop.live", + provider: "cctp", + reliabilityScore: 0.99, + }; + }, + + // execute/status are intentionally stubbed for the quote-only MVP. The real path + // (depositForBurn -> Iris attestation -> receiveMessage) lands in a later phase. + // SOLANA_USDC_MINT / CHAIN_IDS above are the reference values that path will use. + async execute( + _srcToken: string, + _amountIn: number, + _chain: EvmChain, + _destToken: string, + ): Promise { + throw new Error("cctp.execute not implemented in quote-only MVP — see PROVIDERS.md #1"); + }, + + async status(_id: string): Promise { + throw new Error("cctp.status not implemented in quote-only MVP — see PROVIDERS.md #1"); + }, +}; + +// Reference exports are kept local; silence unused warnings without exporting extra surface. +void SOLANA_USDC_MINT; +void CHAIN_IDS; diff --git a/solana-x402-bridge-skill/scripts/adapters/debridge.ts b/solana-x402-bridge-skill/scripts/adapters/debridge.ts new file mode 100644 index 0000000..fe6db4f --- /dev/null +++ b/solana-x402-bridge-skill/scripts/adapters/debridge.ts @@ -0,0 +1,133 @@ +// deBridge (DLN — deBridge Liquidity Network) adapter. +// Fast intent-based liquidity network with native Solana <-> EVM support. +// ANY token -> ANY token (USDC->USDC bridge AND swaps like SOL->ETH). +// Quote API: GET https://dln.debridge.finance/v1.0/dln/order/quote (public, no key). +import type { EvmChain, BridgeResult } from "../types.js"; +import type { BridgeProvider, ProviderQuote } from "../providers.js"; + +const SOLANA_DLN_CHAIN_ID = 7565164; + +const DST_CHAIN_ID: Record = { + polygon: 137, ethereum: 1, base: 8453, arbitrum: 42161, gnosis: 100, +}; + +// Token address resolution. Native sentinels per deBridge convention. +const SOL_NATIVE = "11111111111111111111111111111111"; // SystemProgram = native SOL +const EVM_NATIVE = "0x0000000000000000000000000000000000000000"; + +const SRC_TOKENS: Record = { + usdc: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + sol: SOL_NATIVE, +}; + +// Destination token addresses per chain. "usdc" = canonical bridged USDC (CCTP-style), +// "usdc.e" = the Polygon PoS bridged USDC.e that Polymarket uses. +const DST_TOKENS: Record> = { + polygon: { usdc: "0x3c499c542cEF5E3811e1192ce70d8cc03d5c3359", "usdc.e": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", eth: EVM_NATIVE }, + ethereum: { usdc: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", eth: EVM_NATIVE }, + base: { usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", eth: EVM_NATIVE }, + arbitrum: { usdc: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", eth: EVM_NATIVE }, + gnosis: { usdc: "0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83" }, +}; + +const SRC_DECIMALS: Record = { usdc: 6, sol: 9 }; + +function resolveSrc(token: string): string { + const a = SRC_TOKENS[token.toLowerCase()]; + if (!a) throw new Error(`debridge: unsupported source token '${token}'`); + return a; +} +function resolveDst(chain: EvmChain, token: string): string { + const a = DST_TOKENS[chain]?.[token.toLowerCase()]; + if (!a) throw new Error(`debridge: unsupported dest token '${token}' on ${chain}`); + return a; +} +function toAtomic(amount: number, token: string): string { + const dec = SRC_DECIMALS[token.toLowerCase()] ?? 6; + return BigInt(Math.round(amount * 10 ** dec)).toString(); +} + +export const debridge: BridgeProvider = { + name: "debridge", + supportsPair: () => true, // any -> any + + async quote(srcToken, amountIn, chain, destToken): Promise { + const dstChainId = DST_CHAIN_ID[chain]; + if (!dstChainId) throw new Error(`debridge: unsupported chain '${chain}'`); + + const params = new URLSearchParams({ + srcChainId: String(SOLANA_DLN_CHAIN_ID), + srcChainTokenIn: resolveSrc(srcToken), + srcChainTokenInAmount: toAtomic(amountIn, srcToken), + dstChainId: String(dstChainId), + dstChainTokenOut: resolveDst(chain, destToken), + // false => srcChainTokenInAmount is the exact spend; operating expenses come OUT of the output. + prependOperatingExpenses: "false", + }); + + const url = `https://dln.debridge.finance/v1.0/dln/order/quote?${params}`; + const res = await fetch(url); + const json: any = await res.json(); + if (!res.ok || json.error || !json.estimation) { + throw new Error(`debridge quote failed: ${json.errorMessage ?? json.error ?? res.status}`); + } + + const est = json.estimation; + const dst = est.dstChainTokenOut; + const destDec: number = dst.decimals ?? 6; + const amountOut = Number(dst.recommendedAmount ?? dst.amount) / 10 ** destDec; + + const kind = srcToken.toLowerCase() === destToken.toLowerCase() ? "bridge" : "swap"; + + // Fees: DLN protocol fee + taker margin are the provider fee. Operating expenses are network/gas. + const costs: any[] = Array.isArray(est.costsDetails) ? est.costsDetails : []; + const usdcAmt = (c: any) => Number(c?.payload?.feeAmount ?? 0) / 1e6; + const protocolFee = Number(json.protocolFeeApproximateUsdValue ?? 0); + const takerMargin = usdcAmt(costs.find((c) => c.type === "TakerMargin")); + const bridgeFeeUSDC = protocolFee + takerMargin; + const opExpense = usdcAmt(costs.find((c) => c.type === "EstimatedOperatingExpenses")); + + // Solana fixed protocol fee, paid in SOL (lamports). Disclosed as a network cost (rough USD). + const solPriceUsd = Number(process.env.SOL_PRICE_USD ?? 150); + const fixFeeUsd = (Number(json.fixFee ?? 0) / 1e9) * solPriceUsd; + const networkFeesUSDC = opExpense + fixFeeUsd; + + const bridgeFeeBps = amountIn > 0 ? (bridgeFeeUSDC / amountIn) * 10000 : 0; + + // Same-asset transfers have no price impact; swaps take it from the reported usd impact. + const priceImpactBps = kind === "bridge" ? 0 : Math.abs(Number(json.usdPriceImpact ?? 0)) * 100; + + const slippageBps = Number(process.env.DEFAULT_SLIPPAGE_BPS ?? 50); + const minAmountOut = amountOut * (1 - slippageBps / 10000); + const etaSeconds = Number(json.order?.approximateFulfillmentDelay ?? 30) + 20; + + return { + kind, + route: "deBridge DLN", + srcChain: "solana", + srcToken, + destChain: chain, + destToken, + amountIn, + amountOut, + bridgeFeeUSDC, + bridgeFeeBps, + networkFeesUSDC, + priceImpactBps, + minAmountOut, + slippageBps, + etaSeconds, + feeRecipient: process.env.INTEGRATOR_FEE_ACCOUNT ?? "HFSP", + relayer: process.env.X402_RELAYER_URL ?? "https://bridge.clawdrop.live", + provider: "debridge", + reliabilityScore: 0.9, + }; + }, + + async execute(): Promise { + throw new Error("debridge.execute not implemented in quote-only MVP — PROVIDERS.md #3 (create-tx + sign)"); + }, + async status(): Promise { + throw new Error("debridge.status not implemented in quote-only MVP — PROVIDERS.md #3"); + }, +}; diff --git a/solana-x402-bridge-skill/scripts/adapters/mayan.ts b/solana-x402-bridge-skill/scripts/adapters/mayan.ts new file mode 100644 index 0000000..0bd4b4e --- /dev/null +++ b/solana-x402-bridge-skill/scripts/adapters/mayan.ts @@ -0,0 +1,119 @@ +// Mayan Finance adapter. Solana-native cross-chain (Swift / MCTP / Wormhole routes). +// ANY token -> ANY token, so it handles USDC->USDC bridges AND swaps (e.g. SOL->ETH). +// Quote API: GET https://price-api.mayan.finance/v3/quote (public; sdkVersion required for Swift v2). +import type { EvmChain, BridgeResult } from "../types.js"; +import type { BridgeProvider, ProviderQuote } from "../providers.js"; + +// Mayan chain names match our EvmChain names; Solana source is "solana". +const SRC_TOKENS: Record = { + usdc: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + sol: "So11111111111111111111111111111111111111112", // wSOL mint represents native SOL +}; +const EVM_NATIVE = "0x0000000000000000000000000000000000000000"; + +const DST_TOKENS: Record> = { + polygon: { usdc: "0x3c499c542cEF5E3811e1192ce70d8cc03d5c3359", "usdc.e": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", eth: EVM_NATIVE }, + ethereum: { usdc: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", eth: EVM_NATIVE }, + base: { usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", eth: EVM_NATIVE }, + arbitrum: { usdc: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", eth: EVM_NATIVE }, + gnosis: { usdc: "0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83" }, +}; + +const SRC_DECIMALS: Record = { usdc: 6, sol: 9 }; + +function resolveSrc(token: string): string { + const a = SRC_TOKENS[token.toLowerCase()]; + if (!a) throw new Error(`mayan: unsupported source token '${token}'`); + return a; +} +function resolveDst(chain: EvmChain, token: string): string { + const a = DST_TOKENS[chain]?.[token.toLowerCase()]; + if (!a) throw new Error(`mayan: unsupported dest token '${token}' on ${chain}`); + return a; +} +function toAtomic(amount: number, token: string): string { + const dec = SRC_DECIMALS[token.toLowerCase()] ?? 6; + return BigInt(Math.round(amount * 10 ** dec)).toString(); +} + +export const mayan: BridgeProvider = { + name: "mayan", + supportsPair: () => true, // any -> any + + async quote(srcToken, amountIn, chain, destToken): Promise { + const params = new URLSearchParams({ + amountIn64: toAtomic(amountIn, srcToken), + fromToken: resolveSrc(srcToken), + fromChain: "solana", + toToken: resolveDst(chain, destToken), + toChain: chain, + slippageBps: "auto", + gasDrop: "0", + // enable all route protocols; sdkVersion >= 13.0.0 is required to receive Swift v2 routes + swift: "true", mctp: "true", fastMctp: "true", wormhole: "true", + referrerBps: String(process.env.MAYAN_REFERRER_BPS ?? 0), + sdkVersion: "13_1_0", + }); + if (process.env.MAYAN_REFERRER) params.set("referrer", process.env.MAYAN_REFERRER); + + const url = `https://price-api.mayan.finance/v3/quote?${params}`; + const res = await fetch(url); + const json: any = await res.json(); + const quotes: any[] = json?.quotes ?? []; + if (!res.ok || json.code || quotes.length === 0) { + throw new Error(`mayan quote failed: ${json.msg ?? json.code ?? res.status}`); + } + + // Best route = highest expected output. + const q = quotes.reduce((best, cur) => + Number(cur.expectedAmountOut) > Number(best.expectedAmountOut) ? cur : best); + + const kind = srcToken.toLowerCase() === destToken.toLowerCase() ? "bridge" : "swap"; + const amountOut = Number(q.expectedAmountOut); + const minAmountOut = Number(q.minAmountOut ?? q.minReceived ?? amountOut); + const slippageBps = Number(q.slippageBps ?? process.env.DEFAULT_SLIPPAGE_BPS ?? 50); + + // Provider fee (protocol + referrer), disclosed in USD. + const bridgeFeeUSDC = Number(q.protocolFeeUsd ?? 0) + Number(q.referrerFeeUsd ?? 0); + const bridgeFeeBps = (Number(q.protocolBps ?? 0) + Number(q.referrerBps ?? 0)); + + // priceImpact is a fraction when present (null for clean stable routes). + const priceImpactBps = kind === "bridge" + ? 0 + : (q.priceImpact != null ? Math.abs(Number(q.priceImpact)) * 10000 : 0); + + // For same-asset USDC bridge, residual (in - out - providerFee) is the network/relayer cost. + const networkFeesUSDC = kind === "bridge" + ? Math.max(0, amountIn - amountOut - bridgeFeeUSDC) + : Number(q.clientRelayerFeeSuccess ?? 0); + + return { + kind, + route: `Mayan ${q.type ?? ""}`.trim(), + srcChain: "solana", + srcToken, + destChain: chain, + destToken, + amountIn, + amountOut, + bridgeFeeUSDC, + bridgeFeeBps, + networkFeesUSDC, + priceImpactBps, + minAmountOut, + slippageBps, + etaSeconds: Number(q.etaSeconds ?? 60), + feeRecipient: process.env.INTEGRATOR_FEE_ACCOUNT ?? "HFSP", + relayer: process.env.X402_RELAYER_URL ?? "https://bridge.clawdrop.live", + provider: "mayan", + reliabilityScore: 0.9, + }; + }, + + async execute(): Promise { + throw new Error("mayan.execute not implemented in quote-only MVP — PROVIDERS.md #2 (swapFromSolana)"); + }, + async status(): Promise { + throw new Error("mayan.status not implemented in quote-only MVP — PROVIDERS.md #2"); + }, +}; diff --git a/solana-x402-bridge-skill/scripts/auto-bridge.ts b/solana-x402-bridge-skill/scripts/auto-bridge.ts new file mode 100644 index 0000000..f17b9b1 --- /dev/null +++ b/solana-x402-bridge-skill/scripts/auto-bridge.ts @@ -0,0 +1,93 @@ +// auto-bridge — the one-call "automatic best-route bridge". +// Aggregates every eligible provider, picks the best net route, runs the mandatory +// safety preflight, and (optionally) routes execution to the winning provider. +// Dry-run by DEFAULT: it never moves funds unless you pass --execute. It will NEVER +// execute without a passing bridge-safety preflight. +// +// usage: +// tsx scripts/auto-bridge.ts [--execute] +// tsx scripts/auto-bridge.ts USDC 5 polygon USDC # dry-run: best route + safety, no funds moved +// tsx scripts/auto-bridge.ts USDC 5 polygon USDC --execute # route real funds via the winning provider +import "./env.js"; +import { aggregate } from "./bridge-aggregator.js"; +import { preflight, requoteGuard, describeSwapSlippage } from "./bridge-safety.js"; +import { PROVIDERS } from "./providers.js"; +import type { EvmChain, BridgeResult, SafetyResult } from "./types.js"; +import type { ProviderQuote } from "./providers.js"; + +export interface AutoBridgeResult { + mode: "dry-run" | "executed"; + chosen: ProviderQuote; + ranked: ProviderQuote[]; + safety: SafetyResult; + result?: BridgeResult; + note?: string; +} + +export async function autoBridge( + srcToken: string, + amountIn: number, + destChain: EvmChain, + destToken: string, + opts: { execute?: boolean; acceptSlippageBps?: number } = {}, +): Promise { + // 1. Shop every eligible provider, take the best net amount-out. + const { best, ranked } = await aggregate(srcToken, amountIn, destChain, destToken); + if (!best) throw new Error(`auto-bridge: no eligible route for ${srcToken} -> ${destToken} on ${destChain}`); + + // 2. Mandatory safety preflight (allowlist, caps, cross-chain RPC freshness, swap slippage). Fail loud. + const safety = await preflight(srcToken, amountIn, destChain, destToken, best, { acceptSlippageBps: opts.acceptSlippageBps }); + if (!safety.ok) throw new Error("auto-bridge blocked by safety preflight: " + safety.failures.join("; ")); + + // 3. Dry-run by default — never move funds unless explicitly told to. + if (!opts.execute) { + return { mode: "dry-run", chosen: best, ranked, safety, note: "dry-run only — pass --execute to route real funds via the winning provider" }; + } + + // 4. Re-quote right before execute; abort swaps that drifted below the minAmountOut floor. + const rq = await requoteGuard(srcToken, amountIn, destChain, destToken, best); + if (!rq.ok) throw new Error("auto-bridge blocked by re-quote guard: " + rq.reason); + + // 5. Route execution to the winning provider's adapter. + const result = await PROVIDERS[best.provider].execute(srcToken, amountIn, destChain, destToken); + return { mode: "executed", chosen: best, ranked, safety, result }; +} + +// ---- CLI ---- +if (import.meta.url === `file://${process.argv[1]}`) { + const args = process.argv.slice(2); + const execute = args.includes("--execute"); + const accArg = args.find((a) => a.startsWith("--accept-slippage=")); + const acceptSlippageBps = accArg ? Number(accArg.split("=")[1]) : undefined; + const [srcToken, amountIn, destChain, destToken] = args.filter((a) => !a.startsWith("--")); + + autoBridge(srcToken, Number(amountIn), destChain as EvmChain, destToken, { execute, acceptSlippageBps }) + .then((r) => { + const c = r.chosen; + const slip = describeSwapSlippage(c); + const summary: Record = { + winner: c.provider, + amountIn: `${c.amountIn} ${c.srcToken}`, + amountOut: `${c.amountOut} ${c.destToken}`, + route: c.route, + fee: `${c.bridgeFeeUSDC} (${c.bridgeFeeBps.toFixed(1)} bps)`, + etaSeconds: c.etaSeconds, + safety: { ok: r.safety.ok, usedRpc: r.safety.usedRpc, slotLag: r.safety.rpcSlotLag }, + }; + if (slip.isSwap) { + summary.slippageTolerance = `${slip.tolerancePct} (${slip.bps} bps)`; + summary.minReceived = `${c.minAmountOut} ${c.destToken} (worst case)`; + } + console.log(`AUTO-BRIDGE [${r.mode}] — chose ${c.provider} (${c.kind})`); + console.log(JSON.stringify(summary, null, 2)); + if (slip.isSwap && slip.aboveDefaultCap) { + console.log(` ⚠ HIGH slippage: ${slip.tolerancePct} consciously accepted (above the ${slip.defaultCapPct} default cap) — worst case ${c.minAmountOut} ${c.destToken}`); + } + console.log("\nROUTES CONSIDERED (ranked by net amountOut):"); + for (const q of r.ranked) + console.log(` ${q.provider.padEnd(10)} out=${q.amountOut} ${q.destToken} fee=${q.bridgeFeeBps.toFixed(1)}bps eta=${q.etaSeconds}s`); + if (r.note) console.log(`\n${r.note}`); + if (r.result) console.log("\nEXECUTION:", JSON.stringify(r.result, null, 2)); + }) + .catch((e) => { console.error(String(e.message ?? e)); process.exit(1); }); +} diff --git a/solana-x402-bridge-skill/scripts/bridge-aggregator.ts b/solana-x402-bridge-skill/scripts/bridge-aggregator.ts new file mode 100644 index 0000000..36c6be4 --- /dev/null +++ b/solana-x402-bridge-skill/scripts/bridge-aggregator.ts @@ -0,0 +1,25 @@ +// Aggregate providers for a bridge (USDC->USDC) OR cross-chain swap (e.g. SOL->ETH). +// Returns best net route + ranked comparison. Eligibility via each adapter's supports(). +import { PROVIDERS, type ProviderQuote } from "./providers.js"; +import type { EvmChain } from "./types.js"; + +export async function aggregate( + srcToken: string, + amountIn: number, + destChain: EvmChain, + destToken: string, +) { + const maxEta = Number(process.env.MAX_BRIDGE_ETA_SECONDS ?? 300); + const active = Object.values(PROVIDERS).filter((p) => p.supportsPair(srcToken, destChain, destToken)); + + const quotes: ProviderQuote[] = []; + await Promise.all(active.map(async (p) => { + try { quotes.push(await p.quote(srcToken, amountIn, destChain, destToken)); } catch { /* skip failed */ } + })); + + const eligible = quotes + .filter((q) => q.etaSeconds <= maxEta && q.reliabilityScore >= 0.5) + .sort((a, b) => b.amountOut - a.amountOut); // best net out (in destToken) first + + return { best: eligible[0] ?? null, ranked: eligible }; +} diff --git a/solana-x402-bridge-skill/scripts/bridge-execute.ts b/solana-x402-bridge-skill/scripts/bridge-execute.ts new file mode 100644 index 0000000..67c1384 --- /dev/null +++ b/solana-x402-bridge-skill/scripts/bridge-execute.ts @@ -0,0 +1,91 @@ +// usage: tsx scripts/bridge-execute.ts [flags] +// flags: --provider= --accept-slippage= --confirm +// Aggregate -> safety preflight -> re-quote guard -> PLAN preview. Broadcasts ONLY with --confirm. +// Without --confirm it never moves funds: it prints exactly what would happen and stops. +import "./env.js"; +import { preflight, requoteGuard } from "./bridge-safety.js"; +import { aggregate } from "./bridge-aggregator.js"; +import { PROVIDERS } from "./providers.js"; +import type { EvmChain } from "./types.js"; + +const redact = (u?: string) => (u ?? "").replace(/api-key=[^&]+/i, "api-key=***"); + +// Derive the configured wallet addresses for the plan (public info only). +async function walletAddrs() { + let sol = "(SOLANA_WALLET_PRIVATE_KEY not set)"; + let evm = "(EVM_WALLET_PRIVATE_KEY not set)"; + try { + if (process.env.SOLANA_WALLET_PRIVATE_KEY) { + const web3: any = await import("@solana/web3.js"); + const bs58 = (await import("bs58")).default; + sol = web3.Keypair.fromSecretKey(bs58.decode(process.env.SOLANA_WALLET_PRIVATE_KEY)).publicKey.toBase58(); + } + } catch { /* leave placeholder */ } + try { + if (process.env.EVM_WALLET_PRIVATE_KEY) { + const { privateKeyToAccount } = await import("viem/accounts"); + evm = privateKeyToAccount(process.env.EVM_WALLET_PRIVATE_KEY as `0x${string}`).address; + } + } catch { /* leave placeholder */ } + return { sol, evm }; +} + +async function run( + srcToken: string, + amountIn: number, + chain: EvmChain, + destToken: string, + opts: { acceptSlippageBps?: number; confirm?: boolean; provider?: string }, +) { + // 1. Best route (or a pinned provider). + const { best, ranked } = await aggregate(srcToken, amountIn, chain, destToken); + const chosen = opts.provider ? ranked.find((q) => q.provider === opts.provider) : best; + if (!chosen) throw new Error(opts.provider ? `provider '${opts.provider}' not eligible for this route` : "No eligible route"); + + // 2. Mandatory preflight (allowlist, caps, RPC health, swap slippage protection). + const safety = await preflight(srcToken, amountIn, chain, destToken, chosen, { acceptSlippageBps: opts.acceptSlippageBps }); + if (!safety.ok) throw new Error("Safety preflight failed: " + safety.failures.join("; ")); + + // 3. Re-quote right before execute; abort swaps that drifted below minAmountOut. + const rq = await requoteGuard(srcToken, amountIn, chain, destToken, chosen); + if (!rq.ok) throw new Error("Re-quote guard blocked execution: " + rq.reason); + + // 4. Plan preview (no funds moved). + const { sol, evm } = await walletAddrs(); + console.log("=== BRIDGE PLAN ==="); + console.log(JSON.stringify({ + provider: chosen.provider, + route: chosen.route, + kind: chosen.kind, + amountIn: `${amountIn} ${srcToken}`, + expectedOut: `${chosen.amountOut} ${destToken}`, + minReceived: `${chosen.minAmountOut} ${destToken}`, + fee: `${chosen.bridgeFeeUSDC} (${chosen.bridgeFeeBps.toFixed(1)} bps)`, + from: sol, + to: evm, + destChain: chain, + etaSeconds: chosen.etaSeconds, + solanaRpc: redact(safety.usedRpc), + }, null, 2)); + + // 5. Broadcast only on explicit --confirm. + if (!opts.confirm) { + console.log("\nDRY-RUN — no funds moved. Re-run with --confirm to broadcast (moves REAL funds)."); + return; + } + console.log("\n--confirm set → broadcasting via", chosen.provider, "..."); + const result = await PROVIDERS[chosen.provider].execute(srcToken, amountIn, chain, destToken); + console.log("=== EXECUTED ==="); + console.log(JSON.stringify(result, null, 2)); +} + +const args = process.argv.slice(2); +const confirm = args.includes("--confirm"); +const accArg = args.find((a) => a.startsWith("--accept-slippage=")); +const provArg = args.find((a) => a.startsWith("--provider=")); +const acceptSlippageBps = accArg ? Number(accArg.split("=")[1]) : undefined; +const provider = provArg ? provArg.split("=")[1] : undefined; +const [srcToken, amountIn, chain, destToken] = args.filter((a) => !a.startsWith("--")); + +run(srcToken, Number(amountIn), chain as EvmChain, destToken, { acceptSlippageBps, confirm, provider }) + .catch((e) => { console.error(String(e.message ?? e)); process.exit(1); }); diff --git a/solana-x402-bridge-skill/scripts/bridge-quote.ts b/solana-x402-bridge-skill/scripts/bridge-quote.ts new file mode 100644 index 0000000..89172ca --- /dev/null +++ b/solana-x402-bridge-skill/scripts/bridge-quote.ts @@ -0,0 +1,50 @@ +// usage: tsx scripts/bridge-quote.ts +// bridge: tsx scripts/bridge-quote.ts USDC 5 polygon USDC +// swap: tsx scripts/bridge-quote.ts SOL 1 ethereum ETH +import "./env.js"; +import { aggregate } from "./bridge-aggregator.js"; +import { describeSwapSlippage } from "./bridge-safety.js"; +import type { ProviderQuote } from "./providers.js"; +import type { EvmChain } from "./types.js"; + +// "Should you pay for aggregation?" — honest free-vs-paid verdict. +// FREE tier = CCTP (USDC same-asset). PAID tier = full multi-provider aggregation + swaps. +// Only pay when the best paid route beats free CCTP by more than the integrator fee. +function paidValueVerdict(ranked: ProviderQuote[], best: ProviderQuote, srcToken: string, amountIn: number): string | null { + if (best.kind === "swap") { + return "Free tier (CCTP) can't do swaps — cross-chain swaps are the paid capability (no free fallback)."; + } + if (srcToken.toLowerCase() !== "usdc") return null; + const free = ranked.find((q) => q.provider === "cctp"); + if (!free) return null; + const f = (n: number) => n.toFixed(6); + if (best.provider === "cctp") { + return `Free CCTP is already the best route (${f(free.amountOut)} USDC) — no need to pay for aggregation.`; + } + const floor = Number(process.env.QUOTE_FEE_FLOOR_USDC ?? 0.02); + const bps = Number(process.env.INTEGRATOR_FEE_BPS ?? 15); + const fee = floor + (amountIn * bps) / 10000; + const savings = best.amountOut - free.amountOut; + const net = savings - fee; + const verdict = net > 0 ? `net +${f(net)} USDC → worth paying` : `net ${f(net)} USDC → use FREE CCTP`; + return `Free CCTP: ${f(free.amountOut)} | Best paid (${best.provider}): ${f(best.amountOut)} | saves ${f(savings)} − fee ~${f(fee)} → ${verdict}`; +} + +const [srcToken, amountIn, destChain, destToken] = process.argv.slice(2); +aggregate(srcToken, Number(amountIn), destChain as EvmChain, destToken).then(({ best, ranked }) => { + if (!best) { console.log("No eligible route for this pair."); return; } + console.log(`BEST (${best.kind}):`, JSON.stringify(best, null, 2)); + if (best.kind === "swap") { + const s = describeSwapSlippage(best); + const flag = s.aboveDefaultCap + ? ` ⚠ above ${s.defaultCapPct} default cap — needs --accept-slippage=${s.bps} to execute` + : " (within default cap)"; + console.log(` slippage tolerance: ${s.tolerancePct} (${s.bps} bps); min received ${best.minAmountOut} ${best.destToken}${flag}`); + } + console.log("\nCOMPARISON (ranked, net of fees + impact):"); + for (const q of ranked) + console.log(` ${q.provider.padEnd(10)} out=${q.amountOut} ${q.destToken} impact=${q.priceImpactBps}bps eta=${q.etaSeconds}s`); + + const verdict = paidValueVerdict(ranked, best, srcToken, Number(amountIn)); + if (verdict) console.log(`\nFREE vs PAID: ${verdict}`); +}); diff --git a/solana-x402-bridge-skill/scripts/bridge-return.ts b/solana-x402-bridge-skill/scripts/bridge-return.ts new file mode 100644 index 0000000..94f1e73 --- /dev/null +++ b/solana-x402-bridge-skill/scripts/bridge-return.ts @@ -0,0 +1,98 @@ +// usage: tsx scripts/bridge-return.ts [--confirm] +// The RETURN leg of a round trip: Polygon -> Solana USDC via Allbridge. +// (The core aggregator is Solana-front-door; this dedicated utility runs the reverse +// direction for round-trip demos.) EVM source: approve-if-needed then send, signed +// locally with viem; the Solana wallet receives. Preview by default; broadcasts only +// with --confirm. No funds move without --confirm. +import "./env.js"; + +async function main(amount: number, confirm: boolean) { + const evmPk = process.env.EVM_WALLET_PRIVATE_KEY; + const solSk = process.env.SOLANA_WALLET_PRIVATE_KEY; + if (!evmPk) throw new Error("bridge-return: EVM_WALLET_PRIVATE_KEY not set in .env"); + if (!solSk) throw new Error("bridge-return: SOLANA_WALLET_PRIVATE_KEY (recipient) not set in .env"); + if (!process.env.POLYGON_RPC_URL) throw new Error("bridge-return: POLYGON_RPC_URL not set"); + + const mod: any = await import("@allbridge/bridge-core-sdk"); + const { createWalletClient, createPublicClient, http } = await import("viem"); + const { privateKeyToAccount } = await import("viem/accounts"); + const { polygon } = await import("viem/chains"); + const web3: any = await import("@solana/web3.js"); + const bs58 = (await import("bs58")).default; + + const solAddr = web3.Keypair.fromSecretKey(bs58.decode(solSk)).publicKey.toBase58(); + const account = privateKeyToAccount(evmPk as `0x${string}`); + const evmAddr = account.address; + + const nodeUrls: any = {}; + if (process.env.SOLANA_RPC_URL) nodeUrls.SOL = process.env.SOLANA_RPC_URL; + nodeUrls.POL = process.env.POLYGON_RPC_URL; + + const sdk = new mod.AllbridgeCoreSdk(nodeUrls); + const tokens: any[] = await sdk.tokens(); + const eq = (a: string, b: string) => a?.toUpperCase() === b?.toUpperCase(); + const source = tokens.find((t) => t.chainSymbol === "POL" && eq(t.symbol, "USDC")); + const dest = tokens.find((t) => t.chainSymbol === "SOL" && eq(t.symbol, "USDC")); + if (!source || !dest) throw new Error("bridge-return: Polygon USDC -> Solana USDC pool not found"); + + const out = Number(await sdk.getAmountToBeReceived(String(amount), source, dest)); + + console.log("=== RETURN BRIDGE PLAN (Polygon -> Solana) ==="); + console.log(JSON.stringify({ + provider: "allbridge", + amountIn: `${amount} USDC (polygon)`, + expectedOut: `${out} USDC (solana)`, + from: evmAddr, + to: solAddr, + gasToken: "MATIC", + }, null, 2)); + + if (!confirm) { + console.log("\nDRY-RUN — no funds moved. Re-run with --confirm to broadcast (moves REAL funds)."); + return; + } + + const walletClient = createWalletClient({ account, chain: polygon, transport: http(process.env.POLYGON_RPC_URL) }); + const publicClient = createPublicClient({ chain: polygon, transport: http(process.env.POLYGON_RPC_URL) }); + const sendRaw = async (tx: any): Promise => { + const hash = await walletClient.sendTransaction({ to: tx.to, data: tx.data, value: tx.value ? BigInt(tx.value) : 0n }); + await publicClient.waitForTransactionReceipt({ hash }); + return hash; + }; + + // Approve the bridge to spend USDC if the current allowance is insufficient. + const enough = await sdk.bridge.checkAllowance({ + token: source, owner: evmAddr, + gasFeePaymentMethod: mod.FeePaymentMethod.WITH_NATIVE_CURRENCY, + amount: String(amount), + }); + if (!enough) { + console.log("approving USDC spend (allowance insufficient)..."); + const approveTx = await sdk.bridge.rawTxBuilder.approve({ token: source, owner: evmAddr }); + console.log("approve tx:", await sendRaw(approveTx)); + } + + console.log("--confirm set → broadcasting Polygon->Solana send..."); + const sendTx = await sdk.bridge.rawTxBuilder.send({ + amount: String(amount), + fromAccountAddress: evmAddr, + toAccountAddress: solAddr, + sourceToken: source, + destinationToken: dest, + messenger: mod.Messenger.ALLBRIDGE, + }); + const hash = await sendRaw(sendTx); + console.log("=== EXECUTED ==="); + console.log(JSON.stringify({ + sourceTx: hash, + sourceExplorer: `https://polygonscan.com/tx/${hash}`, + destWallet: solAddr, + destExplorer: `https://explorer.solana.com/address/${solAddr}`, + note: "Allbridge relayer mints USDC on Solana shortly", + }, null, 2)); +} + +const args = process.argv.slice(2); +const confirm = args.includes("--confirm"); +const amount = Number(args.find((a) => !a.startsWith("--")) ?? "0.5"); +main(amount, confirm).catch((e) => { console.error(String(e.message ?? e)); process.exit(1); }); diff --git a/solana-x402-bridge-skill/scripts/bridge-safety.ts b/solana-x402-bridge-skill/scripts/bridge-safety.ts new file mode 100644 index 0000000..da92016 --- /dev/null +++ b/solana-x402-bridge-skill/scripts/bridge-safety.ts @@ -0,0 +1,104 @@ +// Mandatory preflight. Fail loud; never silently proceed. +// Checks BOTH chains' RPC health (source Solana + destination EVM) before any execution, +// and — for cross-chain SWAPS (srcToken != destToken) — enforces slippage protection. +import { getHealthySolana, getHealthyEvmRpc } from "./rpc-health.js"; +import { aggregate } from "./bridge-aggregator.js"; +import type { SafetyResult } from "./types.js"; +import type { ProviderQuote } from "./providers.js"; + +const MAX_SLIPPAGE_BPS = Number(process.env.MAX_SLIPPAGE_BPS ?? 300); // default comfortable cap (3%) +const ABSOLUTE_MAX_SLIPPAGE_BPS = Number(process.env.ABSOLUTE_MAX_SLIPPAGE_BPS ?? 1000); // hard rail (10%) — not even consent can exceed + +export interface SlippageOpts { + // The agent's EXPLICIT, conscious acceptance of higher slippage for this call (in bps). + // Raises the cap above MAX_SLIPPAGE_BPS, but never above ABSOLUTE_MAX_SLIPPAGE_BPS. + acceptSlippageBps?: number; +} + +// Slippage protection for swaps. Same-asset bridges (priceImpact 0) skip this entirely. +// Guards the canonical failure modes: no/zero min-out, unbounded slippage, missing floor. +// An agent may opt into "unusual" slippage via opts.acceptSlippageBps, bounded by the hard rail. +export function checkSwapSlippage( + q: Pick, + opts: SlippageOpts = {}, +): string[] { + const f: string[] = []; + if (q.kind !== "swap") return f; // bridges are 1:1, no slippage logic + + // Effective cap: default, optionally raised by explicit agent consent, never past the hard rail. + const consented = opts.acceptSlippageBps != null && opts.acceptSlippageBps > MAX_SLIPPAGE_BPS; + const cap = consented ? Math.min(opts.acceptSlippageBps!, ABSOLUTE_MAX_SLIPPAGE_BPS) : MAX_SLIPPAGE_BPS; + + if (!(q.slippageBps > 0)) f.push("swap requires a non-zero slippage tolerance (slippageBps)"); + if (q.slippageBps > ABSOLUTE_MAX_SLIPPAGE_BPS) { + f.push(`slippage ${q.slippageBps}bps exceeds the absolute ceiling ${ABSOLUTE_MAX_SLIPPAGE_BPS}bps (raise ABSOLUTE_MAX_SLIPPAGE_BPS to allow)`); + } else if (q.slippageBps > cap) { + f.push(`slippage ${q.slippageBps}bps exceeds max ${MAX_SLIPPAGE_BPS}bps — pass acceptSlippageBps >= ${q.slippageBps} to consciously accept (up to ${ABSOLUTE_MAX_SLIPPAGE_BPS}bps)`); + } + if (!(q.minAmountOut > 0)) f.push("swap requires a positive minAmountOut floor (never accept 0-out)"); + if (q.minAmountOut > q.amountOut) f.push("minAmountOut above quoted amountOut (inverted floor)"); + return f; +} + +// Human-readable slippage summary for output (so the tolerance/floor and any override +// are visible, not buried as raw bps). aboveDefaultCap => an override was needed/used. +export function describeSwapSlippage(q: Pick) { + return { + isSwap: q.kind === "swap", + bps: q.slippageBps, + tolerancePct: (q.slippageBps / 100).toFixed(2) + "%", + minAmountOut: q.minAmountOut, + aboveDefaultCap: q.slippageBps > MAX_SLIPPAGE_BPS, + defaultCapPct: (MAX_SLIPPAGE_BPS / 100).toFixed(0) + "%", + }; +} + +export async function preflight( + srcToken: string, + amountIn: number, + chain: string, + destToken: string, + quote?: Pick, + opts: SlippageOpts = {}, +): Promise { + const failures: string[] = []; + const allow = (process.env.DEST_ALLOWLIST ?? "").split(",").map((s) => s.trim()); + const maxTx = Number(process.env.MAX_BRIDGE_USDC_PER_TX ?? 100); + + if (!allow.includes(chain)) failures.push(`destination '${chain}' not in allowlist`); + if (srcToken.toLowerCase() === "usdc" && amountIn > maxTx) failures.push(`amount ${amountIn} exceeds per-tx cap ${maxTx}`); + + // Swap slippage protection (only when a chosen quote is supplied and it's a swap). + // opts.acceptSlippageBps lets the agent consciously opt into unusual slippage (bounded). + if (quote) failures.push(...checkSwapSlippage(quote, opts)); + + // Source: Solana RPC health (lowest slot-lag healthy endpoint, else fail). + let slotLag = -1, usedRpc = ""; + try { const s = await getHealthySolana(); slotLag = s.slotLag; usedRpc = s.endpoint; } + catch (e) { failures.push(`Solana RPC: ${(e as Error).message}`); } + + // Destination: EVM RPC health (auto-failover; fail if all stale/unreachable). + try { await getHealthyEvmRpc(chain); } + catch (e) { failures.push(`${chain} RPC: ${(e as Error).message}`); } + + // TODO(devin): daily-cap accounting; post-execute confirmation on both chains. + return { ok: failures.length === 0, failures, rpcSlotLag: slotLag, usedRpc }; +} + +// Re-quote IMMEDIATELY before execution and re-check the floor. Prices move between +// quote-time and signing; for swaps, abort if the fresh route no longer clears the +// original minAmountOut. Returns the fresh route to execute against. +export async function requoteGuard( + srcToken: string, + amountIn: number, + chain: string, + destToken: string, + chosen: ProviderQuote, +): Promise<{ ok: boolean; reason?: string; fresh?: ProviderQuote }> { + const { best } = await aggregate(srcToken, amountIn, chain as any, destToken); + if (!best) return { ok: false, reason: "re-quote returned no eligible route" }; + if (chosen.kind === "swap" && best.amountOut < chosen.minAmountOut) { + return { ok: false, reason: `price moved beyond tolerance: fresh amountOut ${best.amountOut} < minAmountOut ${chosen.minAmountOut}` }; + } + return { ok: true, fresh: best }; +} diff --git a/solana-x402-bridge-skill/scripts/demo-roundtrip.ts b/solana-x402-bridge-skill/scripts/demo-roundtrip.ts new file mode 100644 index 0000000..9ac13b9 --- /dev/null +++ b/solana-x402-bridge-skill/scripts/demo-roundtrip.ts @@ -0,0 +1,47 @@ +// Read-only recap of a REAL cross-chain round trip (Allbridge, native USDC). +// Shows both on-chain tx hashes + live balances. Moves no funds. Used for the demo video. +import "./env.js"; + +const LEG1 = "5PRGrU7qC1s6LmvLYmQ8iU1ZGyU4qkvynxGVoK1FCy3kW36SpBh8M8yaiTqH97ZUmbs2o4kr33DFeCSYEH62J3Qk"; +const LEG2 = "0x5cb09254977140845386432ae6b89416f3883c35a9b3254a36a2a9979642ae77"; +const SOL = "7yESaEnYPnvSpRFK8xFb9TzdbXh1ppU9sgfmckwKAqLo"; +const EVM = "0x3CcCd869AF2d489e2EEb97Ea5299D0F864e7c0A8"; +const USDC_MINT = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"; +const POL_USDC = "0x3c499c542cEF5E3811e1192ce70d8cc03d5c3359"; + +async function rpc(url: string, body: unknown) { + const r = await fetch(url, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(body) }); + return r.json() as any; +} +async function solUsdc(): Promise { + const d = await rpc(process.env.SOLANA_RPC_URL!, { jsonrpc: "2.0", id: 1, method: "getTokenAccountsByOwner", params: [SOL, { mint: USDC_MINT }, { encoding: "jsonParsed" }] }); + const a = d.result?.value ?? []; + return a.length ? String(a[0].account.data.parsed.info.tokenAmount.uiAmount) : "0"; +} +async function polUsdc(): Promise { + const data = "0x70a08231000000000000000000000000" + EVM.slice(2); + const d = await rpc(process.env.POLYGON_RPC_URL!, { jsonrpc: "2.0", id: 1, method: "eth_call", params: [{ to: POL_USDC, data }, "latest"] }); + return d.result && d.result !== "0x" ? String(parseInt(d.result, 16) / 1e6) : "0"; +} + +(async () => { + console.log("┌──────────────────────────────────────────────────────────────────┐"); + console.log("│ solana-x402-bridge — REAL cross-chain round trip (Allbridge) │"); + console.log("│ best-rate aggregation · safety preflight · slippage-protected │"); + console.log("└──────────────────────────────────────────────────────────────────┘"); + console.log(""); + console.log("LEG 1 Solana ──▶ Polygon 0.5 USDC (native)"); + console.log(" tx " + LEG1); + console.log(" → https://explorer.solana.com/tx/" + LEG1); + console.log(""); + console.log("LEG 2 Polygon ──▶ Solana 0.5 USDC (return)"); + console.log(" tx " + LEG2); + console.log(" → https://polygonscan.com/tx/" + LEG2); + console.log(""); + console.log("Live on-chain balances:"); + const [s, p] = await Promise.all([solUsdc(), polUsdc()]); + console.log(" Solana USDC " + s + " (" + SOL + ")"); + console.log(" Polygon USDC " + p + " (" + EVM + ")"); + console.log(""); + console.log("Initiated from a Solana wallet. One skill. Cross-chain. Non-custodial."); +})(); diff --git a/solana-x402-bridge-skill/scripts/env.ts b/solana-x402-bridge-skill/scripts/env.ts new file mode 100644 index 0000000..4fd749a --- /dev/null +++ b/solana-x402-bridge-skill/scripts/env.ts @@ -0,0 +1,16 @@ +// Minimal zero-dependency .env loader. Import this first in any entrypoint that +// reads process.env, so the documented `npx tsx scripts/.ts` commands work +// without dotenv. Real env vars already in the environment take precedence. +import { readFileSync } from "fs"; + +try { + const txt = readFileSync(new URL("../.env", import.meta.url), "utf8"); + for (const line of txt.split("\n")) { + const m = line.match(/^\s*([\w.-]+)\s*=\s*(.*?)\s*$/); + if (m && !(m[1] in process.env)) { + process.env[m[1]] = m[2].replace(/^["']|["']$/g, ""); + } + } +} catch { + /* no .env present — rely on the ambient environment */ +} diff --git a/solana-x402-bridge-skill/scripts/evm-targets.ts b/solana-x402-bridge-skill/scripts/evm-targets.ts new file mode 100644 index 0000000..972877c --- /dev/null +++ b/solana-x402-bridge-skill/scripts/evm-targets.ts @@ -0,0 +1,9 @@ +// Registry of supported EVM destinations. Print with: tsx scripts/evm-targets.ts +export const EVM_TARGETS = { + polygon: { chainId: 137, finalitySeconds: 45, tokens: { USDC_E: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174" }, note: "Polymarket uses USDC.e" }, + gnosis: { chainId: 100, finalitySeconds: 90, tokens: { USDC: "0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83" }, note: "live via gnosis-card-x402" }, + base: { chainId: 8453, finalitySeconds: 30, tokens: { USDC: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" } }, + arbitrum: { chainId: 42161, finalitySeconds: 30, tokens: { USDC: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831" } }, +} as const; + +if (import.meta.url === `file://${process.argv[1]}`) console.log(JSON.stringify(EVM_TARGETS, null, 2)); diff --git a/solana-x402-bridge-skill/scripts/globals.d.ts b/solana-x402-bridge-skill/scripts/globals.d.ts new file mode 100644 index 0000000..59f815e --- /dev/null +++ b/solana-x402-bridge-skill/scripts/globals.d.ts @@ -0,0 +1,2 @@ +// bs58@4 ships no type declarations; it is used only via dynamic import for key decoding. +declare module "bs58"; diff --git a/solana-x402-bridge-skill/scripts/onramp.ts b/solana-x402-bridge-skill/scripts/onramp.ts new file mode 100644 index 0000000..5547402 --- /dev/null +++ b/solana-x402-bridge-skill/scripts/onramp.ts @@ -0,0 +1,132 @@ +// fiat-onramp module — Onramper integration (the fiat aggregator analog of the +// bridge aggregator). Returns the best ranked quote across 20+ providers, fee +// always disclosed. Quote-first; no secrets in code (key via ONRAMPER_API_KEY). +// +// usage: +// tsx scripts/onramp.ts quote # fiat -> USDC (buy) +// tsx scripts/onramp.ts offramp [fromChain] # USDC -> fiat (sell) +// +// Examples: +// tsx scripts/onramp.ts quote USD 20 solana # USD -> USDC on Solana +// tsx scripts/onramp.ts quote EUR 50 usdce_polygon # EUR -> USDC.e on Polygon (Polymarket leg) +// tsx scripts/onramp.ts offramp 20 USD solana # cash out 20 USDC on Solana -> USD +import "./env.js"; + +const BASE = process.env.ONRAMPER_API_BASE ?? "https://api.onramper.com"; +const KEY = process.env.ONRAMPER_API_KEY ?? ""; + +// Map a chain name to the Onramper USDC asset id. A full id ("usdc_solana", +// "usdce_polygon", ...) passed directly is used as-is. +const CHAIN_ALIASES: Record = { + solana: "usdc_solana", + polygon: "usdc_polygon", + "polygon.e": "usdce_polygon", // USDC.e on Polygon — what Polymarket uses + ethereum: "usdc_ethereum", + base: "usdc_base", + arbitrum: "usdc_arbitrum", +}; + +function cryptoId(chainOrId: string): string { + if (chainOrId.includes("_")) return chainOrId.toLowerCase(); // already a full asset id + const id = CHAIN_ALIASES[chainOrId.toLowerCase()]; + if (!id) throw new Error(`onramp: unknown chain '${chainOrId}' (use solana|polygon|base|arbitrum|ethereum or a full asset id like usdce_polygon)`); + return id; +} + +interface OnramperQuote { + ramp: string; + payout: number | null; + rate: number | null; + networkFee: number | null; + transactionFee: number | null; + paymentMethod: string; + recommendations?: string[]; +} + +interface RankedQuote { + provider: string; + payout: number; // amount received (crypto for buy, fiat for sell) + rate: number; + networkFee: number; + transactionFee: number; + totalFeeOnTop: number; // networkFee + transactionFee, disclosed + feePct: number; // total fee as % of input amount + paymentMethod: string; + recommendations: string[]; +} + +async function fetchQuotes(source: string, dest: string, amount: number): Promise { + if (!KEY) throw new Error("ONRAMPER_API_KEY not set (put it in .env)"); + const url = `${BASE}/quotes/${source.toLowerCase()}/${dest.toLowerCase()}?amount=${amount}`; + const res = await fetch(url, { headers: { Authorization: KEY } }); + const json: any = await res.json(); + if (!res.ok || json?.message?.length === 0 || json?.error) { + throw new Error(`onramper quote failed: ${json.message ?? json.error ?? res.status}`); + } + return Array.isArray(json) ? json : (json.quotes ?? []); +} + +// Normalize + rank: drop providers that couldn't quote (null payout), best payout first. +function rank(quotes: OnramperQuote[], amount: number): RankedQuote[] { + return quotes + .filter((q) => typeof q.payout === "number" && (q.payout as number) > 0) + .map((q) => { + const networkFee = Number(q.networkFee ?? 0); + const transactionFee = Number(q.transactionFee ?? 0); + const totalFeeOnTop = networkFee + transactionFee; + return { + provider: q.ramp, + payout: q.payout as number, + rate: Number(q.rate ?? 0), + networkFee, + transactionFee, + totalFeeOnTop, + feePct: amount > 0 ? (totalFeeOnTop / amount) * 100 : 0, + paymentMethod: q.paymentMethod, + recommendations: q.recommendations ?? [], + }; + }) + .sort((a, b) => b.payout - a.payout); +} + +export async function onrampQuote(fiat: string, amount: number, deliverChain: string) { + const dest = cryptoId(deliverChain); + const ranked = rank(await fetchQuotes(fiat, dest, amount), amount); + return { best: ranked[0] ?? null, ranked, direction: "onramp" as const, source: fiat, dest, amount }; +} + +export async function offrampQuote(amountUSDC: number, fiat: string, fromChain = "solana") { + const source = cryptoId(fromChain); + const ranked = rank(await fetchQuotes(source, fiat, amountUSDC), amountUSDC); + return { best: ranked[0] ?? null, ranked, direction: "offramp" as const, source, dest: fiat, amount: amountUSDC }; +} + +type QuoteReport = { best: RankedQuote | null; ranked: RankedQuote[]; source: string; dest: string; amount: number }; + +function print(label: string, unit: string, r: QuoteReport) { + if (!r.best) { console.log(`No ${label} quote available for ${r.source} -> ${r.dest}.`); return; } + const b = r.best; + console.log(`BEST ${label}: ${r.amount} ${r.source.toUpperCase()} -> ${r.dest}`); + console.log(JSON.stringify({ + provider: b.provider, + payout: `${b.payout} ${unit}`, + fee: `${b.totalFeeOnTop.toFixed(2)} (${b.feePct.toFixed(2)}%) [network ${b.networkFee} + txn ${b.transactionFee}]`, + paymentMethod: b.paymentMethod, + labels: b.recommendations, + }, null, 2)); + console.log("\nCOMPARISON (ranked by payout, fee disclosed):"); + for (const q of r.ranked) + console.log(` ${q.provider.padEnd(12)} payout=${q.payout} ${unit} fee=${q.totalFeeOnTop.toFixed(2)} (${q.feePct.toFixed(2)}%) via ${q.paymentMethod}`); +} + +// CLI dispatch only when run directly (not when imported by other modules) +if (import.meta.url === `file://${process.argv[1]}`) { + const [cmd, ...rest] = process.argv.slice(2); + if (cmd === "quote") { + onrampQuote(rest[0], Number(rest[1]), rest[2]).then((r) => print("(onramp)", "USDC", r)).catch((e) => { console.error(String(e.message ?? e)); process.exit(1); }); + } else if (cmd === "offramp") { + offrampQuote(Number(rest[0]), rest[1], rest[2]).then((r) => print("(offramp)", rest[1].toUpperCase(), r)).catch((e) => { console.error(String(e.message ?? e)); process.exit(1); }); + } else { + console.log("usage: quote | offramp [fromChain]"); + } +} diff --git a/solana-x402-bridge-skill/scripts/polymarket.ts b/solana-x402-bridge-skill/scripts/polymarket.ts new file mode 100644 index 0000000..5ebe52e --- /dev/null +++ b/solana-x402-bridge-skill/scripts/polymarket.ts @@ -0,0 +1,44 @@ +// usage: +// tsx scripts/polymarket.ts read [keyword] # live markets + odds (read-only) +// tsx scripts/polymarket.ts bet # roadmap +// Polymarket runs on Polygon (USDC.e). `read` is live via the public Gamma API; `bet` +// (CLOB order placement) is on the roadmap — bridge USDC to Polygon first via this skill. +import "./env.js"; + +const GAMMA = process.env.POLYMARKET_GAMMA_URL ?? "https://gamma-api.polymarket.com"; + +async function read(keyword?: string) { + const url = `${GAMMA}/markets?active=true&closed=false&order=volumeNum&ascending=false&limit=120`; + const res = await fetch(url); + const all: any[] = await res.json(); + const norm = (s: string) => (s ?? "").toLowerCase().replace(/[^a-z0-9]/g, ""); + const kw = norm(keyword ?? ""); + const matched = (kw ? all.filter((m) => norm(m.question).includes(kw)) : all).slice(0, 8); + if (!matched.length) { console.log(`No active markets${keyword ? ` matching "${keyword}"` : ""}.`); return; } + + console.log(`Polymarket — top ${matched.length} active markets${keyword ? ` matching "${keyword}"` : ""} (by volume):`); + for (const m of matched) { + let outs: string[] = [], prices: string[] = []; + try { outs = JSON.parse(m.outcomes ?? "[]"); prices = JSON.parse(m.outcomePrices ?? "[]"); } catch { /* skip parse */ } + const odds = outs.map((o, i) => `${o} ${(Number(prices[i]) * 100).toFixed(1)}%`).join(" | "); + console.log(`\n• ${m.question}`); + if (odds) console.log(` ${odds}`); + console.log(` vol $${Math.round(Number(m.volumeNum || 0)).toLocaleString()} liq $${Math.round(Number(m.liquidityNum || 0)).toLocaleString()} ends ${(m.endDate ?? "").slice(0, 10)}`); + console.log(` conditionId ${m.conditionId}`); + } +} + +async function bet(_marketId: string, _outcome: string, _amount: number) { + throw new Error( + "polymarket-bet is on the ROADMAP — placing a CLOB order (USDC.e on Polygon) needs order signing. " + + "Use this skill to bridge USDC onto Polygon first (npm run execute USDC polygon USDC), then place the bet. " + + "Reading markets is live: `npm run polymarket read `.", + ); +} + +if (import.meta.url === `file://${process.argv[1]}`) { + const [cmd, ...rest] = process.argv.slice(2); + if (cmd === "read") read(rest[0]).catch((e) => { console.error(String(e.message ?? e)); process.exit(1); }); + else if (cmd === "bet") bet(rest[0], rest[1], Number(rest[2])).catch((e) => { console.error(String(e.message ?? e)); process.exit(1); }); + else console.log("usage: read [keyword] | bet "); +} diff --git a/solana-x402-bridge-skill/scripts/providers.ts b/solana-x402-bridge-skill/scripts/providers.ts new file mode 100644 index 0000000..fd3336e --- /dev/null +++ b/solana-x402-bridge-skill/scripts/providers.ts @@ -0,0 +1,48 @@ +// Bridge/swap provider adapters — 5 Solana -> EVM providers. Spec: PROVIDERS.md. +// Same-asset bridge (USDC->USDC) AND cross-chain swap (SOL->ETH) supported where the +// provider allows. Eligibility is decided per-pair by supportsPair(). +import type { BridgeQuote, BridgeResult, EvmChain } from "./types.js"; +import { cctp } from "./adapters/cctp.js"; +import { mayan } from "./adapters/mayan.js"; +import { debridge } from "./adapters/debridge.js"; +import { allbridge } from "./adapters/allbridge.js"; + +export interface ProviderQuote extends BridgeQuote { + provider: string; + reliabilityScore: number; // 0..1 — aggregator filters below 0.5 +} + +export interface BridgeProvider { + name: string; + // supportsPair: can this provider move srcToken on Solana to destToken on destChain? + supportsPair(srcToken: string, chain: EvmChain, destToken: string): boolean; + quote(srcToken: string, amountIn: number, chain: EvmChain, destToken: string): Promise; + execute(srcToken: string, amountIn: number, chain: EvmChain, destToken: string): Promise; + status(id: string): Promise; +} + +export const SOLANA_DLN_CHAIN_ID = 7565164; +const isStable = (t: string) => ["usdc", "usdt"].includes(t.toLowerCase()); +const sameAsset = (a: string, b: string) => a.toLowerCase() === b.toLowerCase(); + +// 1. Circle CCTP — USDC->USDC only, native 1:1, no slippage. DEFAULT BENCHMARK. → adapters/cctp.ts +// 2. Mayan — ANY token -> ANY token (cross-chain swap). Best for SOL->ETH. → adapters/mayan.ts +// 3. deBridge DLN — ANY token -> ANY token (intent market). Supports SOL->ETH. → adapters/debridge.ts +// (cctp, mayan, debridge are implemented in scripts/adapters/ and imported above.) + +// 4. Wormhole/Portal — same-asset bridge + CCTP route. SOL->ETH only via added swap legs (treat as limited). +const wormhole: BridgeProvider = { + name: "wormhole", + supportsPair: (s, _c, d) => sameAsset(s, d) || (s.toLowerCase() === "usdc" && d.toLowerCase() === "usdc"), + async quote() { throw new Error("TODO(devin): Wormhole SDK route; higher eta for VAA. PROVIDERS.md #4"); }, + async execute() { throw new Error("TODO(devin): Wormhole transfer + VAA + redeem"); }, + async status() { throw new Error("TODO(devin): Wormhole VAA status"); }, +}; + +// 5. Allbridge Core — stablecoin pools only (USDC/USDT). No SOL->ETH. → adapters/allbridge.ts + +// Aggregator pool — exactly 5 external providers. +// SOL->ETH eligible set resolves to: mayan, debridge (cctp/allbridge/wormhole filtered out). +export const PROVIDERS: Record = { + cctp, mayan, debridge, wormhole, allbridge, +}; diff --git a/solana-x402-bridge-skill/scripts/rpc-health.ts b/solana-x402-bridge-skill/scripts/rpc-health.ts new file mode 100644 index 0000000..fb74040 --- /dev/null +++ b/solana-x402-bridge-skill/scripts/rpc-health.ts @@ -0,0 +1,129 @@ +// Cross-chain RPC health switcher. Detects lagging/failing endpoints and fails over +// BEFORE execution — on both the Solana source and the EVM destination. +// Never act on a stale/unhealthy RPC. +import "./env.js"; +import { Connection } from "@solana/web3.js"; + +const TIMEOUT_MS = Number(process.env.RPC_PROBE_TIMEOUT_MS ?? 2500); + +async function withTimeout(p: Promise): Promise { + return Promise.race([ + p, + new Promise((_, rej) => setTimeout(() => rej(new Error("rpc timeout")), TIMEOUT_MS)), + ]); +} + +// ---------- Solana ---------- +export async function getHealthySolana() { + const endpoints = [process.env.SOLANA_RPC_URL!, ...split(process.env.SOLANA_FALLBACK_RPCS)]; + const maxLag = Number(process.env.RPC_MAX_SLOT_LAG ?? 150); + + const probes = await Promise.all(endpoints.map(async (url) => { + const t0 = Date.now(); + try { + const slot = await withTimeout(new Connection(url, "confirmed").getSlot()); + return { url, slot, latency: Date.now() - t0, ok: true as const }; + } catch { return { url, slot: -1, latency: Infinity, ok: false as const }; } + })); + + const healthy = probes.filter((p) => p.ok); + if (!healthy.length) throw new Error("No healthy Solana RPC endpoint"); + const maxSlot = Math.max(...healthy.map((p) => p.slot)); + const eligible = healthy + .map((p) => ({ ...p, lag: maxSlot - p.slot })) + .filter((p) => p.lag <= maxLag) + .sort((a, b) => a.lag - b.lag || a.latency - b.latency); + + if (!eligible.length) throw new Error(`All Solana RPCs stale (> ${maxLag} slots behind)`); + const chosen = selectPreferringPrimary(eligible, endpoints[0]); + return { connection: new Connection(chosen.url, "confirmed"), slotLag: chosen.lag, endpoint: chosen.url }; +} + +// Back-compat alias used by bridge-safety. +export const getHealthyConnection = getHealthySolana; + +// ---------- EVM ---------- +// Reliable keyless public RPC defaults so the skill works out of the box. Any user-configured +// _RPC_URL / _FALLBACK_RPCS is always preferred over these. +const DEFAULT_EVM_RPCS: Record = { + ethereum: ["https://ethereum-rpc.publicnode.com"], + polygon: ["https://polygon-bor-rpc.publicnode.com"], + base: ["https://base-rpc.publicnode.com"], + arbitrum: ["https://arbitrum-one-rpc.publicnode.com"], + optimism: ["https://optimism-rpc.publicnode.com"], + gnosis: ["https://gnosis-rpc.publicnode.com"], +}; + +// Per-chain fallback RPCs via env, e.g. POLYGON_FALLBACK_RPCS, ETHEREUM_FALLBACK_RPCS. +export async function getHealthyEvmRpc(chain: string) { + const primary = process.env[`${chain.toUpperCase()}_RPC_URL`]; + const fallbacks = split(process.env[`${chain.toUpperCase()}_FALLBACK_RPCS`]); + const endpoints = [primary, ...fallbacks, ...(DEFAULT_EVM_RPCS[chain.toLowerCase()] ?? [])].filter(Boolean) as string[]; + if (!endpoints.length) throw new Error(`No RPC configured for ${chain}`); + + const probes = await Promise.all(endpoints.map(async (url) => { + const t0 = Date.now(); + try { + const block = await withTimeout(evmBlockNumber(url)); + return { url, block, latency: Date.now() - t0, ok: true as const }; + } catch { return { url, block: -1, latency: Infinity, ok: false as const }; } + })); + + const healthy = probes.filter((p) => p.ok); + if (!healthy.length) throw new Error(`No healthy ${chain} RPC endpoint`); + const maxBlock = Math.max(...healthy.map((p) => p.block)); + const maxLag = Number(process.env.EVM_MAX_BLOCK_LAG ?? 10); + const eligible = healthy + .map((p) => ({ ...p, lag: maxBlock - p.block })) + .filter((p) => p.lag <= maxLag) + .sort((a, b) => a.lag - b.lag || a.latency - b.latency); + + if (!eligible.length) throw new Error(`All ${chain} RPCs stale (> ${maxLag} blocks behind)`); + const chosen = selectPreferringPrimary(eligible, endpoints[0]); + return { endpoint: chosen.url, blockLag: chosen.lag, latency: chosen.latency }; +} + +// Prefer the configured primary endpoint when it's healthy AND within lag tolerance — so a +// reliable (paid) RPC isn't bypassed just because a public node pinged a few ms faster. Only +// fail over to the best-ranked fallback when the primary is unhealthy/stale. Set +// RPC_PREFER_PRIMARY=false for pure lowest-lag/latency selection across all endpoints. +function selectPreferringPrimary(eligible: T[], primaryUrl: string): T { + const preferPrimary = (process.env.RPC_PREFER_PRIMARY ?? "true") !== "false"; + return (preferPrimary && eligible.find((e) => e.url === primaryUrl)) || eligible[0]; +} + +async function evmBlockNumber(url: string): Promise { + const res = await fetch(url, { + method: "POST", + headers: { "content-type": "application/json" }, + body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "eth_blockNumber", params: [] }), + }); + const json = await res.json(); + return parseInt(json.result, 16); +} + +function split(v?: string) { return (v ?? "").split(",").map((s) => s.trim()).filter(Boolean); } + +// ---------- CLI ---------- +// usage: tsx scripts/rpc-health.ts [chain] (default: solana) +// tsx scripts/rpc-health.ts solana +// tsx scripts/rpc-health.ts polygon +// Prints the selected healthy endpoint + lag. API keys are redacted from output. +if (import.meta.url === `file://${process.argv[1]}`) { + const redact = (u: string) => u.replace(/(api-key=)[^&\s]+/i, "$1***").replace(/(\/v2\/)[^/\s]+/i, "$1***"); + const chain = (process.argv[2] ?? "solana").toLowerCase(); + (async () => { + try { + if (chain === "solana" || chain === "sol") { + const s = await getHealthySolana(); + console.log(`[solana] OK -> ${redact(s.endpoint)} slotLag=${s.slotLag}`); + } else { + const e = await getHealthyEvmRpc(chain); + console.log(`[${chain}] OK -> ${redact(e.endpoint)} blockLag=${e.blockLag} latency=${e.latency}ms`); + } + } catch (err) { + console.error(`[${chain}] UNHEALTHY: ${(err as Error).message}`); + process.exit(1); + } + })(); +} diff --git a/solana-x402-bridge-skill/scripts/test.ts b/solana-x402-bridge-skill/scripts/test.ts new file mode 100644 index 0000000..83ccc64 --- /dev/null +++ b/solana-x402-bridge-skill/scripts/test.ts @@ -0,0 +1,63 @@ +// Deterministic unit suite for the bridge skill's pure logic. No network, no funds. +// Run: npm test (generates thousands of cases across the slippage rails + target registry) +// NOTE: does not load .env — relies on the documented defaults MAX_SLIPPAGE_BPS=300, ABS=1000. +import { checkSwapSlippage, describeSwapSlippage } from "./bridge-safety.js"; +import { EVM_TARGETS } from "./evm-targets.js"; + +const MAX = 300, ABS = 1000; +let pass = 0, fail = 0; +const fails: string[] = []; +const ok = (cond: boolean, name: string) => { if (cond) pass++; else { fail++; if (fails.length < 25) fails.push(name); } }; + +// 1) Slippage rail: every bps from 0..1200 lands in the right enforcement band (no override). +for (let bps = 0; bps <= 1200; bps++) { + const f = checkSwapSlippage({ kind: "swap", slippageBps: bps, minAmountOut: 99, amountOut: 100 }); + const cap = f.some((x) => x.includes("exceeds max")); + const abs = f.some((x) => x.includes("absolute ceiling")); + const zero = f.some((x) => x.includes("non-zero")); + if (bps <= 0) ok(zero, `bps ${bps} -> non-zero failure`); + else if (bps > ABS) ok(abs && !cap, `bps ${bps} -> absolute ceiling`); + else if (bps > MAX) ok(cap && !abs && !zero, `bps ${bps} -> exceeds max`); + else ok(!cap && !abs && !zero, `bps ${bps} -> within default cap`); +} + +// 2) Explicit consent raises the cap up to the hard rail. +for (let bps = MAX + 1; bps <= ABS; bps++) { + const f = checkSwapSlippage({ kind: "swap", slippageBps: bps, minAmountOut: 99, amountOut: 100 }, { acceptSlippageBps: bps }); + ok(!f.some((x) => x.includes("exceeds max")), `consent ${bps} -> allowed`); +} + +// 3) Consent can NEVER exceed the absolute ceiling. +for (let bps = ABS + 1; bps <= ABS + 200; bps++) { + const f = checkSwapSlippage({ kind: "swap", slippageBps: bps, minAmountOut: 99, amountOut: 100 }, { acceptSlippageBps: bps }); + ok(f.some((x) => x.includes("absolute ceiling")), `consent ${bps} -> still capped`); +} + +// 4) Same-asset bridges skip slippage logic entirely, at every bps. +for (let bps = 0; bps <= 1200; bps++) { + ok(checkSwapSlippage({ kind: "bridge", slippageBps: bps, minAmountOut: 0, amountOut: 100 }).length === 0, `bridge skips slippage @ ${bps}`); +} + +// 5) Floor invariants. +ok(checkSwapSlippage({ kind: "swap", slippageBps: 50, minAmountOut: 0, amountOut: 100 }).some((x) => x.includes("positive minAmountOut")), "zero minOut rejected"); +ok(checkSwapSlippage({ kind: "swap", slippageBps: 50, minAmountOut: 101, amountOut: 100 }).some((x) => x.includes("inverted floor")), "inverted floor rejected"); +ok(checkSwapSlippage({ kind: "swap", slippageBps: 50, minAmountOut: 99, amountOut: 100 }).length === 0, "valid swap clean"); + +// 6) describeSwapSlippage formatting. +for (let bps = 0; bps <= 1000; bps += 5) { + const d = describeSwapSlippage({ kind: "swap", slippageBps: bps, minAmountOut: 1 }); + ok(d.tolerancePct === (bps / 100).toFixed(2) + "%", `describe ${bps} pct`); + ok(d.aboveDefaultCap === bps > MAX || d.aboveDefaultCap === (bps > MAX), `describe ${bps} aboveCap`); +} +ok(describeSwapSlippage({ kind: "bridge", slippageBps: 0, minAmountOut: 1 }).isSwap === false, "describe bridge not swap"); + +// 7) EVM target registry integrity. +const addr = /^0x[0-9a-fA-F]{40}$/; +for (const [chain, t] of Object.entries(EVM_TARGETS)) { + ok((t as any).chainId > 0, `${chain} chainId > 0`); + ok((t as any).finalitySeconds > 0, `${chain} finalitySeconds > 0`); + for (const [sym, a] of Object.entries((t as any).tokens)) ok(addr.test(a as string), `${chain}.${sym} valid address`); +} + +console.log(`\n${pass} passed, ${fail} failed (total ${pass + fail})`); +if (fail) { console.log("FAILURES:\n " + fails.join("\n ")); process.exit(1); } diff --git a/solana-x402-bridge-skill/scripts/types.ts b/solana-x402-bridge-skill/scripts/types.ts new file mode 100644 index 0000000..c83bc16 --- /dev/null +++ b/solana-x402-bridge-skill/scripts/types.ts @@ -0,0 +1,43 @@ +// Shared contracts for solana-x402-bridge. Generalized to ANY token (bridge or cross-chain swap). +// Devin: implement against these. Keep the skill client thin — no secrets here. + +export type EvmChain = "polygon" | "gnosis" | "base" | "arbitrum" | "ethereum"; + +// A bridge is a same-asset transfer (USDC->USDC). A swap is cross-chain with a different +// destination token (SOL->ETH) and carries slippage/price impact. +export type TransferKind = "bridge" | "swap"; + +export interface BridgeQuote { + kind: TransferKind; + route: string; + srcChain: "solana"; + srcToken: string; // e.g. "USDC", "SOL" + destChain: EvmChain; + destToken: string; // e.g. "USDC", "ETH" + amountIn: number; // in srcToken units + amountOut: number; // in destToken units (net of all fees + swap impact) + bridgeFeeUSDC: number; + bridgeFeeBps: number; + networkFeesUSDC: number; + priceImpactBps: number; // 0 for same-asset bridges; >0 for swaps + minAmountOut: number; // amountOut after applying slippage tolerance + slippageBps: number; + etaSeconds: number; + feeRecipient: string; + relayer: string; +} + +export interface SafetyResult { + ok: boolean; + failures: string[]; + rpcSlotLag: number; + usedRpc: string; +} + +export interface BridgeResult { + sourceTx: string; + destTx: string; + statusId: string; + sourceExplorer: string; + destExplorer: string; +} diff --git a/solana-x402-bridge-skill/skill/SKILL.md b/solana-x402-bridge-skill/skill/SKILL.md new file mode 100644 index 0000000..2b57096 --- /dev/null +++ b/solana-x402-bridge-skill/skill/SKILL.md @@ -0,0 +1,58 @@ +--- +name: solana-x402-bridge +description: Best-rate cross-chain bridge aggregator for Solana agents. Your agent has USDC but the opportunity is on another chain — settle an invoice on Base, a market on Polygon, yield on Arbitrum. This skill shops every major bridge (Circle CCTP, Mayan, deBridge, Allbridge) in parallel, returns the best net-of-fee route plus the full ranked breakdown, guards the fill, and executes it non-custodially — from the same Solana wallet it started with. Use for "bridge USDC to ", "best cross-chain rate", "move funds to Polygon/Base/Arbitrum/Ethereum", "swap SOL to ETH cross-chain", "cash out to fiat". +user-invocable: true +--- + +# Solana x402 Cross-Chain Bridge Skill + +Move value off Solana to any EVM chain at the best available rate — and actually execute it, +safely, in one call. Solana is always the front door; EVM chains are reached through the bridge. + +## What this skill is for + +Use this skill when the user (or agent) wants to: + +### Quote & aggregate +- get the **best net-of-fee route** to move USDC from Solana to an EVM chain → [quote.md](./quote.md), [aggregation.md](./aggregation.md) +- compare providers (Circle CCTP, Mayan, deBridge, Allbridge) with a ranked breakdown +- know **whether paying for aggregation is worth it** vs free CCTP (honest verdict) +- **cross-chain swaps** (e.g. SOL → ETH, USDC → ETH) → [aggregation.md](./aggregation.md) + +### Execute safely +- run a bridge with guardrails and explicit confirmation → [execute.md](./execute.md) +- the safety preflight: allowlist, per-tx caps, **swap-slippage protection**, re-quote → [safety.md](./safety.md) +- never read from a stale/lagging RPC; fail over automatically → [rpc-health.md](./rpc-health.md) + +### Reach destinations +- supported chains/tokens and how to add more → [targets.md](./targets.md) +- the provider adapters and how to add a new one → [providers.md](./providers.md) +- fiat on/off-ramp (Onramper, sandbox today) → [fiat.md](./fiat.md) +- read live prediction markets (Polymarket) → [polymarket.md](./polymarket.md) + +## How to run + +```bash +npm install +npm run quote USDC 100 ethereum USDC # best route + ranked comparison + free-vs-paid verdict +npm run quote SOL 1 polygon USDC # cross-chain swap (any-token) +npm run health solana # RPC health + failover +npm run execute USDC 5 polygon USDC # preview; add --confirm to broadcast (non-custodial) +``` + +Implementation lives in [`scripts/`](../scripts) (TypeScript, run via `tsx`). See [testing.md](./testing.md). + +## Safety model (read this) + +- **Non-custodial.** Keys live only in your local `.env`; nothing signs without `--confirm`. +- Every money movement passes the preflight in [safety.md](./safety.md): destination allowlist, + per-tx cap, enforced swap-slippage protection (with a bounded, explicit override), and a + re-quote guard so the executed rate matches what was shown. +- Every fee (bridge, swap, gas) is disclosed. The aggregator will tell you to use **free CCTP** + when paying for aggregation does not beat it. + +## Proof + +Real mainnet round trip executed with this skill: +- Solana → Polygon: `5PRGrU7qC1s6LmvLYmQ8iU1ZGyU4qkvynxGVoK1FCy3kW36SpBh8M8yaiTqH97ZUmbs2o4kr33DFeCSYEH62J3Qk` +- Polygon → Solana: `0x5cb09254977140845386432ae6b89416f3883c35a9b3254a36a2a9979642ae77` diff --git a/solana-x402-bridge-skill/skill/aggregation.md b/solana-x402-bridge-skill/skill/aggregation.md new file mode 100644 index 0000000..8781557 --- /dev/null +++ b/solana-x402-bridge-skill/skill/aggregation.md @@ -0,0 +1,22 @@ +--- +name: bridge-aggregator +description: Aggregate multiple cross-chain bridge providers (Circle CCTP, Mayan, deBridge, Wormhole, Allbridge, LI.FI, HFSP x402) and return the best route for a Solana to EVM transfer — same-asset bridge (USDC->USDC) or cross-chain swap (e.g. SOL->ETH), ranked by amount-out net of all fees and gas. The "Jupiter of cross-chain". Use for "best bridge rate", "cheapest way to bridge", "compare bridges", "aggregate bridge quote". +--- + +# bridge-aggregator + +Quote every supported provider in parallel; return the best net route + the full comparison. + +## How it ranks +1. Query all `BridgeProvider` adapters (`scripts/providers.ts`) for (amount, destChain, destToken). +2. Normalize each quote to `amountOutUSDC` after provider fee + gas. +3. Filter: drop providers above `maxEtaSeconds` or below the reliability floor. +4. Add the transparent HFSP integrator fee on top (INTEGRATOR_FEE_BPS). +5. Rank by net amountOut; tie-break on speed. Return winner + ranked list. + +## Rules +- USDC default benchmark = **Circle CCTP** (native 1:1, no slippage) — always include it. +- ALWAYS return the per-provider comparison, not just the winner — proving best-rate selection is the product. +- Adding a provider = one new adapter file implementing the `BridgeProvider` interface. + +Run `scripts/bridge-quote.ts` (aggregates) — it calls the aggregator internally. diff --git a/solana-x402-bridge-skill/skill/execute.md b/solana-x402-bridge-skill/skill/execute.md new file mode 100644 index 0000000..3d6dd53 --- /dev/null +++ b/solana-x402-bridge-skill/skill/execute.md @@ -0,0 +1,20 @@ +--- +name: bridge-execute +description: Execute a USDC bridge from Solana to an EVM chain via the x402 relayer, after a quote and safety preflight. Returns source and destination transaction hashes and a status handle. Use for "do the bridge", "send the USDC", "execute bridge to Polygon". +--- + +# bridge-execute + +Performs the bridge. Only after `bridge-quote` AND a passing `bridge-safety` preflight. + +## Flow +1. Re-confirm quote is fresh. +2. Pay the relayer via x402 (USDC on Solana) — payment header carries the source tx. +3. Relayer settles native USDC on the destination chain (~45–90s). +4. Return `{ sourceTx, destTx, statusId }` with explorer links. + +## Rules +- Never execute without a passing safety preflight (allowlist, caps, freshness). +- Poll `/status/:id` on the relayer until settled; surface both chain confirmations. +- Reuse the proven flow in `packages/gnosis-card-x402`. +- Run `scripts/bridge-execute.ts`. diff --git a/solana-x402-bridge-skill/skill/fiat.md b/solana-x402-bridge-skill/skill/fiat.md new file mode 100644 index 0000000..0bf702c --- /dev/null +++ b/solana-x402-bridge-skill/skill/fiat.md @@ -0,0 +1,24 @@ +--- +name: fiat-onramp +description: Fund a Solana agent with fiat (card/bank) or cash out to fiat, via Onramper — an aggregator of 20+ on/off-ramp providers across 130+ payment methods. Returns the best ranked onramp/offramp quote, disclosed transparently. Use for "fund with fiat", "buy USDC with card", "onramp", "cash out to bank", "offramp winnings". +--- + +# fiat-onramp + +Onramper integration — the fiat aggregator that mirrors our bridge aggregator. + +> **Status:** the cross-chain **bridge aggregation is LIVE and proven on mainnet** (real round-trip txs). This **Onramper fiat layer currently runs against Onramper's SANDBOX** (staging API / test key) — onramp quotes work end-to-end in sandbox; production fiat on/off-ramp is wired and coming soon. + +## Onramp (fiat -> crypto) +- Quote fiat -> USDC delivered on Solana OR directly on the destination EVM chain. +- Onramper ranks 20+ providers; surface its best quote next to the bridge quote so the agent picks "fund + bridge" vs "fund directly on destination". + +## Offramp (crypto -> fiat) +- Quote USDC -> fiat for cashing out (e.g. Polymarket winnings). + +## Rules +- Quote-first, fee always disclosed (same rule as bridges). +- API key via env (`ONRAMPER_API_KEY`); requests signed. Widget or pure API. +- Supports onramp, offramp, and crypto swaps via one unified API. + +Run `scripts/onramp.ts quote|offramp ...`. diff --git a/solana-x402-bridge-skill/skill/polymarket.md b/solana-x402-bridge-skill/skill/polymarket.md new file mode 100644 index 0000000..85ea9d6 --- /dev/null +++ b/solana-x402-bridge-skill/skill/polymarket.md @@ -0,0 +1,15 @@ +--- +name: polymarket-read +description: Read Polymarket prediction markets — search/list markets, current YES/NO odds, liquidity, resolution status, and the user's open positions. Demo layer on top of the bridge (Polymarket runs on Polygon). Use for "show Polymarket markets", "odds on ", "my Polymarket positions". +--- + +# polymarket-read + +Read-only access to Polymarket (Polygon) via the public **Gamma API**. **LIVE.** + +## Capabilities +- search/list active markets by keyword, ranked by volume +- current odds (per-outcome implied %), liquidity, volume, end date, `conditionId` + +No bridge or funds needed for reads. Run `npm run polymarket read [keyword]` +(e.g. `npm run polymarket read worldcup`). diff --git a/solana-x402-bridge-skill/skill/providers.md b/solana-x402-bridge-skill/skill/providers.md new file mode 100644 index 0000000..fc60708 --- /dev/null +++ b/solana-x402-bridge-skill/skill/providers.md @@ -0,0 +1,59 @@ +# Bridge Providers — Adapter Specs (5 providers) + +The aggregator (`scripts/bridge-aggregator.ts`) ranks these **5 Solana → EVM** providers by net amount-out. Each implements the `BridgeProvider` interface in `scripts/providers.ts`: `supports()`, `quote()`, `execute()`, `status()`. + +> All endpoints/SDKs below are starting points — confirm versions against each provider's live docs before implementing. Normalize every quote into `ProviderQuote` (amountOutUSDC net of provider fee + gas, etaSeconds, reliabilityScore). + +--- + +## 1. Circle CCTP — `cctp` (DEFAULT BENCHMARK) +- **Why:** Native USDC burn-and-mint, **1:1, no slippage**, lowest cost. Every other provider is judged against this. +- **SDK/API:** No price API — it's a protocol. Attestation service (Iris): `https://iris-api.circle.com` (`GET /v1/attestations/{messageHash}`; CCTP v2 supports fast transfers). +- **Flow:** `depositForBurn` on source (Solana TokenMessenger program) → poll Iris for attestation → `receiveMessage` mint on destination EVM. +- **quote():** amountOut ≈ amountIn − dest gas (− fast-transfer fee if CCTP v2 fast). reliabilityScore ~0.99. +- **Solana:** CCTP programs deployed on Solana. Polygon: delivers **native** USDC (note USDC.e mismatch for Polymarket — may need a downstream swap). +- **Docs:** https://developers.circle.com/stablecoins/docs/cctp-getting-started + +## 2. Mayan Finance — `mayan` +- **Why:** Solana-native cross-chain (Swift / MCTP / Wormhole routes), strong Solana↔EVM coverage, fast. +- **SDK/API:** `@mayanfinance/swap-sdk`; quote API `https://price-api.mayan.finance/v3/quote`. +- **quote():** call quote API with fromChain=solana, toChain, fromToken=USDC, amount → returns route + expected out + fees. Pick best of returned routes. +- **execute():** build + sign via SDK (`swapFromSolana`), returns source sig; track via Mayan explorer/status. +- **status():** Mayan tracking API by source tx. +- **Docs:** https://docs.mayan.finance + +## 3. deBridge (DLN) — `debridge` +- **Why:** Fast intent-based liquidity network, native Solana↔EVM support. +- **API:** `https://dln.debridge.finance/v1.0/dln/order/quote` (quote) and `/create-tx` (build). +- **quote():** params srcChainId (Solana=7565164), dstChainId, srcTokenIn=USDC, amount → estimation with fees + recommended out. +- **execute():** `/create-tx` returns the tx to sign on Solana; order filled by takers on destination. +- **status():** order status endpoint by orderId. +- **Docs:** https://docs.debridge.finance/dln-the-debridge-liquidity-network-protocol + +## 4. Wormhole / Portal — `wormhole` +- **Why:** Canonical, battle-tested token bridge; CCTP route also available via Connect. Good fallback. +- **SDK:** `@wormhole-foundation/sdk` (TS). For USDC, prefer its CCTP route; else token-bridge lock/mint. +- **quote():** SDK route quoting; slower (guardian VAA ~ minutes for non-CCTP). Set higher etaSeconds, slightly lower reliabilityScore for wrapped routes. +- **execute():** initiate transfer on Solana → fetch VAA → redeem on destination. +- **status():** poll VAA / redeem status. +- **Docs:** https://wormhole.com/docs/ + +## 5. Allbridge (Core) — `allbridge` +- **Why:** Stablecoin-focused Solana↔EVM pools; simple USDC routing. +- **SDK/API:** `@allbridge/bridge-core-sdk`; API `https://core.api.allbridge.io`. +- **quote():** SDK `getAmountToBeReceived` (accounts for pool fee + slippage) for USDC Solana→dest. +- **execute():** SDK send (sign on Solana); pools settle on destination. +- **status():** SDK/explorer status by tx. +- **Docs:** https://docs.allbridge.io/ + +--- + +## Ranking inputs the aggregator expects from each adapter +`{ provider, amountOutUSDC (net), bridgeFeeUSDC, bridgeFeeBps, networkFeesUSDC, etaSeconds, reliabilityScore, route }` + +## MVP order (24h) +1. **CCTP** (benchmark) + **Mayan** (Solana-native) → prove aggregation with 2. +2. Add **deBridge** → 3 providers = credible aggregator. +3. Add **Wormhole** + **Allbridge** if time remains. + +The HFSP x402 relayer (gnosis-card-x402, generalized) is the **execution/fee layer**, not counted among the 5 external quote providers — it can also be registered as a 6th adapter that carries the integrator fee natively. diff --git a/solana-x402-bridge-skill/skill/quote.md b/solana-x402-bridge-skill/skill/quote.md new file mode 100644 index 0000000..a09691f --- /dev/null +++ b/solana-x402-bridge-skill/skill/quote.md @@ -0,0 +1,30 @@ +--- +name: bridge-quote +description: Quote a USDC bridge from Solana to an EVM chain. Returns route, transparent fee breakdown, network fees, amount out, and ETA. Always call before bridge-execute. Use for "how much to bridge", "bridge quote", "cost to send USDC to Polygon/EVM". +--- + +# bridge-quote + +Read-only. Quote a Solana→EVM USDC bridge via the x402 relayer. + +## Input +`amountUSDC`, `destChain` (see evm-targets), `destToken` (default USDC). + +## Output (always disclose the fee) +```json +{ + "route": "USDC Solana → Polygon (x402)", + "amountIn": "5.00 USDC", + "bridgeFee": "0.0075 USDC (15 bps)", + "networkFees": "~0.01 USDC", + "amountOut": "4.98 USDC", + "etaSeconds": 45, + "feeRecipient": "", + "relayer": "https://bridge.clawdrop.live" +} +``` + +## Rules +- Fee = relayer x402 price. Configurable via INTEGRATOR_FEE_BPS / INTEGRATOR_FEE_ACCOUNT. +- Never hide or round away the fee — it is a feature, show it in full. +- Run `scripts/bridge-quote.ts`. diff --git a/solana-x402-bridge-skill/skill/rpc-health.md b/solana-x402-bridge-skill/skill/rpc-health.md new file mode 100644 index 0000000..eea8fd6 --- /dev/null +++ b/solana-x402-bridge-skill/skill/rpc-health.md @@ -0,0 +1,33 @@ +--- +name: rpc-health +description: Detect lagging or failing RPC endpoints and automatically fail over to a healthy one BEFORE executing — for Solana (slot-lag) and EVM chains (block-lag). Agents that depend on a single RPC are fragile; this swaps endpoints when the primary is stale or dead, and fails loud if none are healthy. Use for "RPC failover", "healthy RPC", "RPC is stale/lagging", "switch RPC endpoint", "RPC health check", "avoid acting on a stale RPC". +--- + +# rpc-health + +Cross-chain RPC health switcher — a reusable utility for any Solana/EVM agent. Never act on a stale or dead RPC. + +## What it does +1. Probes the primary **plus all fallbacks in parallel** (`SOLANA_FALLBACK_RPCS`, `_FALLBACK_RPCS`). +2. Drops dead/timed-out endpoints (`RPC_PROBE_TIMEOUT_MS`, default 2500ms). +3. Computes **lag** vs the freshest endpoint — slot-lag (Solana), block-lag (EVM) — and rejects stale ones (`RPC_MAX_SLOT_LAG` default 150, `EVM_MAX_BLOCK_LAG` default 10). +4. Returns the healthiest endpoint (lowest lag, tie-broken by latency). **Fails loud** if none are healthy/fresh. + +## Use it +- **CLI:** `tsx scripts/rpc-health.ts solana` · `tsx scripts/rpc-health.ts polygon` (API keys redacted in output) +- **Code:** `import { getHealthySolana, getHealthyEvmRpc } from "./rpc-health.js"` +- **Wired in:** `bridge-safety`'s preflight calls both before any `bridge-execute` / `auto-bridge` — so the switcher runs automatically before money moves. + +## Env +``` +SOLANA_RPC_URL # primary Solana RPC +SOLANA_FALLBACK_RPCS # comma-separated failover endpoints +_RPC_URL # e.g. POLYGON_RPC_URL +_FALLBACK_RPCS # e.g. POLYGON_FALLBACK_RPCS +RPC_MAX_SLOT_LAG=150 # max Solana slot-lag before "stale" +EVM_MAX_BLOCK_LAG=10 # max EVM block-lag before "stale" +RPC_PROBE_TIMEOUT_MS=2500 # per-endpoint probe timeout +``` + +## Rule +Never proceed on a stale/dead RPC. If every endpoint is unhealthy, the switcher throws — callers must block (e.g. `bridge-safety` adds it to the failures list). diff --git a/solana-x402-bridge-skill/skill/safety.md b/solana-x402-bridge-skill/skill/safety.md new file mode 100644 index 0000000..a4ff39d --- /dev/null +++ b/solana-x402-bridge-skill/skill/safety.md @@ -0,0 +1,32 @@ +--- +name: bridge-safety +description: Mandatory preflight before any bridge execution. Enforces destination allowlist, per-transaction and daily spend caps, slippage / minimum amount-out, and a stale-RPC freshness guard that refuses to act on lagging chain state. Use whenever a bridge or cross-chain transfer is about to execute. +--- + +# bridge-safety + +The guard that makes moving funds safe. ALWAYS run before `bridge-execute`. + +## Checks (fail loud — never silently proceed) +1. **Destination allowlist** — destChain ∈ DEST_ALLOWLIST. +2. **Spend caps** — amount ≤ MAX_BRIDGE_USDC_PER_TX and rolling 24h ≤ MAX_BRIDGE_USDC_PER_DAY. +3. **Slippage / min-out** — amountOut ≥ user minimum. +4. **Freshness guard** — source RPC slot-lag ≤ RPC_MAX_SLOT_LAG; otherwise fail over (scripts/rpc-health.ts) or abort. A lagging RPC = stale balance = do NOT bridge. +5. **Confirmation monitor** — after execute, confirm on both source and dest chains. + +## Why the freshness guard matters +Bridging on a stale balance read can double-spend or strand funds. Treat a stale slot as "do not act." + +Run `scripts/bridge-safety.ts` (uses `scripts/rpc-health.ts`). + +## Swap slippage (any-token transfers, e.g. SOL->ETH) +For `kind: "swap"` quotes (different destToken), additionally: +- Reject if `amountOut < minAmountOut` (slippage tolerance, DEFAULT_SLIPPAGE_BPS). +- Re-quote right before execute; abort if price drifted beyond tolerance. +Same-asset bridges (USDC->USDC) have priceImpactBps=0 and skip this. + +## RPC health switcher (both chains) +Backed by `scripts/rpc-health.ts`: +- **Solana source:** probes `getSlot` across SOLANA_RPC_URL + SOLANA_FALLBACK_RPCS, picks lowest slot-lag healthy endpoint, fails if all > RPC_MAX_SLOT_LAG behind. +- **EVM destination:** probes `eth_blockNumber` across _RPC_URL + _FALLBACK_RPCS, picks freshest/lowest-latency, fails if all > EVM_MAX_BLOCK_LAG behind. +A failing/lagging RPC on either side blocks execution — agents on a single RPC are fragile; this auto-swaps endpoints before acting. diff --git a/solana-x402-bridge-skill/skill/targets.md b/solana-x402-bridge-skill/skill/targets.md new file mode 100644 index 0000000..db4cee9 --- /dev/null +++ b/solana-x402-bridge-skill/skill/targets.md @@ -0,0 +1,21 @@ +--- +name: evm-targets +description: Registry of EVM chains, token addresses, and relayer endpoints supported by the bridge. Use to discover which destination chains and tokens are available and their identifiers. Use for "which chains are supported", "list EVM targets", "Polygon USDC address". +--- + +# evm-targets + +Source of truth for supported destinations. + +## Each entry +`{ chain, chainId, relayerEndpoint, tokens: { USDC:
, ... }, finalitySeconds }` + +## MVP coverage +- polygon (Polymarket lives here — mandatory) +- gnosis (already live via gnosis-card-x402) +- base +- arbitrum (stretch) + +Keep addresses canonical (USDC.e vs native USDC on Polygon — be explicit; Polymarket uses USDC.e). + +Run `scripts/evm-targets.ts` to print the registry. diff --git a/solana-x402-bridge-skill/skill/testing.md b/solana-x402-bridge-skill/skill/testing.md new file mode 100644 index 0000000..5168c3f --- /dev/null +++ b/solana-x402-bridge-skill/skill/testing.md @@ -0,0 +1,68 @@ +# TEST-PLAN.md — solana-x402-bridge + +Small-amount, reproducible runs that double as the demo. Use tiny sizes; this moves real funds. + +## 0. Prereqs +- `.env` filled: Solana RPC (+ fallbacks), per-chain EVM RPC (+ fallbacks), `X402_RELAYER_URL`, fee config, caps, `ONRAMPER_API_KEY` (optional). +- Demo wallets funded with small amounts (e.g. 5 USDC on Solana; ~0.02 SOL for the swap test). +- `npm install` in the skill package. + +## 1. Aggregation correctness (USDC bridge) — the headline +```bash +npx tsx scripts/bridge-quote.ts USDC 5 polygon USDC +``` +Expect: `BEST (bridge)` plus a ranked COMPARISON across eligible providers (cctp, mayan, debridge, wormhole, allbridge). +Pass: CCTP appears with `priceImpactBps: 0`; fee line disclosed; ranking sorted by net `amountOut`. + +## 2. Cross-chain swap quote (SOL → ETH) — second capability +```bash +npx tsx scripts/bridge-quote.ts SOL 0.1 ethereum ETH +``` +Expect: eligible set narrows to **mayan + debridge** only (cctp/allbridge/wormhole filtered by supportsPair). +Pass: each quote shows `kind: "swap"`, non-zero `priceImpactBps`, and a `minAmountOut`. + +## 3. Safety preflight — must BLOCK bad states +Run each and confirm it fails loud: +```bash +# a) destination not allowlisted +DEST_ALLOWLIST=gnosis npx tsx scripts/bridge-execute.ts USDC 5 polygon USDC # -> blocked: not in allowlist +# b) over per-tx cap +MAX_BRIDGE_USDC_PER_TX=1 npx tsx scripts/bridge-execute.ts USDC 5 polygon USDC # -> blocked: exceeds cap +# c) stale/dead Solana RPC (point primary at a bad URL, no fallback) +SOLANA_RPC_URL=https://api.invalid SOLANA_FALLBACK_RPCS= npx tsx scripts/bridge-execute.ts USDC 5 polygon USDC # -> blocked: Solana RPC +# d) dead EVM RPC +POLYGON_RPC_URL=https://api.invalid POLYGON_FALLBACK_RPCS= npx tsx scripts/bridge-execute.ts USDC 5 polygon USDC # -> blocked: polygon RPC +``` +Pass: every case returns "Safety preflight failed: ..." and does NOT execute. + +## 4. RPC failover — must RECOVER +```bash +# bad primary + good fallback => should succeed via fallback, slotLag within bound +SOLANA_RPC_URL=https://api.invalid \ +SOLANA_FALLBACK_RPCS=$GOOD_SOLANA_RPC \ +npx tsx scripts/bridge-quote.ts USDC 5 polygon USDC +``` +Pass: quote succeeds; switcher selected the healthy fallback. Repeat for `POLYGON_RPC_URL` + `POLYGON_FALLBACK_RPCS`. + +## 5. Execute (real, small) — USDC Solana → Polygon +```bash +npx tsx scripts/bridge-execute.ts USDC 5 polygon USDC +``` +Pass: returns `{sourceTx, destTx, statusId}` + explorer links; USDC arrives on Polygon (~45–90s). NOTE the USDC.e vs native-USDC handling for the Polymarket leg. + +## 6. Polymarket demo +```bash +npx tsx scripts/polymarket.ts read worldcup # list markets + odds +npx tsx scripts/polymarket.ts bet YES 5 # place small bet +``` +Pass: market list returns odds; bet returns a position. + +## 7. Optional — fiat funnel (Onramper) +```bash +npx tsx scripts/onramp.ts quote USD 20 solana # best ranked fiat->USDC quote, fee disclosed +``` +Pass: returns a ranked provider quote with disclosed fee. + +## Demo recording order (60s) +Step 1 (aggregation) → step 3c (safety blocks stale RPC) → step 5 (execute) → step 6 (bet). +That sequence shows: best-rate aggregation, safety, real settlement, real action — the full story. diff --git a/solana-x402-bridge-skill/tsconfig.json b/solana-x402-bridge-skill/tsconfig.json new file mode 100644 index 0000000..0ec55c8 --- /dev/null +++ b/solana-x402-bridge-skill/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "types": ["node"], + "strict": true, + "noEmit": true, + "skipLibCheck": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true + }, + "include": ["scripts/**/*.ts"] +}