From b4de6b8b45f3d50525d5e35d81cecba5fbb7fda7 Mon Sep 17 00:00:00 2001 From: bdj Date: Wed, 17 Sep 2025 10:46:14 -0700 Subject: [PATCH 01/61] First draft --- README.md | 56 +- docs/x402-integration.md | 340 +++++ examples/x402-server/.env.example | 10 + examples/x402-server/README.md | 140 +++ examples/x402-server/package.json | 26 + examples/x402-server/src/server.ts | 195 +++ examples/x402-server/src/test-client.ts | 113 ++ examples/x402-server/tsconfig.json | 11 + package-lock.json | 1089 +++++++---------- packages/atxp-client/src/atxpAccount.ts | 60 +- packages/atxp-client/src/basePaymentMaker.ts | 100 +- packages/atxp-client/src/index.ts | 10 +- .../atxp-client/src/solanaPaymentMaker.ts | 93 +- packages/atxp-client/src/types.ts | 12 + packages/atxp-client/src/x402Wrapper.ts | 178 +++ 15 files changed, 1718 insertions(+), 715 deletions(-) create mode 100644 docs/x402-integration.md create mode 100644 examples/x402-server/.env.example create mode 100644 examples/x402-server/README.md create mode 100644 examples/x402-server/package.json create mode 100644 examples/x402-server/src/server.ts create mode 100644 examples/x402-server/src/test-client.ts create mode 100644 examples/x402-server/tsconfig.json create mode 100644 packages/atxp-client/src/x402Wrapper.ts diff --git a/README.md b/README.md index b49e258f..d119cf68 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,57 @@ # ATXP -ATXP is a framework for building and running agents that can interact with the world. See [docs.atxp.ai](https://docs.atxp.ai) for documentation and examples. \ No newline at end of file +ATXP is a framework for building and running agents that can interact with the world. See [docs.atxp.ai](https://docs.atxp.ai) for documentation and examples. + +## Features + +- **OAuth 2.0 Authentication**: Secure authentication flow for accessing protected resources +- **Micropayments**: Built-in support for USDC payments on Base and Solana networks +- **MCP Integration**: Full Model Context Protocol support for AI agents +- **X402 Protocol Support**: Compatible with X402 payment-required servers +- **Multi-Network**: Support for Base, Solana, and ATXP native accounts + +## X402 Support + +ATXP SDK now includes support for the X402 payment protocol, allowing ATXP clients to interact with X402 servers seamlessly. This enables: + +- Automatic handling of HTTP 402 payment challenges +- Signed payment message creation without immediate blockchain submission +- Facilitator-based payment verification and settlement + +For detailed X402 integration instructions, see [X402 Integration Guide](./docs/x402-integration.md) and the [X402 example](./examples/x402-server). + +## Quick Start + +### Basic ATXP Client + +```typescript +import { atxpClient, BaseAccount } from '@atxp/client'; + +const account = new BaseAccount(rpcUrl, privateKey); +const client = await atxpClient({ account, /* ... */ }); +``` + +### With X402 Support + +```typescript +import { wrapWithX402 } from '@atxp/client'; + +const x402Fetch = wrapWithX402(fetch, { + account, + approvePayment: async (payment) => true, + // ... configuration +}); +``` + +## Documentation + +- [ATXP Documentation](https://docs.atxp.ai) +- [X402 Integration Guide](./docs/x402-integration.md) +- [API Reference](https://docs.atxp.ai/api) + +## Examples + +- [Basic ATXP Example](./examples/basic) +- [X402 Server Example](./examples/x402-server) +- [Server Example](./examples/server) +- [Vercel SDK Integration](./examples/vercel-sdk) \ No newline at end of file diff --git a/docs/x402-integration.md b/docs/x402-integration.md new file mode 100644 index 00000000..9535b6cd --- /dev/null +++ b/docs/x402-integration.md @@ -0,0 +1,340 @@ +# X402 Integration Guide + +## Overview + +The ATXP SDK now includes support for the X402 payment protocol, allowing ATXP clients to seamlessly interact with X402 servers. X402 is a micropayment protocol that uses HTTP 402 (Payment Required) status codes to enable pay-per-use web resources. + +## Key Concepts + +### X402 Protocol Flow + +1. **Payment Challenge**: Server responds with HTTP 402 and payment requirements in `X-Payment` header +2. **Payment Signing**: Client creates and signs a payment message without submitting to blockchain +3. **Payment Verification**: Server's facilitator verifies the signed payment +4. **Payment Settlement**: Facilitator submits the payment to blockchain +5. **Resource Access**: Server grants access to the protected resource + +### Architecture Components + +- **Client**: Uses ATXP SDK with X402 wrapper to handle payment challenges +- **Resource Server**: Protects resources and issues payment challenges +- **Facilitator**: Verifies signatures and settles payments on-chain + +## Implementation + +### Refactored PaymentMaker Interface + +The `PaymentMaker` interface has been extended to support separate signing and submission: + +```typescript +interface PaymentMaker { + // Original method (still supported) + makePayment(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise; + + // New methods for X402 support + createSignedPaymentMessage(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise; + submitPaymentMessage(signedMessage: SignedPaymentMessage): Promise; + + generateJWT(params: {paymentRequestId: string, codeChallenge: string}): Promise; +} +``` + +### SignedPaymentMessage Type + +```typescript +type SignedPaymentMessage = { + data: string; // Transaction data + signature: string; // Signed transaction + from: string; // Sender address + to: string; // Recipient address + amount: BigNumber; // Payment amount + currency: Currency; // Payment currency + network: Network; // Blockchain network +} +``` + +## Usage + +### Basic X402 Integration + +```typescript +import { wrapWithX402, BaseAccount } from '@atxp/client'; + +// Create an account +const account = new BaseAccount(rpcUrl, privateKey); + +// Wrap fetch with X402 support +const x402Fetch = wrapWithX402(fetch, { + account, + approvePayment: async (payment) => { + console.log(`Approve payment of ${payment.amount} ${payment.currency}?`); + return true; // or false to reject + }, + onPayment: async ({ payment }) => { + console.log('Payment successful:', payment); + }, + onPaymentFailure: async ({ payment, error }) => { + console.error('Payment failed:', error); + }, + logger: new ConsoleLogger(), + maxRetries: 1 +}); + +// Use like regular fetch +const response = await x402Fetch('https://x402-server.com/protected-resource'); +const data = await response.json(); +``` + +### Advanced Configuration + +```typescript +import { enableX402Support } from '@atxp/client'; + +const config = enableX402Support({ + account, + approvePayment: async (payment) => { + // Custom approval logic + if (payment.amount.gt(new BigNumber(10))) { + // Require user confirmation for payments > 10 USDC + return await promptUser(payment); + } + return true; + }, + onPayment: async ({ payment }) => { + // Track successful payments + await analytics.track('payment_success', { + amount: payment.amount.toString(), + currency: payment.currency, + resource: payment.resourceUrl + }); + }, + onPaymentFailure: async ({ payment, error }) => { + // Handle payment failures + await analytics.track('payment_failure', { + error: error.message, + resource: payment.resourceUrl + }); + }, + logger: customLogger, + maxRetries: 2 +}); + +// Use the wrapped fetch +const response = await config.fetchFn(url); +``` + +### Integration with Existing ATXP Client + +```typescript +import { atxpClient, wrapWithX402 } from '@atxp/client'; + +// Create ATXP client with X402 support +const clientConfig = buildClientConfig({ + account, + // ... other config + fetchFn: wrapWithX402(fetch, { + account, + approvePayment: async (payment) => true, + // ... X402 config + }) +}); + +const client = await atxpClient(clientConfig); +``` + +## Supported Account Types + +X402 support depends on the facilitator's capabilities. The following account types are expected to work: + +| Account Type | Network | Currency | Status | +|-------------|---------|----------|--------| +| BaseAccount | Base | USDC | ✅ Supported | +| SolanaAccount | Solana | USDC | ✅ Supported | +| ATXPAccount | Base | USDC | ✅ Supported | + +Note: Actual compatibility depends on the X402 facilitator implementation. + +## Payment Approval Strategies + +### Automatic Approval + +```typescript +approvePayment: async (payment) => { + // Auto-approve small payments + const threshold = new BigNumber(1); // 1 USDC + return payment.amount.lte(threshold); +} +``` + +### User Confirmation + +```typescript +approvePayment: async (payment) => { + // Show confirmation dialog + const message = `Approve ${payment.amount} ${payment.currency} payment to access ${payment.resourceName}?`; + return await showConfirmDialog(message); +} +``` + +### Whitelist-based + +```typescript +const trustedServers = ['https://trusted1.com', 'https://trusted2.com']; + +approvePayment: async (payment) => { + const url = new URL(payment.resourceUrl); + return trustedServers.includes(url.origin); +} +``` + +## Error Handling + +The X402 wrapper handles various error scenarios: + +```typescript +onPaymentFailure: async ({ payment, error }) => { + if (error.message.includes('No payment maker')) { + console.error('Unsupported network/currency combination'); + } else if (error.message.includes('Payment not approved')) { + console.log('User rejected payment'); + } else if (error.message.includes('Insufficient funds')) { + console.error('Not enough balance'); + } else { + console.error('Payment failed:', error); + } +} +``` + +## Security Considerations + +1. **Payment Approval**: Always implement proper payment approval logic +2. **Amount Validation**: Verify payment amounts match expected values +3. **Recipient Validation**: Ensure payments go to legitimate recipients +4. **Replay Protection**: Facilitators should prevent payment replay attacks +5. **Private Keys**: Never expose private keys in client-side code + +## Testing + +### Mock X402 Server + +Use the provided example server for testing: + +```bash +cd examples/x402-server +npm install +npm run dev +``` + +### Test Client + +```bash +cd examples/x402-server +npm run test-client +``` + +### Unit Testing + +```typescript +import { wrapWithX402 } from '@atxp/client'; +import { MockAccount } from '@atxp/client/testing'; + +describe('X402 Integration', () => { + it('handles payment challenges', async () => { + const mockAccount = new MockAccount(); + const mockFetch = jest.fn() + .mockReturnValueOnce({ + status: 402, + headers: new Headers({ + 'X-Payment': JSON.stringify({ + network: 'base', + currency: 'USDC', + amount: '1', + recipient: '0x...' + }) + }) + }) + .mockReturnValueOnce({ + ok: true, + json: async () => ({ data: 'protected' }) + }); + + const x402Fetch = wrapWithX402(mockFetch, { + account: mockAccount, + approvePayment: async () => true + }); + + const response = await x402Fetch('https://example.com/protected'); + const data = await response.json(); + + expect(data).toEqual({ data: 'protected' }); + expect(mockFetch).toHaveBeenCalledTimes(2); + }); +}); +``` + +## Migration Guide + +### For Existing ATXP Users + +1. Update your PaymentMaker implementations if you have custom ones +2. Add X402 wrapper to your fetch configuration if needed +3. No changes required if not using X402 servers + +### For X402 Server Operators + +1. Implement standard X402 challenge/response flow +2. Use a compatible facilitator that supports Base/Solana +3. Follow the example server implementation + +## Troubleshooting + +### Common Issues + +| Issue | Solution | +|-------|----------| +| "No payment maker found" | Ensure account has payment maker for required network/currency | +| "Payment not approved" | Check approvePayment callback logic | +| "Insufficient funds" | Ensure account has enough balance | +| "Invalid signature" | Verify facilitator supports your account type | +| "Transaction reverted" | Check recipient address and amount | + +### Debug Logging + +Enable detailed logging for troubleshooting: + +```typescript +import { ConsoleLogger } from '@atxp/common'; + +const logger = new ConsoleLogger(); +logger.level = 'debug'; + +const x402Fetch = wrapWithX402(fetch, { + account, + logger, + // ... other config +}); +``` + +## FAQ + +**Q: Can I use X402 with existing ATXP servers?** +A: No, X402 and ATXP are different protocols. X402 servers specifically implement the X402 payment challenge flow. + +**Q: What happens if payment fails?** +A: The original 402 response is returned, and the `onPaymentFailure` callback is triggered. + +**Q: Can I retry failed payments?** +A: Yes, configure `maxRetries` in the X402 config. + +**Q: Is the payment submitted immediately?** +A: With X402, the client only signs the payment. The facilitator submits it to the blockchain. + +**Q: Can I use custom facilitators?** +A: Yes, as long as they follow the X402 protocol specification. + +## References + +- [X402 Protocol Specification](https://x402.org/spec) +- [ATXP Documentation](https://atxp.ai/docs) +- [Example Implementation](../examples/x402-server) +- [Design Document](./x402-design.md) \ No newline at end of file diff --git a/examples/x402-server/.env.example b/examples/x402-server/.env.example new file mode 100644 index 00000000..39696533 --- /dev/null +++ b/examples/x402-server/.env.example @@ -0,0 +1,10 @@ +# Base network RPC URL +# You can get one from https://www.alchemy.com/ or https://www.infura.io/ +BASE_RPC_URL=https://base-mainnet.g.alchemy.com/v2/your-api-key + +# Private key for the Base account (without 0x prefix) +# WARNING: Never commit real private keys to version control +BASE_PRIVATE_KEY=your_private_key_here + +# Optional: X402 server URL (defaults to http://localhost:3001) +X402_SERVER_URL=http://localhost:3001 \ No newline at end of file diff --git a/examples/x402-server/README.md b/examples/x402-server/README.md new file mode 100644 index 00000000..4292fa5f --- /dev/null +++ b/examples/x402-server/README.md @@ -0,0 +1,140 @@ +# X402 Server Example + +This example demonstrates how to use ATXP SDK with X402 payment protocol support. + +## What is X402? + +X402 is a payment protocol that uses HTTP 402 (Payment Required) status codes with payment headers to enable micropayments for web resources. The protocol involves three parties: + +1. **Client** - Makes payments to access resources +2. **Resource Server** - Serves protected content and requires payment +3. **Facilitator** - Verifies and settles payments on the blockchain + +## Setup + +1. Install dependencies: +```bash +npm install +``` + +2. Create a `.env` file based on `.env.example`: +```bash +cp .env.example .env +``` + +3. Configure your environment variables: + - `BASE_RPC_URL`: Your Base network RPC endpoint + - `BASE_PRIVATE_KEY`: Private key for a Base account with USDC funds + +## Running the Example + +### Start the X402 Server + +```bash +npm run dev +``` + +This starts a mock X402 server on `http://localhost:3001` with the following endpoints: + +- `GET /protected-resource/:id` - Protected resource requiring 1 USDC payment +- `GET /health` - Health check endpoint +- `GET /user/:address/resources` - List resources accessed by a user + +### Test with the Client + +In a separate terminal: + +```bash +npm run test-client +``` + +This runs a test client that: +1. Attempts to access a protected resource with regular fetch (fails with 402) +2. Uses X402-wrapped fetch to automatically handle payment and access the resource +3. Accesses multiple resources and tracks them + +## How It Works + +### Server Flow + +1. Client requests a protected resource +2. Server returns 402 status with `X-Payment` header containing payment requirements +3. Client signs a payment message and retries with `X-Payment` header +4. Server verifies the payment with facilitator +5. Facilitator settles payment on blockchain +6. Server returns the protected resource + +### Client Flow + +The ATXP SDK provides a `wrapWithX402` function that wraps the standard fetch API: + +```typescript +const x402Fetch = wrapWithX402(fetch, { + account, + approvePayment: async (payment) => { + // Approve or reject payment + return true; + }, + onPayment: async ({ payment }) => { + // Payment successful + }, + onPaymentFailure: async ({ payment, error }) => { + // Payment failed + } +}); + +// Use like regular fetch +const response = await x402Fetch('http://example.com/protected'); +``` + +## Important Notes + +⚠️ **This is a mock implementation for demonstration purposes** + +- The facilitator is mocked and doesn't actually verify signatures or submit to blockchain +- In production, use a real X402 facilitator service +- Never commit real private keys to version control +- Always validate payment amounts and recipients on the server side + +## Architecture + +``` +┌─────────┐ 402 + Challenge ┌────────────┐ +│ │ ──────────────────────> │ │ +│ Client │ │ Server │ +│ │ <────────────────────── │ │ +└─────────┘ Retry + Payment Msg └────────────┘ + │ │ + │ │ Verify + │ ▼ + │ ┌────────────┐ + │ │Facilitator │ + └─────────────────────────────> │ │ + Submit to Chain └────────────┘ +``` + +## Supported Networks and Currencies + +Currently supports: +- **Base Network**: USDC +- **Solana**: USDC (when using SolanaAccount) + +## Troubleshooting + +### Insufficient Funds Error +Ensure your account has enough USDC on the Base network. + +### Network Errors +Check that your RPC URL is correct and accessible. + +### Payment Verification Fails +In production, ensure the facilitator service is properly configured. + +## Next Steps + +To integrate X402 support in your application: + +1. Wrap your fetch calls with `wrapWithX402` +2. Implement payment approval logic +3. Handle payment events for user feedback +4. Deploy with a real X402 facilitator service \ No newline at end of file diff --git a/examples/x402-server/package.json b/examples/x402-server/package.json new file mode 100644 index 00000000..2f68d4fd --- /dev/null +++ b/examples/x402-server/package.json @@ -0,0 +1,26 @@ +{ + "name": "@atxp/x402-server-example", + "version": "1.0.0", + "type": "module", + "private": true, + "scripts": { + "dev": "tsx watch src/server.ts", + "start": "tsx src/server.ts", + "test-client": "tsx src/test-client.ts" + }, + "dependencies": { + "@atxp/client": "workspace:*", + "@atxp/common": "workspace:*", + "express": "^4.18.2", + "cors": "^2.8.5", + "bignumber.js": "^9.1.2", + "dotenv": "^16.0.3" + }, + "devDependencies": { + "@types/express": "^4.17.17", + "@types/cors": "^2.8.13", + "@types/node": "^20.0.0", + "tsx": "^4.0.0", + "typescript": "^5.0.0" + } +} \ No newline at end of file diff --git a/examples/x402-server/src/server.ts b/examples/x402-server/src/server.ts new file mode 100644 index 00000000..d7e70abb --- /dev/null +++ b/examples/x402-server/src/server.ts @@ -0,0 +1,195 @@ +import express from 'express'; +import cors from 'cors'; +import { BigNumber } from 'bignumber.js'; +import { Network, Currency } from '@atxp/common'; +import type { SignedPaymentMessage } from '@atxp/client'; + +const app = express(); +app.use(cors()); +app.use(express.json()); + +// Mock facilitator for demonstration +// In production, this would be replaced with an actual X402 facilitator +class MockX402Facilitator { + private processedPayments = new Map(); + + async verify(paymentMessage: SignedPaymentMessage): Promise { + // Mock verification - in production this would: + // 1. Verify the signature + // 2. Check account balance + // 3. Verify the payment details match what was requested + console.log('Facilitator: Verifying payment message:', { + from: paymentMessage.from, + to: paymentMessage.to, + amount: paymentMessage.amount.toString(), + currency: paymentMessage.currency, + network: paymentMessage.network + }); + + // Simple mock validation + if (!paymentMessage.signature || !paymentMessage.data) { + console.log('Facilitator: Invalid payment message - missing signature or data'); + return false; + } + + // Check if payment amount is sufficient (mock check) + const requiredAmount = new BigNumber('1'); // 1 USDC + if (paymentMessage.amount.lt(requiredAmount)) { + console.log(`Facilitator: Insufficient payment amount. Required: ${requiredAmount}, Got: ${paymentMessage.amount}`); + return false; + } + + return true; + } + + async settle(paymentMessage: SignedPaymentMessage): Promise { + // Mock settlement - in production this would submit to blockchain + console.log('Facilitator: Settling payment on blockchain...'); + + // Generate a mock transaction hash + const mockTxHash = '0x' + Math.random().toString(16).substring(2, 66); + + // Mark as processed to prevent replay + this.processedPayments.set(paymentMessage.signature, true); + + console.log(`Facilitator: Payment settled with tx hash: ${mockTxHash}`); + return mockTxHash; + } + + isPaymentProcessed(signature: string): boolean { + return this.processedPayments.has(signature); + } +} + +const facilitator = new MockX402Facilitator(); + +// Protected resource that requires payment +interface ResourceData { + data: string; + timestamp: number; +} + +// Store for accessed resources (in production, this would be a database) +const accessedResources = new Map>(); + +// Example protected endpoint +app.get('/protected-resource/:id', async (req, res) => { + const resourceId = req.params.id; + const paymentHeader = req.headers['x-payment'] as string | undefined; + + console.log(`\n=== Request for resource: ${resourceId} ===`); + + // Check if payment was provided + if (!paymentHeader) { + console.log('No payment provided, sending 402 challenge'); + + // Send X402 payment challenge + const paymentChallenge = { + network: 'base' as Network, + currency: 'USDC' as Currency, + amount: '1', // 1 USDC + recipient: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb8', // Example recipient address + memo: `Payment for resource ${resourceId}` + }; + + res.status(402) + .header('X-Payment', JSON.stringify(paymentChallenge)) + .json({ + error: 'Payment Required', + message: 'This resource requires payment to access', + payment: paymentChallenge + }); + return; + } + + try { + // Parse the payment message from header + console.log('Payment header received:', paymentHeader); + const paymentMessage: SignedPaymentMessage = JSON.parse(paymentHeader); + + // Check if this payment was already processed + if (facilitator.isPaymentProcessed(paymentMessage.signature)) { + console.log('Payment already processed (replay attempt)'); + res.status(400).json({ + error: 'Payment already processed', + message: 'This payment signature has already been used' + }); + return; + } + + // Verify the payment with facilitator + const isValid = await facilitator.verify(paymentMessage); + + if (!isValid) { + console.log('Payment verification failed'); + res.status(400).json({ + error: 'Invalid payment', + message: 'The payment could not be verified' + }); + return; + } + + // Settle the payment + const txHash = await facilitator.settle(paymentMessage); + + // Grant access to the resource + const userAddress = paymentMessage.from; + if (!accessedResources.has(userAddress)) { + accessedResources.set(userAddress, new Set()); + } + accessedResources.get(userAddress)!.add(resourceId); + + console.log(`Access granted to ${userAddress} for resource ${resourceId}`); + + // Return the protected resource + const resource: ResourceData = { + data: `This is protected content for resource ${resourceId}. Thank you for your payment!`, + timestamp: Date.now() + }; + + res.json({ + success: true, + transactionHash: txHash, + resource + }); + + } catch (error) { + console.error('Error processing payment:', error); + res.status(500).json({ + error: 'Payment processing failed', + message: (error as Error).message + }); + } +}); + +// Health check endpoint +app.get('/health', (req, res) => { + res.json({ status: 'ok', facilitator: 'mock' }); +}); + +// List accessed resources for a user +app.get('/user/:address/resources', (req, res) => { + const userAddress = req.params.address; + const resources = accessedResources.get(userAddress); + + res.json({ + address: userAddress, + resources: resources ? Array.from(resources) : [] + }); +}); + +const PORT = process.env.PORT || 3001; + +app.listen(PORT, () => { + console.log(`X402 Example Server running on http://localhost:${PORT}`); + console.log('\nAvailable endpoints:'); + console.log(` GET /protected-resource/:id - Protected resource requiring X402 payment`); + console.log(` GET /health - Health check`); + console.log(` GET /user/:address/resources - List resources accessed by a user`); + console.log('\nPayment details:'); + console.log(' Network: Base'); + console.log(' Currency: USDC'); + console.log(' Amount: 1 USDC per resource'); + console.log('\nNote: This is a mock implementation for demonstration purposes.'); + console.log('In production, use a real X402 facilitator for payment verification and settlement.'); +}); \ No newline at end of file diff --git a/examples/x402-server/src/test-client.ts b/examples/x402-server/src/test-client.ts new file mode 100644 index 00000000..2b8cfbe8 --- /dev/null +++ b/examples/x402-server/src/test-client.ts @@ -0,0 +1,113 @@ +import { wrapWithX402, BaseAccount, type ProspectivePayment } from '@atxp/client'; +import { ConsoleLogger } from '@atxp/common'; +import { BigNumber } from 'bignumber.js'; +import dotenv from 'dotenv'; + +dotenv.config(); + +async function testX402Client() { + const logger = new ConsoleLogger(); + + // Check for required environment variables + if (!process.env.BASE_RPC_URL || !process.env.BASE_PRIVATE_KEY) { + console.error('Missing required environment variables: BASE_RPC_URL and BASE_PRIVATE_KEY'); + console.error('Please create a .env file with:'); + console.error('BASE_RPC_URL=your_base_rpc_url'); + console.error('BASE_PRIVATE_KEY=your_private_key'); + process.exit(1); + } + + console.log('=== X402 Client Test ===\n'); + + // Create a Base account + const account = new BaseAccount( + process.env.BASE_RPC_URL, + process.env.BASE_PRIVATE_KEY + ); + + console.log('Account address:', await account.getAddress()); + + // Create X402-wrapped fetch + const x402Fetch = wrapWithX402(fetch as any, { + account, + approvePayment: async (payment: ProspectivePayment) => { + console.log('\n--- Payment Approval Request ---'); + console.log(`Resource: ${payment.resourceUrl}`); + console.log(`Amount: ${payment.amount} ${payment.currency}`); + console.log(`Network: ${payment.network}`); + + // Auto-approve for testing (in production, prompt user) + const approved = true; + console.log(`Approved: ${approved}`); + console.log('-------------------------------\n'); + + return approved; + }, + onPayment: async ({ payment }) => { + console.log(`✅ Payment successful for ${payment.amount} ${payment.currency}`); + }, + onPaymentFailure: async ({ payment, error }) => { + console.error(`❌ Payment failed for ${payment.amount} ${payment.currency}:`, error.message); + }, + logger, + maxRetries: 1 + }); + + const serverUrl = process.env.X402_SERVER_URL || 'http://localhost:3001'; + + try { + // First, check server health + console.log(`\nChecking server health at ${serverUrl}...`); + const healthResponse = await fetch(`${serverUrl}/health`); + const health = await healthResponse.json(); + console.log('Server health:', health); + + // Try to access a protected resource without payment (should fail with regular fetch) + console.log('\n1. Attempting to access protected resource with regular fetch...'); + const regularResponse = await fetch(`${serverUrl}/protected-resource/123`); + console.log(`Response status: ${regularResponse.status} ${regularResponse.statusText}`); + + if (regularResponse.status === 402) { + const errorData = await regularResponse.json(); + console.log('Received 402 Payment Required:', errorData.message); + } + + // Now try with X402-enabled fetch + console.log('\n2. Attempting to access protected resource with X402-enabled fetch...'); + const x402Response = await x402Fetch(`${serverUrl}/protected-resource/123`); + console.log(`Response status: ${x402Response.status} ${x402Response.statusText}`); + + if (x402Response.ok) { + const data = await x402Response.json(); + console.log('\n🎉 Successfully accessed protected resource!'); + console.log('Transaction hash:', data.transactionHash); + console.log('Resource data:', data.resource); + } else { + const errorData = await x402Response.json(); + console.log('Failed to access resource:', errorData); + } + + // Try to access another resource + console.log('\n3. Accessing a second protected resource...'); + const secondResponse = await x402Fetch(`${serverUrl}/protected-resource/456`); + + if (secondResponse.ok) { + const data = await secondResponse.json(); + console.log('\n🎉 Successfully accessed second resource!'); + console.log('Resource data:', data.resource); + } + + // Check what resources we've accessed + const userAddress = await account.getAddress(); + console.log(`\n4. Checking accessed resources for ${userAddress}...`); + const resourcesResponse = await fetch(`${serverUrl}/user/${userAddress}/resources`); + const resourcesData = await resourcesResponse.json(); + console.log('Accessed resources:', resourcesData.resources); + + } catch (error) { + console.error('Test failed:', error); + } +} + +// Run the test +testX402Client().catch(console.error); \ No newline at end of file diff --git a/examples/x402-server/tsconfig.json b/examples/x402-server/tsconfig.json new file mode 100644 index 00000000..30709e6b --- /dev/null +++ b/examples/x402-server/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "rootDir": "./src", + "outDir": "./dist", + "declaration": false, + "declarationMap": false + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index f5ab837b..f0d31b25 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@atxp/atxp-monorepo", - "version": "0.4.0", + "version": "0.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@atxp/atxp-monorepo", - "version": "0.4.0", + "version": "0.3.0", "license": "MIT", "workspaces": [ "packages/atxp-common", @@ -14,9 +14,7 @@ "packages/atxp-redis", "packages/atxp-server", "packages/atxp-client", - "packages/atxp-base", - "packages/atxp-express", - "packages/atxp-cloudflare" + "packages/atxp-base" ], "dependencies": { "dotenv": "^16.5.0" @@ -72,51 +70,10 @@ "version": "1.11.0", "license": "MIT" }, - "node_modules/@ai-sdk/gateway": { - "version": "1.0.23", - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "@ai-sdk/provider": "2.0.0", - "@ai-sdk/provider-utils": "3.0.9" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "zod": "^3.25.76 || ^4" - } - }, - "node_modules/@ai-sdk/provider": { - "version": "2.0.0", - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "json-schema": "^0.4.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@ai-sdk/provider-utils": { - "version": "3.0.9", - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "@ai-sdk/provider": "2.0.0", - "@standard-schema/spec": "^1.0.0", - "eventsource-parser": "^3.0.5" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "zod": "^3.25.76 || ^4" - } - }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "license": "Apache-2.0", + "peer": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" @@ -150,18 +107,10 @@ "resolved": "packages/atxp-client", "link": true }, - "node_modules/@atxp/cloudflare": { - "resolved": "packages/atxp-cloudflare", - "link": true - }, "node_modules/@atxp/common": { "resolved": "packages/atxp-common", "link": true }, - "node_modules/@atxp/express": { - "resolved": "packages/atxp-express", - "link": true - }, "node_modules/@atxp/redis": { "resolved": "packages/atxp-redis", "link": true @@ -453,6 +402,7 @@ "node_modules/@babel/helper-string-parser": { "version": "7.27.1", "license": "MIT", + "peer": true, "engines": { "node": ">=6.9.0" } @@ -578,6 +528,7 @@ "node_modules/@babel/parser": { "version": "7.27.5", "license": "MIT", + "peer": true, "dependencies": { "@babel/types": "^7.27.3" }, @@ -1486,17 +1437,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/runtime-corejs3": { - "version": "7.28.4", - "license": "MIT", - "peer": true, - "dependencies": { - "core-js-pure": "^3.43.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/template": { "version": "7.27.2", "license": "MIT", @@ -1548,6 +1488,7 @@ "node_modules/@babel/types": { "version": "7.27.3", "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" @@ -1558,6 +1499,8 @@ }, "node_modules/@base-org/account": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@base-org/account/-/account-2.1.0.tgz", + "integrity": "sha512-iQBuMRmL2krwXCZgDF8b9/5JUncjwtd88UMHj+xsfMUOMn/j4WGwCTa8foevNNPKLtxq0OGjTagRIHCF2IEVEA==", "license": "Apache-2.0", "dependencies": { "@noble/hashes": "1.4.0", @@ -1617,20 +1560,6 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/@bcoe/v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", - "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@cloudflare/workers-types": { - "version": "4.20250917.0", - "license": "MIT OR Apache-2.0" - }, "node_modules/@csstools/color-helpers": { "version": "5.0.2", "dev": true, @@ -3355,11 +3284,14 @@ }, "node_modules/@ioredis/commands": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.3.0.tgz", + "integrity": "sha512-M/T6Zewn7sDaBQEqIZ8Rb+i9y8qfGmq+5SDFSf9sA2lUZTmdDLVdOiQaeDp+Q4wElZ9HG1GAX5KhDaidp6LQsQ==", "license": "MIT" }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "license": "ISC", + "peer": true, "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", @@ -3375,6 +3307,7 @@ "node_modules/@isaacs/cliui/node_modules/ansi-regex": { "version": "6.1.0", "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -3385,6 +3318,7 @@ "node_modules/@isaacs/cliui/node_modules/ansi-styles": { "version": "6.2.1", "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -3394,11 +3328,13 @@ }, "node_modules/@isaacs/cliui/node_modules/emoji-regex": { "version": "9.2.2", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@isaacs/cliui/node_modules/string-width": { "version": "5.1.2", "license": "MIT", + "peer": true, "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -3414,6 +3350,7 @@ "node_modules/@isaacs/cliui/node_modules/strip-ansi": { "version": "7.1.0", "license": "MIT", + "peer": true, "dependencies": { "ansi-regex": "^6.0.1" }, @@ -3427,6 +3364,7 @@ "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { "version": "8.1.0", "license": "MIT", + "peer": true, "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -3476,6 +3414,7 @@ "node_modules/@istanbuljs/schema": { "version": "0.1.3", "license": "MIT", + "peer": true, "engines": { "node": ">=8" } @@ -3656,6 +3595,7 @@ "node_modules/@jridgewell/gen-mapping": { "version": "0.3.8", "license": "MIT", + "peer": true, "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -3668,6 +3608,7 @@ "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "license": "MIT", + "peer": true, "engines": { "node": ">=6.0.0" } @@ -3675,6 +3616,7 @@ "node_modules/@jridgewell/set-array": { "version": "1.2.1", "license": "MIT", + "peer": true, "engines": { "node": ">=6.0.0" } @@ -3693,17 +3635,16 @@ "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "version": "0.3.25", "license": "MIT", + "peer": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "node_modules/@modelcontextprotocol/sdk": { - "version": "1.18.0", + "version": "1.15.0", "license": "MIT", "dependencies": { "ajv": "^6.12.6", @@ -3788,14 +3729,6 @@ "node": ">= 8" } }, - "node_modules/@opentelemetry/api": { - "version": "1.9.0", - "license": "Apache-2.0", - "peer": true, - "engines": { - "node": ">=8.0.0" - } - }, "node_modules/@paralleldrive/cuid2": { "version": "2.2.2", "dev": true, @@ -4150,6 +4083,8 @@ }, "node_modules/@rollup/plugin-commonjs": { "version": "28.0.6", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.6.tgz", + "integrity": "sha512-XSQB1K7FUU5QP+3lOQmVCE3I0FcbbNvmNT4VJSj93iUjayaARrTQeoRdiYQoftAJBLrR9t2agwAd3ekaTgHNlw==", "dev": true, "license": "MIT", "dependencies": { @@ -4175,11 +4110,15 @@ }, "node_modules/@rollup/plugin-commonjs/node_modules/estree-walker": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "dev": true, "license": "MIT" }, "node_modules/@rollup/plugin-json": { "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.1.0.tgz", + "integrity": "sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==", "dev": true, "license": "MIT", "dependencies": { @@ -4199,6 +4138,8 @@ }, "node_modules/@rollup/plugin-node-resolve": { "version": "16.0.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-16.0.1.tgz", + "integrity": "sha512-tk5YCxJWIG81umIvNkSod2qK5KyQW19qcBF/B78n1bjtOON6gzKoVeSzAE8yHCZEDmqkHKkxplExA8KzdJLJpA==", "dev": true, "license": "MIT", "dependencies": { @@ -4222,6 +4163,8 @@ }, "node_modules/@rollup/plugin-typescript": { "version": "12.1.4", + "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-12.1.4.tgz", + "integrity": "sha512-s5Hx+EtN60LMlDBvl5f04bEiFZmAepk27Q+mr85L/00zPDn1jtzlTV6FWn81MaIwqfWzKxmOJrBWHU6vtQyedQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4247,6 +4190,8 @@ }, "node_modules/@rollup/pluginutils": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", + "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", "dev": true, "license": "MIT", "dependencies": { @@ -4268,6 +4213,8 @@ }, "node_modules/@rollup/pluginutils/node_modules/estree-walker": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "dev": true, "license": "MIT" }, @@ -4758,7 +4705,7 @@ } }, "node_modules/@solana/spl-token": { - "version": "0.4.14", + "version": "0.4.13", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -4896,11 +4843,6 @@ "node": ">=18" } }, - "node_modules/@standard-schema/spec": { - "version": "1.0.0", - "license": "MIT", - "peer": true - }, "node_modules/@swc/helpers": { "version": "0.5.17", "dev": true, @@ -4963,16 +4905,6 @@ "@types/node": "*" } }, - "node_modules/@types/chai": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.2.tgz", - "integrity": "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/deep-eql": "*" - } - }, "node_modules/@types/connect": { "version": "3.4.38", "dev": true, @@ -4991,15 +4923,10 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/deep-eql": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", - "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/estree": { "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "dev": true, "license": "MIT" }, @@ -5102,6 +5029,8 @@ }, "node_modules/@types/resolve": { "version": "1.20.2", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", + "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", "dev": true, "license": "MIT" }, @@ -5431,112 +5360,13 @@ "@urql/core": "^5.0.0" } }, - "node_modules/@vitest/coverage-v8": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.2.4.tgz", - "integrity": "sha512-EyF9SXU6kS5Ku/U82E259WSnvg6c8KTjppUncuNdm5QHpe17mwREHnjDzozC8x9MZ0xfBUFSaLkRv4TMA75ALQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.3.0", - "@bcoe/v8-coverage": "^1.0.2", - "ast-v8-to-istanbul": "^0.3.3", - "debug": "^4.4.1", - "istanbul-lib-coverage": "^3.2.2", - "istanbul-lib-report": "^3.0.1", - "istanbul-lib-source-maps": "^5.0.6", - "istanbul-reports": "^3.1.7", - "magic-string": "^0.30.17", - "magicast": "^0.3.5", - "std-env": "^3.9.0", - "test-exclude": "^7.0.1", - "tinyrainbow": "^2.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@vitest/browser": "3.2.4", - "vitest": "3.2.4" - }, - "peerDependenciesMeta": { - "@vitest/browser": { - "optional": true - } - } - }, - "node_modules/@vitest/coverage-v8/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@vitest/coverage-v8/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@vitest/coverage-v8/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@vitest/coverage-v8/node_modules/test-exclude": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", - "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", - "dev": true, - "license": "ISC", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^10.4.1", - "minimatch": "^9.0.4" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/@vitest/expect": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz", - "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==", + "version": "3.1.3", "dev": true, "license": "MIT", "dependencies": { - "@types/chai": "^5.2.2", - "@vitest/spy": "3.2.4", - "@vitest/utils": "3.2.4", + "@vitest/spy": "3.1.3", + "@vitest/utils": "3.1.3", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" }, @@ -5545,13 +5375,11 @@ } }, "node_modules/@vitest/mocker": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz", - "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", + "version": "3.1.3", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.2.4", + "@vitest/spy": "3.1.3", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, @@ -5560,7 +5388,7 @@ }, "peerDependencies": { "msw": "^2.4.9", - "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + "vite": "^5.0.0 || ^6.0.0" }, "peerDependenciesMeta": { "msw": { @@ -5572,9 +5400,7 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz", - "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", + "version": "3.1.3", "dev": true, "license": "MIT", "dependencies": { @@ -5585,28 +5411,23 @@ } }, "node_modules/@vitest/runner": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.4.tgz", - "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==", + "version": "3.1.3", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.2.4", - "pathe": "^2.0.3", - "strip-literal": "^3.0.0" + "@vitest/utils": "3.1.3", + "pathe": "^2.0.3" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/snapshot": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.4.tgz", - "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==", + "version": "3.1.3", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.2.4", + "@vitest/pretty-format": "3.1.3", "magic-string": "^0.30.17", "pathe": "^2.0.3" }, @@ -5615,27 +5436,23 @@ } }, "node_modules/@vitest/spy": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz", - "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==", + "version": "3.1.3", "dev": true, "license": "MIT", "dependencies": { - "tinyspy": "^4.0.3" + "tinyspy": "^3.0.2" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/utils": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz", - "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==", + "version": "3.1.3", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.2.4", - "loupe": "^3.1.4", + "@vitest/pretty-format": "3.1.3", + "loupe": "^3.1.3", "tinyrainbow": "^2.0.0" }, "funding": { @@ -5734,58 +5551,6 @@ "node": ">= 8.0.0" } }, - "node_modules/agents": { - "version": "0.1.4", - "license": "MIT", - "peer": true, - "dependencies": { - "@modelcontextprotocol/sdk": "^1.18.0", - "ai": "5.0.44", - "cron-schedule": "^5.0.4", - "mimetext": "^3.0.27", - "nanoid": "^5.1.5", - "partyserver": "^0.0.74", - "partysocket": "1.1.5", - "zod": "^3.25.76" - }, - "peerDependencies": { - "react": "*" - } - }, - "node_modules/agents/node_modules/nanoid": { - "version": "5.1.5", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "peer": true, - "bin": { - "nanoid": "bin/nanoid.js" - }, - "engines": { - "node": "^18 || >=20" - } - }, - "node_modules/ai": { - "version": "5.0.44", - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "@ai-sdk/gateway": "1.0.23", - "@ai-sdk/provider": "2.0.0", - "@ai-sdk/provider-utils": "3.0.9", - "@opentelemetry/api": "1.9.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "zod": "^3.25.76 || ^4" - } - }, "node_modules/ajv": { "version": "6.12.6", "license": "MIT", @@ -5833,6 +5598,7 @@ "node_modules/ansi-regex": { "version": "5.0.1", "license": "MIT", + "peer": true, "engines": { "node": ">=8" } @@ -6005,33 +5771,12 @@ }, "node_modules/assertion-error": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, "license": "MIT", "engines": { "node": ">=12" } }, - "node_modules/ast-v8-to-istanbul": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.5.tgz", - "integrity": "sha512-9SdXjNheSiE8bALAQCQQuT6fgQaoxJh7IRYrRGZ8/9nv8WhJeC1aXAwN8TbaOssGOukUvyvnkgD9+Yuykvl1aA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.30", - "estree-walker": "^3.0.3", - "js-tokens": "^9.0.1" - } - }, - "node_modules/ast-v8-to-istanbul/node_modules/js-tokens": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", - "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", - "dev": true, - "license": "MIT" - }, "node_modules/async-function": { "version": "1.0.0", "dev": true, @@ -6350,6 +6095,8 @@ }, "node_modules/better-sqlite3": { "version": "12.2.0", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.2.0.tgz", + "integrity": "sha512-eGbYq2CT+tos1fBwLQ/tkBt9J5M3JEHjku4hbvQUePCckkvVf14xWj+1m7dGoK81M/fOjFT7yM9UMeKT/+vFLQ==", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -6396,6 +6143,8 @@ }, "node_modules/bl": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "license": "MIT", "dependencies": { "buffer": "^5.5.0", @@ -6405,6 +6154,8 @@ }, "node_modules/bl/node_modules/buffer": { "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "funding": [ { "type": "github", @@ -6607,8 +6358,6 @@ }, "node_modules/cac": { "version": "6.7.14", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", "dev": true, "license": "MIT", "engines": { @@ -6715,9 +6464,7 @@ "peer": true }, "node_modules/chai": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", - "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", + "version": "5.2.0", "dev": true, "license": "MIT", "dependencies": { @@ -6728,7 +6475,7 @@ "pathval": "^2.0.0" }, "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/chalk": { @@ -6744,8 +6491,6 @@ }, "node_modules/check-error": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", "dev": true, "license": "MIT", "engines": { @@ -6856,6 +6601,8 @@ }, "node_modules/cluster-key-slot": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", + "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", "license": "Apache-2.0", "engines": { "node": ">=0.10.0" @@ -6895,6 +6642,8 @@ }, "node_modules/commondir": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", "dev": true, "license": "MIT" }, @@ -7083,16 +6832,6 @@ "url": "https://opencollective.com/core-js" } }, - "node_modules/core-js-pure": { - "version": "3.45.1", - "hasInstallScript": true, - "license": "MIT", - "peer": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, "node_modules/cors": { "version": "2.8.5", "license": "MIT", @@ -7118,14 +6857,6 @@ "node": ">=4" } }, - "node_modules/cron-schedule": { - "version": "5.0.4", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=18" - } - }, "node_modules/cross-fetch": { "version": "3.2.0", "dev": true, @@ -7271,9 +7002,7 @@ } }, "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "version": "4.4.0", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -7294,6 +7023,8 @@ }, "node_modules/decompress-response": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "license": "MIT", "dependencies": { "mimic-response": "^3.1.0" @@ -7307,8 +7038,6 @@ }, "node_modules/deep-eql": { "version": "5.0.2", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", "dev": true, "license": "MIT", "engines": { @@ -7406,6 +7135,8 @@ }, "node_modules/denque": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", "license": "Apache-2.0", "engines": { "node": ">=0.10" @@ -7437,6 +7168,8 @@ }, "node_modules/detect-libc": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", + "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", "license": "Apache-2.0", "engines": { "node": ">=8" @@ -7500,7 +7233,8 @@ }, "node_modules/eastasianwidth": { "version": "0.2.0", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/ee-first": { "version": "1.1.1", @@ -7513,7 +7247,8 @@ }, "node_modules/emoji-regex": { "version": "8.0.0", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/encodeurl": { "version": "2.0.0", @@ -7524,6 +7259,8 @@ }, "node_modules/end-of-stream": { "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", "license": "MIT", "dependencies": { "once": "^1.4.0" @@ -7647,8 +7384,6 @@ }, "node_modules/es-module-lexer": { "version": "1.7.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", "dev": true, "license": "MIT" }, @@ -8139,8 +7874,6 @@ }, "node_modules/estree-walker": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", "dev": true, "license": "MIT", "dependencies": { @@ -8162,11 +7895,6 @@ "node": ">= 0.6" } }, - "node_modules/event-target-polyfill": { - "version": "0.0.4", - "license": "MIT", - "peer": true - }, "node_modules/event-target-shim": { "version": "5.0.1", "license": "MIT", @@ -8190,7 +7918,7 @@ } }, "node_modules/eventsource-parser": { - "version": "3.0.6", + "version": "3.0.2", "license": "MIT", "engines": { "node": ">=18.0.0" @@ -8203,6 +7931,8 @@ }, "node_modules/expand-template": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", "license": "(MIT OR WTFPL)", "engines": { "node": ">=6" @@ -8639,14 +8369,9 @@ } }, "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "version": "6.4.4", "dev": true, "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, "peerDependencies": { "picomatch": "^3 || ^4" }, @@ -8766,6 +8491,7 @@ "node_modules/foreground-child": { "version": "3.3.1", "license": "ISC", + "peer": true, "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" @@ -8780,6 +8506,7 @@ "node_modules/foreground-child/node_modules/signal-exit": { "version": "4.1.0", "license": "ISC", + "peer": true, "engines": { "node": ">=14" }, @@ -8861,6 +8588,8 @@ }, "node_modules/fs-constants": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", "license": "MIT" }, "node_modules/fs.realpath": { @@ -9007,6 +8736,8 @@ }, "node_modules/github-from-package": { "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", "license": "MIT" }, "node_modules/glob": { @@ -9236,13 +8967,6 @@ "node": ">=18" } }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true, - "license": "MIT" - }, "node_modules/http-errors": { "version": "2.0.0", "license": "MIT", @@ -9409,6 +9133,8 @@ }, "node_modules/ioredis": { "version": "5.7.0", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.7.0.tgz", + "integrity": "sha512-NUcA93i1lukyXU+riqEyPtSEkyFq8tX90uL659J+qpCZ3rEdViB/APC58oAhIh3+bJln2hzdlZbBZsGNrlsR8g==", "license": "MIT", "dependencies": { "@ioredis/commands": "^1.3.0", @@ -9606,6 +9332,7 @@ "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "license": "MIT", + "peer": true, "engines": { "node": ">=8" } @@ -9651,6 +9378,8 @@ }, "node_modules/is-module": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", "dev": true, "license": "MIT" }, @@ -9698,6 +9427,8 @@ }, "node_modules/is-reference": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", + "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9875,6 +9606,7 @@ "node_modules/istanbul-lib-coverage": { "version": "3.2.2", "license": "BSD-3-Clause", + "peer": true, "engines": { "node": ">=8" } @@ -9902,66 +9634,10 @@ "semver": "bin/semver.js" } }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", - "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.23", - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-reports": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", - "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/jackspeak": { "version": "3.4.3", "license": "BlueOak-1.0.0", + "peer": true, "dependencies": { "@isaacs/cliui": "^8.0.2" }, @@ -10297,6 +9973,7 @@ }, "node_modules/js-base64": { "version": "3.7.7", + "dev": true, "license": "BSD-3-Clause" }, "node_modules/js-tokens": { @@ -10439,11 +10116,6 @@ "license": "MIT", "peer": true }, - "node_modules/json-schema": { - "version": "0.4.0", - "license": "(AFL-2.1 OR BSD-3-Clause)", - "peer": true - }, "node_modules/json-schema-traverse": { "version": "0.4.1", "license": "MIT" @@ -10596,10 +10268,14 @@ }, "node_modules/lodash.defaults": { "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", "license": "MIT" }, "node_modules/lodash.isarguments": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==", "license": "MIT" }, "node_modules/lodash.merge": { @@ -10699,9 +10375,7 @@ } }, "node_modules/loupe": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", - "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", + "version": "3.1.3", "dev": true, "license": "MIT" }, @@ -10721,34 +10395,6 @@ "@jridgewell/sourcemap-codec": "^1.5.0" } }, - "node_modules/magicast": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz", - "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.25.4", - "@babel/types": "^7.25.4", - "source-map-js": "^1.2.0" - } - }, - "node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/makeerror": { "version": "1.0.12", "license": "BSD-3-Clause", @@ -11217,40 +10863,6 @@ "node": ">= 0.6" } }, - "node_modules/mimetext": { - "version": "3.0.27", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.26.0", - "@babel/runtime-corejs3": "^7.26.0", - "js-base64": "^3.7.7", - "mime-types": "^2.1.35" - }, - "funding": { - "type": "patreon", - "url": "https://patreon.com/muratgozel" - } - }, - "node_modules/mimetext/node_modules/mime-db": { - "version": "1.52.0", - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimetext/node_modules/mime-types": { - "version": "2.1.35", - "license": "MIT", - "peer": true, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/mimic-fn": { "version": "1.2.0", "license": "MIT", @@ -11261,6 +10873,8 @@ }, "node_modules/mimic-response": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", "license": "MIT", "engines": { "node": ">=10" @@ -11289,6 +10903,7 @@ "node_modules/minipass": { "version": "7.1.2", "license": "ISC", + "peer": true, "engines": { "node": ">=16 || 14 >=14.17" } @@ -11317,6 +10932,8 @@ }, "node_modules/mkdirp-classic": { "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", "license": "MIT" }, "node_modules/ms": { @@ -11351,6 +10968,8 @@ }, "node_modules/napi-build-utils": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", "license": "MIT" }, "node_modules/natural-compare": { @@ -11372,6 +10991,8 @@ }, "node_modules/node-abi": { "version": "3.75.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.75.0.tgz", + "integrity": "sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg==", "license": "MIT", "dependencies": { "semver": "^7.3.5" @@ -11931,7 +11552,8 @@ }, "node_modules/package-json-from-dist": { "version": "1.0.1", - "license": "BlueOak-1.0.0" + "license": "BlueOak-1.0.0", + "peer": true }, "node_modules/parent-module": { "version": "1.0.1", @@ -11993,42 +11615,6 @@ "node": ">= 0.8" } }, - "node_modules/partyserver": { - "version": "0.0.74", - "license": "ISC", - "peer": true, - "dependencies": { - "nanoid": "^5.1.5" - }, - "peerDependencies": { - "@cloudflare/workers-types": "^4.20240729.0" - } - }, - "node_modules/partyserver/node_modules/nanoid": { - "version": "5.1.5", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "peer": true, - "bin": { - "nanoid": "bin/nanoid.js" - }, - "engines": { - "node": "^18 || >=20" - } - }, - "node_modules/partysocket": { - "version": "1.1.5", - "license": "MIT", - "peer": true, - "dependencies": { - "event-target-polyfill": "^0.0.4" - } - }, "node_modules/path-exists": { "version": "4.0.0", "license": "MIT", @@ -12058,6 +11644,7 @@ "node_modules/path-scurry": { "version": "1.11.1", "license": "BlueOak-1.0.0", + "peer": true, "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" @@ -12071,7 +11658,8 @@ }, "node_modules/path-scurry/node_modules/lru-cache": { "version": "10.4.3", - "license": "ISC" + "license": "ISC", + "peer": true }, "node_modules/path-to-regexp": { "version": "8.2.0", @@ -12082,15 +11670,11 @@ }, "node_modules/pathe": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "dev": true, "license": "MIT" }, "node_modules/pathval": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", - "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", + "version": "2.0.0", "dev": true, "license": "MIT", "engines": { @@ -12102,9 +11686,7 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "version": "4.0.2", "dev": true, "license": "MIT", "engines": { @@ -12159,9 +11741,7 @@ } }, "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "version": "8.5.3", "dev": true, "funding": [ { @@ -12179,7 +11759,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.11", + "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -12197,6 +11777,8 @@ }, "node_modules/prebuild-install": { "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", "license": "MIT", "dependencies": { "detect-libc": "^2.0.0", @@ -12300,6 +11882,8 @@ }, "node_modules/pump": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", @@ -12556,6 +12140,8 @@ }, "node_modules/readable-stream": { "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "license": "MIT", "dependencies": { "inherits": "^2.0.3", @@ -12568,6 +12154,8 @@ }, "node_modules/redis-errors": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", "license": "MIT", "engines": { "node": ">=4" @@ -12575,6 +12163,8 @@ }, "node_modules/redis-parser": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", "license": "MIT", "dependencies": { "redis-errors": "^1.0.0" @@ -12815,6 +12405,8 @@ }, "node_modules/rollup": { "version": "4.50.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.50.2.tgz", + "integrity": "sha512-BgLRGy7tNS9H66aIMASq1qSYbAAJV6Z6WR4QYTvj5FgF15rZ/ympT1uixHXwzbZUBDbkvqUI1KR0fH1FhMaQ9w==", "dev": true, "license": "MIT", "dependencies": { @@ -12854,6 +12446,8 @@ }, "node_modules/rollup-plugin-analyzer": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-analyzer/-/rollup-plugin-analyzer-4.0.0.tgz", + "integrity": "sha512-LL9GEt3bkXp6Wa19SNR5MWcvHNMvuTFYg+eYBZN2OIFhSWN+pEJUQXEKu5BsOeABob3x9PDaLKW7w5iOJnsESQ==", "dev": true, "license": "MIT", "engines": { @@ -12862,6 +12456,8 @@ }, "node_modules/rollup-plugin-dts": { "version": "6.2.3", + "resolved": "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-6.2.3.tgz", + "integrity": "sha512-UgnEsfciXSPpASuOelix7m4DrmyQgiaWBnvI0TM4GxuDh5FkqW8E5hu57bCxXB90VvR1WNfLV80yEDN18UogSA==", "dev": true, "license": "LGPL-3.0-only", "dependencies": { @@ -12883,6 +12479,8 @@ }, "node_modules/rollup/node_modules/@rollup/rollup-darwin-arm64": { "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.50.2.tgz", + "integrity": "sha512-OZuTVTpj3CDSIxmPgGH8en/XtirV5nfljHZ3wrNwvgkT5DQLhIKAeuFSiwtbMto6oVexV0k1F1zqURPKf5rI1Q==", "cpu": [ "arm64" ], @@ -13362,6 +12960,8 @@ }, "node_modules/simple-concat": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", "funding": [ { "type": "github", @@ -13380,6 +12980,8 @@ }, "node_modules/simple-get": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", "funding": [ { "type": "github", @@ -13522,6 +13124,8 @@ }, "node_modules/standard-as-callback": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", + "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==", "license": "MIT" }, "node_modules/statuses": { @@ -13571,6 +13175,8 @@ }, "node_modules/string_decoder": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" @@ -13579,6 +13185,7 @@ "node_modules/string-width": { "version": "4.2.3", "license": "MIT", + "peer": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -13592,6 +13199,7 @@ "name": "string-width", "version": "4.2.3", "license": "MIT", + "peer": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -13657,6 +13265,7 @@ "node_modules/strip-ansi": { "version": "6.0.1", "license": "MIT", + "peer": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -13668,6 +13277,7 @@ "name": "strip-ansi", "version": "6.0.1", "license": "MIT", + "peer": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -13690,26 +13300,6 @@ "node": ">=0.10.0" } }, - "node_modules/strip-literal": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.0.0.tgz", - "integrity": "sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==", - "dev": true, - "license": "MIT", - "dependencies": { - "js-tokens": "^9.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/strip-literal/node_modules/js-tokens": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", - "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", - "dev": true, - "license": "MIT" - }, "node_modules/structured-headers": { "version": "0.4.1", "license": "MIT", @@ -13905,6 +13495,8 @@ }, "node_modules/tar-fs": { "version": "2.1.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.3.tgz", + "integrity": "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==", "license": "MIT", "dependencies": { "chownr": "^1.1.1", @@ -13915,10 +13507,14 @@ }, "node_modules/tar-fs/node_modules/chownr": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "license": "ISC" }, "node_modules/tar-stream": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "license": "MIT", "dependencies": { "bl": "^4.0.3", @@ -14050,14 +13646,12 @@ "license": "MIT" }, "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "version": "0.2.13", "dev": true, "license": "MIT", "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" + "fdir": "^6.4.4", + "picomatch": "^4.0.2" }, "engines": { "node": ">=12.0.0" @@ -14067,9 +13661,7 @@ } }, "node_modules/tinypool": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", - "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", + "version": "1.0.2", "dev": true, "license": "MIT", "engines": { @@ -14085,9 +13677,7 @@ } }, "node_modules/tinyspy": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.3.tgz", - "integrity": "sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==", + "version": "3.0.2", "dev": true, "license": "MIT", "engines": { @@ -14188,6 +13778,8 @@ }, "node_modules/tslib": { "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true, "license": "0BSD" }, @@ -14211,6 +13803,8 @@ }, "node_modules/tunnel-agent": { "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", "license": "Apache-2.0", "dependencies": { "safe-buffer": "^5.0.1" @@ -14481,6 +14075,8 @@ }, "node_modules/util-deprecate": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "license": "MIT" }, "node_modules/utils-merge": { @@ -14562,24 +14158,22 @@ } }, "node_modules/vite": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.5.tgz", - "integrity": "sha512-4cKBO9wR75r0BeIWWWId9XK9Lj6La5X846Zw9dFfzMRw38IlTk2iCcUt6hsyiDRcPidc55ZParFYDXi0nXOeLQ==", + "version": "6.3.5", "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.25.0", - "fdir": "^6.5.0", - "picomatch": "^4.0.3", - "postcss": "^8.5.6", - "rollup": "^4.43.0", - "tinyglobby": "^0.2.15" + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" @@ -14588,14 +14182,14 @@ "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": "^20.19.0 || >=22.12.0", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", - "less": "^4.0.0", + "less": "*", "lightningcss": "^1.21.0", - "sass": "^1.70.0", - "sass-embedded": "^1.70.0", - "stylus": ">=0.54.8", - "sugarss": "^5.0.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" @@ -14637,17 +14231,15 @@ } }, "node_modules/vite-node": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz", - "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", + "version": "3.1.3", "dev": true, "license": "MIT", "dependencies": { "cac": "^6.7.14", - "debug": "^4.4.1", + "debug": "^4.4.0", "es-module-lexer": "^1.7.0", "pathe": "^2.0.3", - "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + "vite": "^5.0.0 || ^6.0.0" }, "bin": { "vite-node": "vite-node.mjs" @@ -14660,34 +14252,30 @@ } }, "node_modules/vitest": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.4.tgz", - "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", + "version": "3.1.3", "dev": true, "license": "MIT", "dependencies": { - "@types/chai": "^5.2.2", - "@vitest/expect": "3.2.4", - "@vitest/mocker": "3.2.4", - "@vitest/pretty-format": "^3.2.4", - "@vitest/runner": "3.2.4", - "@vitest/snapshot": "3.2.4", - "@vitest/spy": "3.2.4", - "@vitest/utils": "3.2.4", + "@vitest/expect": "3.1.3", + "@vitest/mocker": "3.1.3", + "@vitest/pretty-format": "^3.1.3", + "@vitest/runner": "3.1.3", + "@vitest/snapshot": "3.1.3", + "@vitest/spy": "3.1.3", + "@vitest/utils": "3.1.3", "chai": "^5.2.0", - "debug": "^4.4.1", + "debug": "^4.4.0", "expect-type": "^1.2.1", "magic-string": "^0.30.17", "pathe": "^2.0.3", - "picomatch": "^4.0.2", "std-env": "^3.9.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", - "tinyglobby": "^0.2.14", - "tinypool": "^1.1.1", + "tinyglobby": "^0.2.13", + "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", - "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", - "vite-node": "3.2.4", + "vite": "^5.0.0 || ^6.0.0", + "vite-node": "3.1.3", "why-is-node-running": "^2.3.0" }, "bin": { @@ -14703,8 +14291,8 @@ "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.2.4", - "@vitest/ui": "3.2.4", + "@vitest/browser": "3.1.3", + "@vitest/ui": "3.1.3", "happy-dom": "*", "jsdom": "*" }, @@ -14985,6 +14573,7 @@ "name": "wrap-ansi", "version": "7.0.0", "license": "MIT", + "peer": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -15000,6 +14589,7 @@ "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { "version": "4.3.0", "license": "MIT", + "peer": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -15169,7 +14759,7 @@ } }, "node_modules/zod": { - "version": "3.25.76", + "version": "3.25.42", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" @@ -15211,11 +14801,11 @@ }, "packages/atxp-base": { "name": "@atxp/base", - "version": "0.4.0", + "version": "0.3.0", "license": "MIT", "dependencies": { - "@atxp/client": "0.4.0", - "@atxp/common": "0.4.0", + "@atxp/client": "0.3.0", + "@atxp/common": "0.3.0", "@base-org/account": "^2.1.0", "bignumber.js": "^9.3.0" }, @@ -15239,10 +14829,10 @@ }, "packages/atxp-client": { "name": "@atxp/client", - "version": "0.4.0", + "version": "0.3.0", "license": "MIT", "dependencies": { - "@atxp/common": "0.4.0", + "@atxp/common": "0.3.0", "@modelcontextprotocol/sdk": "^1.15.0", "bignumber.js": "^9.3.0", "oauth4webapi": "^3.5.0" @@ -15274,32 +14864,9 @@ "viem": "^2.34.0" } }, - "packages/atxp-cloudflare": { - "name": "@atxp/cloudflare", - "version": "0.4.0", - "license": "MIT", - "dependencies": { - "@atxp/common": "0.4.0", - "@atxp/server": "0.4.0" - }, - "devDependencies": { - "@cloudflare/workers-types": "^4.20241022.0", - "@types/node": "^22.13.0", - "@typescript-eslint/eslint-plugin": "^8.38.0", - "@typescript-eslint/parser": "^8.38.0", - "@vitest/coverage-v8": "^3.2.4", - "bignumber.js": "^9.1.2", - "eslint": "^9.32.0", - "typescript": "^5.7.3", - "vitest": "^3.0.9" - }, - "peerDependencies": { - "agents": "^0.1.2" - } - }, "packages/atxp-common": { "name": "@atxp/common", - "version": "0.4.0", + "version": "0.3.0", "license": "MIT", "dependencies": { "bignumber.js": "^9.3.0", @@ -15318,35 +14885,203 @@ "vitest": "^3.0.9" } }, - "packages/atxp-express": { - "name": "@atxp/express", - "version": "0.4.0", + "packages/atxp-common/node_modules/cssstyle": { + "version": "4.6.0", + "dev": true, "license": "MIT", "dependencies": { - "@atxp/server": "0.4.0" + "@asamuzakjp/css-color": "^3.2.0", + "rrweb-cssom": "^0.8.0" }, - "devDependencies": { - "@types/express": "^5.0.0", - "@types/node": "^22.13.0", - "@types/supertest": "^6.0.3", - "@typescript-eslint/eslint-plugin": "^8.38.0", - "@typescript-eslint/parser": "^8.38.0", - "eslint": "^9.32.0", - "express": "^5.0.0", - "supertest": "^7.1.4", - "typescript": "^5.7.3", - "vitest": "^3.0.9" + "engines": { + "node": ">=18" + } + }, + "packages/atxp-common/node_modules/cssstyle/node_modules/rrweb-cssom": { + "version": "0.8.0", + "dev": true, + "license": "MIT" + }, + "packages/atxp-common/node_modules/data-urls": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "packages/atxp-common/node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-encoding": "^3.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "packages/atxp-common/node_modules/http-proxy-agent": { + "version": "7.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "packages/atxp-common/node_modules/jsdom": { + "version": "25.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "cssstyle": "^4.1.0", + "data-urls": "^5.0.0", + "decimal.js": "^10.4.3", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.12", + "parse5": "^7.1.2", + "rrweb-cssom": "^0.7.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^5.0.0", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^2.11.2" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "packages/atxp-common/node_modules/tough-cookie": { + "version": "5.1.2", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^6.1.32" + }, + "engines": { + "node": ">=16" + } + }, + "packages/atxp-common/node_modules/tr46": { + "version": "5.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "packages/atxp-common/node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "packages/atxp-common/node_modules/webidl-conversions": { + "version": "7.0.0", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "packages/atxp-common/node_modules/whatwg-encoding": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "packages/atxp-common/node_modules/whatwg-mimetype": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "packages/atxp-common/node_modules/whatwg-url": { + "version": "14.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "^5.1.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "packages/atxp-common/node_modules/ws": { + "version": "8.18.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" }, "peerDependencies": { - "express": "^5.0.0" + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "packages/atxp-common/node_modules/xml-name-validator": { + "version": "5.0.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" } }, "packages/atxp-redis": { "name": "@atxp/redis", - "version": "0.4.0", + "version": "0.3.0", "license": "MIT", "dependencies": { - "@atxp/common": "0.4.0", + "@atxp/common": "0.3.0", "ioredis": "^5.7.0" }, "devDependencies": { @@ -15360,33 +15095,39 @@ }, "packages/atxp-server": { "name": "@atxp/server", - "version": "0.4.0", + "version": "0.3.0", "license": "MIT", "dependencies": { - "@atxp/common": "0.4.0", + "@atxp/common": "0.3.0", "@modelcontextprotocol/sdk": "^1.15.0", "bignumber.js": "^9.3.0", "oauth4webapi": "^3.5.0" }, "devDependencies": { + "@types/express": "^5.0.0", "@types/node": "^22.13.0", + "@types/supertest": "^6.0.3", "@typescript-eslint/eslint-plugin": "^8.38.0", "@typescript-eslint/parser": "^8.38.0", "eslint": "^9.32.0", + "express": "^5.0.0", "node-mocks-http": "^1.17.2", + "supertest": "^7.1.4", "typescript": "^5.7.3", "vitest": "^3.0.9" }, "peerDependencies": { - "content-type": "^1.0.5" + "content-type": "^1.0.5", + "express": "^5.0.0", + "raw-body": "^3.0.0" } }, "packages/atxp-sqlite": { "name": "@atxp/sqlite", - "version": "0.4.0", + "version": "0.3.0", "license": "MIT", "dependencies": { - "@atxp/common": "0.4.0", + "@atxp/common": "0.3.0", "better-sqlite3": "^12.2.0" }, "devDependencies": { diff --git a/packages/atxp-client/src/atxpAccount.ts b/packages/atxp-client/src/atxpAccount.ts index e37373b6..b2c457a1 100644 --- a/packages/atxp-client/src/atxpAccount.ts +++ b/packages/atxp-client/src/atxpAccount.ts @@ -1,4 +1,4 @@ -import type { Account, PaymentMaker } from './types.js'; +import type { Account, PaymentMaker, SignedPaymentMessage } from './types.js'; import type { FetchLike, Network, Currency } from '@atxp/common' import BigNumber from 'bignumber.js'; @@ -55,6 +55,64 @@ class ATXPHttpPaymentMaker implements PaymentMaker { return json.txHash; } + async createSignedPaymentMessage(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { + // For ATXPAccount, we create a signed payment message via the HTTP endpoint + // This is a placeholder implementation - the actual ATXP server would need + // to provide an endpoint for creating signed messages without submission + const response = await this.fetchFn(`${this.origin}/sign-payment`, { + method: 'POST', + headers: { + 'Authorization': toBasicAuth(this.token), + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + amount: amount.toString(), + currency, + receiver, + memo, + }), + }); + + if (!response.ok) { + const text = await response.text(); + throw new Error(`ATXPAccount: /sign-payment failed: ${response.status} ${response.statusText} ${text}`); + } + + const json = await response.json() as any; + return { + data: json.data || '', + signature: json.signature || '', + from: json.from || '', + to: receiver, + amount, + currency, + network: 'base' as Network, // ATXPAccount uses Base network + }; + } + + async submitPaymentMessage(signedMessage: SignedPaymentMessage): Promise { + // Submit a pre-signed payment message + const response = await this.fetchFn(`${this.origin}/submit-payment`, { + method: 'POST', + headers: { + 'Authorization': toBasicAuth(this.token), + 'Content-Type': 'application/json', + }, + body: JSON.stringify(signedMessage), + }); + + if (!response.ok) { + const text = await response.text(); + throw new Error(`ATXPAccount: /submit-payment failed: ${response.status} ${response.statusText} ${text}`); + } + + const json = await response.json() as { txHash?: string }; + if (!json?.txHash) { + throw new Error('ATXPAccount: /submit-payment did not return txHash'); + } + return json.txHash; + } + async generateJWT(params: { paymentRequestId: string; codeChallenge: string }): Promise { const response = await this.fetchFn(`${this.origin}/sign`, { method: 'POST', diff --git a/packages/atxp-client/src/basePaymentMaker.ts b/packages/atxp-client/src/basePaymentMaker.ts index 962a8bac..ce2818a2 100644 --- a/packages/atxp-client/src/basePaymentMaker.ts +++ b/packages/atxp-client/src/basePaymentMaker.ts @@ -1,6 +1,6 @@ -import type { PaymentMaker, Hex } from './types.js'; +import type { PaymentMaker, Hex, SignedPaymentMessage } from './types.js'; import { InsufficientFundsError as InsufficientFundsErrorClass, PaymentNetworkError as PaymentNetworkErrorClass } from './types.js'; -import { Logger, Currency } from '@atxp/common'; +import { Logger, Currency, Network } from '@atxp/common'; import { ConsoleLogger } from '@atxp/common'; import { Address, @@ -81,7 +81,7 @@ export class BasePaymentMaker implements PaymentMaker { async generateJWT({paymentRequestId, codeChallenge}: {paymentRequestId: string, codeChallenge: string}): Promise { const headerObj = { alg: 'ES256K' }; - + const payloadObj = { sub: this.signingClient.account!.address, iss: 'accounts.atxp.ai', @@ -99,7 +99,7 @@ export class BasePaymentMaker implements PaymentMaker { const messageBytes = typeof Buffer !== 'undefined' ? Buffer.from(message, 'utf8') : new TextEncoder().encode(message); - + const signResult = await this.signingClient.signMessage({ account: this.signingClient.account!, message: { raw: messageBytes }, @@ -116,24 +116,24 @@ export class BasePaymentMaker implements PaymentMaker { return jwt; } - async makePayment(amount: BigNumber, currency: Currency, receiver: string): Promise { + async createSignedPaymentMessage(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { if (currency.toUpperCase() !== 'USDC') { throw new PaymentNetworkErrorClass('Only USDC currency is supported; received ' + currency); } - this.logger.info(`Making payment of ${amount} ${currency} to ${receiver} on Base from ${this.signingClient.account!.address}`); + this.logger.info(`Creating signed payment message for ${amount} ${currency} to ${receiver} on Base from ${this.signingClient.account!.address}`); try { - // Check balance before attempting payment + // Check balance before creating payment message const balanceRaw = await this.signingClient.readContract({ address: USDC_CONTRACT_ADDRESS_BASE as Address, abi: ERC20_ABI, functionName: 'balanceOf', args: [this.signingClient.account!.address], }) as bigint; - + const balance = new BigNumber(balanceRaw.toString()).dividedBy(10 ** USDC_DECIMALS); - + if (balance.lt(amount)) { this.logger.warn(`Insufficient ${currency} balance for payment. Required: ${amount}, Available: ${balance}`); throw new InsufficientFundsErrorClass(currency, amount, balance, 'base'); @@ -141,42 +141,102 @@ export class BasePaymentMaker implements PaymentMaker { // Convert amount to USDC units (6 decimals) as BigInt const amountInUSDCUnits = BigInt(amount.multipliedBy(10 ** USDC_DECIMALS).toFixed(0)); - + const data = encodeFunctionData({ abi: ERC20_ABI, functionName: "transfer", args: [receiver as Address, amountInUSDCUnits], }); + + // Create the transaction message + const transactionMessage = { + chain: base, + account: this.signingClient.account!, + to: USDC_CONTRACT_ADDRESS_BASE as Address, + data: data, + value: parseEther('0'), + maxPriorityFeePerGas: parseEther('0.000000001') + }; + + // Sign the transaction without sending it + const signedTx = await this.signingClient.prepareTransactionRequest(transactionMessage); + const signature = await this.signingClient.signTransaction(signedTx); + + return { + data: data, + signature: signature, + from: this.signingClient.account!.address, + to: receiver, + amount: amount, + currency: currency, + network: 'base' as Network + }; + } catch (error) { + if (error instanceof InsufficientFundsErrorClass || error instanceof PaymentNetworkErrorClass) { + throw error; + } + + // Wrap other errors in PaymentNetworkError + throw new PaymentNetworkErrorClass(`Failed to create signed payment message: ${(error as Error).message}`, error as Error); + } + } + + async submitPaymentMessage(signedMessage: SignedPaymentMessage): Promise { + this.logger.info(`Submitting signed payment message to blockchain`); + + try { + // For now, we'll re-create and send the transaction + // In a full X402 implementation, this would submit the pre-signed transaction + // to the facilitator which would then submit it to the blockchain + const amountInUSDCUnits = BigInt(signedMessage.amount.multipliedBy(10 ** USDC_DECIMALS).toFixed(0)); + const hash = await this.signingClient.sendTransaction({ chain: base, account: this.signingClient.account!, to: USDC_CONTRACT_ADDRESS_BASE, - data: data, + data: signedMessage.data as Hex, value: parseEther('0'), maxPriorityFeePerGas: parseEther('0.000000001') }); - - // Wait for transaction confirmation with more blocks to ensure propagation + + // Wait for transaction confirmation this.logger.info(`Waiting for transaction confirmation: ${hash}`); - const receipt = await this.signingClient.waitForTransactionReceipt({ + const receipt = await this.signingClient.waitForTransactionReceipt({ hash: hash as Hex, confirmations: 1 }); - + if (receipt.status === 'reverted') { throw new PaymentNetworkErrorClass(`Transaction reverted: ${hash}`, new Error('Transaction reverted on chain')); } - + this.logger.info(`Transaction confirmed: ${hash} in block ${receipt.blockNumber}`); - + return hash; } catch (error) { - if (error instanceof InsufficientFundsErrorClass || error instanceof PaymentNetworkErrorClass) { + if (error instanceof PaymentNetworkErrorClass) { throw error; } - + // Wrap other errors in PaymentNetworkError - throw new PaymentNetworkErrorClass(`Payment failed on Base network: ${(error as Error).message}`, error as Error); + throw new PaymentNetworkErrorClass(`Failed to submit payment: ${(error as Error).message}`, error as Error); + } + } + + async makePayment(amount: BigNumber, currency: Currency, receiver: string, memo: string = ''): Promise { + this.logger.info(`Making payment of ${amount} ${currency} to ${receiver} on Base from ${this.signingClient.account!.address}`); + + try { + // Use the new separated methods + const signedMessage = await this.createSignedPaymentMessage(amount, currency, receiver, memo); + + // For standard ATXP flow, immediately submit the signed payment + const hash = await this.submitPaymentMessage(signedMessage); + + return hash; + } catch (error) { + // Error handling is already done in the individual methods + throw error; } } } diff --git a/packages/atxp-client/src/index.ts b/packages/atxp-client/src/index.ts index ff30c7c1..2721bbe1 100644 --- a/packages/atxp-client/src/index.ts +++ b/packages/atxp-client/src/index.ts @@ -57,5 +57,13 @@ export { type ClientConfig, InsufficientFundsError, PaymentNetworkError, - type PaymentMaker + type PaymentMaker, + type SignedPaymentMessage } from './types.js'; + +// X402 support +export { + type X402Config, + wrapWithX402, + enableX402Support +} from './x402Wrapper.js'; diff --git a/packages/atxp-client/src/solanaPaymentMaker.ts b/packages/atxp-client/src/solanaPaymentMaker.ts index f32addc9..b1e57ac3 100644 --- a/packages/atxp-client/src/solanaPaymentMaker.ts +++ b/packages/atxp-client/src/solanaPaymentMaker.ts @@ -1,14 +1,12 @@ -import type { PaymentMaker } from './types.js'; +import type { PaymentMaker, SignedPaymentMessage } from './types.js'; import { InsufficientFundsError, PaymentNetworkError } from './types.js'; -import { Keypair, Connection, PublicKey, ComputeBudgetProgram, sendAndConfirmTransaction } from "@solana/web3.js"; +import { Keypair, Connection, PublicKey, ComputeBudgetProgram, sendAndConfirmTransaction, Transaction } from "@solana/web3.js"; import { createTransfer, ValidateTransferError as _ValidateTransferError } from "@solana/pay"; import { getAccount, getAssociatedTokenAddress } from "@solana/spl-token"; import bs58 from "bs58"; import BigNumber from "bignumber.js"; -import { generateJWT, Currency } from '@atxp/common'; +import { generateJWT, Currency, Network, Logger, ConsoleLogger } from '@atxp/common'; import { importJWK } from 'jose'; -import { Logger } from '@atxp/common'; -import { ConsoleLogger } from '@atxp/common'; // this is a global public key for USDC on the solana mainnet const USDC_MINT = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"); @@ -19,6 +17,7 @@ export class SolanaPaymentMaker implements PaymentMaker { private connection: Connection; private source: Keypair; private logger: Logger; + private lastTransaction: Transaction | null = null; constructor(solanaEndpoint: string, sourceSecretKey: string, logger?: Logger) { if (!solanaEndpoint) { @@ -49,25 +48,24 @@ export class SolanaPaymentMaker implements PaymentMaker { return generateJWT(this.source.publicKey.toBase58(), privateKey, paymentRequestId || '', codeChallenge || ''); } - makePayment = async (amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise => { + async createSignedPaymentMessage(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { if (currency.toUpperCase() !== 'USDC') { throw new PaymentNetworkError('Only USDC currency is supported; received ' + currency); } const receiverKey = new PublicKey(receiver); - - this.logger.info(`Making payment of ${amount} ${currency} to ${receiver} on Solana from ${this.source.publicKey.toBase58()}`); + this.logger.info(`Creating signed payment message for ${amount} ${currency} to ${receiver} on Solana from ${this.source.publicKey.toBase58()}`); try { - // Check balance before attempting payment + // Check balance before creating payment message const tokenAccountAddress = await getAssociatedTokenAddress( USDC_MINT, this.source.publicKey ); - + const tokenAccount = await getAccount(this.connection, tokenAccountAddress); const balance = new BigNumber(tokenAccount.amount.toString()).dividedBy(10 ** 6); // USDC has 6 decimals - + if (balance.lt(amount)) { this.logger.warn(`Insufficient ${currency} balance for payment. Required: ${amount}, Available: ${balance}`); throw new InsufficientFundsError(currency, amount, balance, 'solana'); @@ -76,11 +74,11 @@ export class SolanaPaymentMaker implements PaymentMaker { const modifyComputeUnits = ComputeBudgetProgram.setComputeUnitLimit({ units: 10000, }); - + const addPriorityFee = ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 20000, }); - + const transaction = await createTransfer( this.connection, this.source.publicKey, @@ -91,23 +89,82 @@ export class SolanaPaymentMaker implements PaymentMaker { memo, } ); - + transaction.add(modifyComputeUnits); transaction.add(addPriorityFee); + // Sign the transaction + transaction.sign(this.source); + + // Store the transaction for later submission + this.lastTransaction = transaction; + + // Serialize the transaction for the signature + const signature = bs58.encode(transaction.serialize()); + + return { + data: signature, + signature: signature, + from: this.source.publicKey.toBase58(), + to: receiver, + amount: amount, + currency: currency, + network: 'solana' as Network + }; + } catch (error) { + if (error instanceof InsufficientFundsError || error instanceof PaymentNetworkError) { + throw error; + } + + // Wrap other errors in PaymentNetworkError + throw new PaymentNetworkError(`Failed to create signed payment message: ${(error as Error).message}`, error as Error); + } + } + + async submitPaymentMessage(signedMessage: SignedPaymentMessage): Promise { + this.logger.info(`Submitting signed payment message to Solana blockchain`); + + try { + // For Solana, we need to reconstruct and submit the transaction + // In a full X402 implementation, this would be handled by the facilitator + if (!this.lastTransaction) { + throw new PaymentNetworkError('No transaction to submit. Call createSignedPaymentMessage first.'); + } + const transactionHash = await sendAndConfirmTransaction( this.connection, - transaction, + this.lastTransaction, [this.source], ); + + // Clear the stored transaction + this.lastTransaction = null; + return transactionHash; } catch (error) { - if (error instanceof InsufficientFundsError || error instanceof PaymentNetworkError) { + if (error instanceof PaymentNetworkError) { throw error; } - + // Wrap other errors in PaymentNetworkError - throw new PaymentNetworkError(`Payment failed on Solana network: ${(error as Error).message}`, error as Error); + throw new PaymentNetworkError(`Failed to submit payment: ${(error as Error).message}`, error as Error); + } + } + + makePayment = async (amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise => { + this.logger.info(`Making payment of ${amount} ${currency} to ${receiver} on Solana from ${this.source.publicKey.toBase58()}`); + + try { + // Use the new separated methods + const signedMessage = await this.createSignedPaymentMessage(amount, currency, receiver, memo); + + // For standard ATXP flow, immediately submit the signed payment + const hash = await this.submitPaymentMessage(signedMessage); + + return hash; + } catch (error) { + // Error handling is already done in the individual methods + throw error; } } } diff --git a/packages/atxp-client/src/types.ts b/packages/atxp-client/src/types.ts index 77ce882b..cf39f296 100644 --- a/packages/atxp-client/src/types.ts +++ b/packages/atxp-client/src/types.ts @@ -67,7 +67,19 @@ export class PaymentNetworkError extends Error { } } +export type SignedPaymentMessage = { + data: string; + signature: string; + from: string; + to: string; + amount: BigNumber; + currency: Currency; + network: Network; +} + export interface PaymentMaker { makePayment: (amount: BigNumber, currency: Currency, receiver: string, memo: string) => Promise; + createSignedPaymentMessage: (amount: BigNumber, currency: Currency, receiver: string, memo: string) => Promise; + submitPaymentMessage: (signedMessage: SignedPaymentMessage) => Promise; generateJWT: (params: {paymentRequestId: string, codeChallenge: string}) => Promise; } diff --git a/packages/atxp-client/src/x402Wrapper.ts b/packages/atxp-client/src/x402Wrapper.ts new file mode 100644 index 00000000..da7287bc --- /dev/null +++ b/packages/atxp-client/src/x402Wrapper.ts @@ -0,0 +1,178 @@ +import type { Account, ProspectivePayment } from './types.js'; +import { FetchLike, Logger, ConsoleLogger, Currency, Network } from '@atxp/common'; +import { BigNumber } from 'bignumber.js'; + +export interface X402Config { + account: Account; + approvePayment: (payment: ProspectivePayment) => Promise; + onPayment?: (args: { payment: ProspectivePayment }) => Promise; + onPaymentFailure?: (args: { payment: ProspectivePayment, error: Error }) => Promise; + logger?: Logger; + maxRetries?: number; +} + +interface X402PaymentChallenge { + network: Network; + currency: Currency; + amount: string; + recipient: string; + memo?: string; +} + +export function wrapWithX402(fetchFn: FetchLike, config: X402Config): FetchLike { + const logger = config.logger ?? new ConsoleLogger(); + const maxRetries = config.maxRetries ?? 1; + + return async function x402FetchWrapper(input: RequestInfo | URL, init?: RequestInit): Promise { + let attempt = 0; + + while (attempt <= maxRetries) { + const response = await fetchFn(input, init); + + // Check if this is an X402 payment challenge + if (response.status === 402 && response.headers.has('X-Payment')) { + const paymentHeaderValue = response.headers.get('X-Payment'); + + if (!paymentHeaderValue) { + logger.warn('Received 402 response without X-Payment header'); + return response; + } + + try { + // Parse the X-Payment header to get payment details + const paymentChallenge: X402PaymentChallenge = JSON.parse(paymentHeaderValue); + + const url = typeof input === 'string' ? input : + input instanceof URL ? input.href : + input instanceof Request ? input.url : ''; + + // Find the appropriate payment maker for this network + const paymentMakerKey = `${paymentChallenge.network}:${paymentChallenge.currency}`; + const paymentMaker = config.account.paymentMakers[paymentMakerKey]; + + if (!paymentMaker) { + logger.error(`No payment maker found for ${paymentMakerKey}`); + if (config.onPaymentFailure) { + const payment: ProspectivePayment = { + accountId: config.account.accountId, + resourceUrl: url, + resourceName: url, + network: paymentChallenge.network, + currency: paymentChallenge.currency, + amount: new BigNumber(paymentChallenge.amount), + iss: 'x402-server' + }; + await config.onPaymentFailure({ + payment, + error: new Error(`No payment maker for ${paymentMakerKey}`) + }); + } + return response; + } + + // Create a prospective payment for approval + const payment: ProspectivePayment = { + accountId: config.account.accountId, + resourceUrl: url, + resourceName: url, + network: paymentChallenge.network, + currency: paymentChallenge.currency, + amount: new BigNumber(paymentChallenge.amount), + iss: 'x402-server' + }; + + // Check if the payment should be approved + const approved = await config.approvePayment(payment); + + if (!approved) { + logger.info('Payment not approved by user'); + if (config.onPaymentFailure) { + await config.onPaymentFailure({ + payment, + error: new Error('Payment not approved') + }); + } + return response; + } + + logger.info(`Creating signed payment message for X402 challenge: ${paymentChallenge.amount} ${paymentChallenge.currency}`); + + // Create a signed payment message (but don't submit it to blockchain yet) + const signedMessage = await paymentMaker.createSignedPaymentMessage( + new BigNumber(paymentChallenge.amount), + paymentChallenge.currency, + paymentChallenge.recipient, + paymentChallenge.memo || '' + ); + + // Retry the request with the X-Payment header containing the signed message + const retryInit = { + ...init, + headers: { + ...(init?.headers || {}), + 'X-Payment': JSON.stringify({ + signature: signedMessage.signature, + data: signedMessage.data, + from: signedMessage.from, + to: signedMessage.to, + amount: signedMessage.amount.toString(), + currency: signedMessage.currency, + network: signedMessage.network + }) + } + }; + + logger.info('Retrying request with X-Payment header'); + const retryResponse = await fetchFn(input, retryInit); + + // If the payment was accepted, notify success + if (retryResponse.ok) { + if (config.onPayment) { + await config.onPayment({ payment }); + } + logger.info('X402 payment successful'); + } else if (config.onPaymentFailure) { + await config.onPaymentFailure({ + payment, + error: new Error(`Payment failed with status ${retryResponse.status}`) + }); + } + + return retryResponse; + } catch (error) { + logger.error('Failed to handle X402 payment challenge:', error); + + // If we have a payment failure handler, call it + if (config.onPaymentFailure) { + const payment: ProspectivePayment = { + accountId: config.account.accountId, + resourceUrl: typeof input === 'string' ? input : '', + resourceName: typeof input === 'string' ? input : '', + network: 'base' as Network, // default + currency: 'USDC' as Currency, // default + amount: new BigNumber(0), + iss: 'x402-server' + }; + await config.onPaymentFailure({ payment, error: error as Error }); + } + + return response; + } + } + + // Not a 402 response, return as-is + return response; + } + + // Should never reach here, but return the last response just in case + return await fetchFn(input, init); + }; +} + +export function enableX402Support(config: X402Config): X402Config & { fetchFn: FetchLike } { + const wrappedFetch = wrapWithX402(fetch as FetchLike, config); + return { + ...config, + fetchFn: wrappedFetch + }; +} \ No newline at end of file From 4f5a6a40b26605c979e6beaf33d53010817ffaa6 Mon Sep 17 00:00:00 2001 From: bdj Date: Wed, 17 Sep 2025 10:53:42 -0700 Subject: [PATCH 02/61] Simplify example --- examples/x402-server/.env.example | 21 ++- examples/x402-server/README.md | 218 ++++++++++++++++-------- examples/x402-server/package.json | 1 + examples/x402-server/src/server.ts | 205 +++------------------- examples/x402-server/src/test-client.ts | 103 ++--------- 5 files changed, 205 insertions(+), 343 deletions(-) diff --git a/examples/x402-server/.env.example b/examples/x402-server/.env.example index 39696533..f28520d5 100644 --- a/examples/x402-server/.env.example +++ b/examples/x402-server/.env.example @@ -1,10 +1,25 @@ -# Base network RPC URL +# Coinbase Developer Platform (CDP) API Keys +# Get these from https://portal.cdp.coinbase.com/ +CDP_API_KEY_ID=your_cdp_api_key_id +CDP_API_KEY_SECRET=your_cdp_api_key_secret + +# Network Configuration +# Options: "base" (mainnet) or "base-sepolia" (testnet) +NETWORK=base + +# Your wallet address to receive payments +RECIPIENT_ADDRESS=0xYourWalletAddressHere + +# Base network RPC URL (for the test client) # You can get one from https://www.alchemy.com/ or https://www.infura.io/ BASE_RPC_URL=https://base-mainnet.g.alchemy.com/v2/your-api-key -# Private key for the Base account (without 0x prefix) +# Private key for the Base account (without 0x prefix) - for test client # WARNING: Never commit real private keys to version control BASE_PRIVATE_KEY=your_private_key_here -# Optional: X402 server URL (defaults to http://localhost:3001) +# Optional: Server port (defaults to 3001) +PORT=3001 + +# Optional: X402 server URL for test client (defaults to http://localhost:3001) X402_SERVER_URL=http://localhost:3001 \ No newline at end of file diff --git a/examples/x402-server/README.md b/examples/x402-server/README.md index 4292fa5f..221983c8 100644 --- a/examples/x402-server/README.md +++ b/examples/x402-server/README.md @@ -1,14 +1,27 @@ -# X402 Server Example +# X402 Server Example with Coinbase Facilitator -This example demonstrates how to use ATXP SDK with X402 payment protocol support. +This example demonstrates how to use ATXP SDK with the real Coinbase X402 facilitator for processing USDC payments on Base. ## What is X402? -X402 is a payment protocol that uses HTTP 402 (Payment Required) status codes with payment headers to enable micropayments for web resources. The protocol involves three parties: +X402 is a payment protocol that uses HTTP 402 (Payment Required) status codes with payment headers to enable micropayments for web resources. This example uses the **official Coinbase X402 facilitator** to process real USDC payments on the Base blockchain. -1. **Client** - Makes payments to access resources -2. **Resource Server** - Serves protected content and requires payment -3. **Facilitator** - Verifies and settles payments on the blockchain +## Prerequisites + +### 1. Coinbase Developer Platform (CDP) Account +You need CDP API keys to use the Coinbase facilitator: +1. Go to [https://portal.cdp.coinbase.com/](https://portal.cdp.coinbase.com/) +2. Create an account or sign in +3. Generate API keys (API Key ID and Secret) + +### 2. Base Wallet with USDC +For the test client, you need: +- A wallet on Base network with some USDC +- The wallet's private key (for signing payments) +- An RPC endpoint (from Alchemy, Infura, or similar) + +### 3. Recipient Wallet +A Base wallet address where you want to receive payments (for the server) ## Setup @@ -17,14 +30,28 @@ X402 is a payment protocol that uses HTTP 402 (Payment Required) status codes wi npm install ``` -2. Create a `.env` file based on `.env.example`: +2. Create a `.env` file: ```bash cp .env.example .env ``` 3. Configure your environment variables: - - `BASE_RPC_URL`: Your Base network RPC endpoint - - `BASE_PRIVATE_KEY`: Private key for a Base account with USDC funds + +```env +# CDP API Keys (required for real payments) +CDP_API_KEY_ID=your_cdp_api_key_id +CDP_API_KEY_SECRET=your_cdp_api_key_secret + +# Network: "base" for mainnet or "base-sepolia" for testnet +NETWORK=base + +# Your wallet to receive payments +RECIPIENT_ADDRESS=0xYourWalletAddressHere + +# For the test client +BASE_RPC_URL=https://base-mainnet.g.alchemy.com/v2/your-api-key +BASE_PRIVATE_KEY=your_private_key_here +``` ## Running the Example @@ -34,11 +61,9 @@ cp .env.example .env npm run dev ``` -This starts a mock X402 server on `http://localhost:3001` with the following endpoints: - -- `GET /protected-resource/:id` - Protected resource requiring 1 USDC payment -- `GET /health` - Health check endpoint -- `GET /user/:address/resources` - List resources accessed by a user +The server will start with either: +- **Production Mode**: If CDP API keys are configured (real payments) +- **Demo Mode**: If no CDP API keys (no actual payments) ### Test with the Client @@ -48,93 +73,146 @@ In a separate terminal: npm run test-client ``` -This runs a test client that: -1. Attempts to access a protected resource with regular fetch (fails with 402) -2. Uses X402-wrapped fetch to automatically handle payment and access the resource -3. Accesses multiple resources and tracks them +The test client will: +1. Check server configuration +2. Attempt to access protected resources +3. Handle X402 payment challenges automatically +4. Make real USDC payments on Base +5. Display transaction details ## How It Works -### Server Flow +### Server Flow (with Coinbase Facilitator) 1. Client requests a protected resource -2. Server returns 402 status with `X-Payment` header containing payment requirements -3. Client signs a payment message and retries with `X-Payment` header -4. Server verifies the payment with facilitator -5. Facilitator settles payment on blockchain -6. Server returns the protected resource - -### Client Flow +2. Coinbase middleware returns 402 with payment requirements +3. Client signs and sends payment in X-Payment header +4. Coinbase facilitator: + - Verifies the payment signature + - Checks account balance + - Submits transaction to Base blockchain + - Waits for confirmation +5. Server returns the protected resource -The ATXP SDK provides a `wrapWithX402` function that wraps the standard fetch API: +### Client Flow (ATXP SDK) ```typescript +// Wrap fetch with X402 support const x402Fetch = wrapWithX402(fetch, { - account, + account: baseAccount, approvePayment: async (payment) => { - // Approve or reject payment - return true; + // Approve payments under 10 cents + return payment.amount.lte(new BigNumber('0.10')); }, onPayment: async ({ payment }) => { - // Payment successful - }, - onPaymentFailure: async ({ payment, error }) => { - // Payment failed + console.log('Payment successful:', payment); } }); -// Use like regular fetch -const response = await x402Fetch('http://example.com/protected'); +// Use like regular fetch - payments handled automatically +const response = await x402Fetch('http://localhost:3001/api/protected-resource'); ``` -## Important Notes +## Pricing Structure -⚠️ **This is a mock implementation for demonstration purposes** +The example server has three tiers: -- The facilitator is mocked and doesn't actually verify signatures or submit to blockchain -- In production, use a real X402 facilitator service -- Never commit real private keys to version control -- Always validate payment amounts and recipients on the server side +| Endpoint | Price | Description | +|----------|-------|-------------| +| `/api/protected-resource/:id` | $0.01 | Basic protected content | +| `/api/premium-resource` | $0.10 | Premium features | +| `/api/expensive-resource` | $1.00 | High-value content | -## Architecture +## Testing on Different Networks +### Base Mainnet (Production) +```env +NETWORK=base ``` -┌─────────┐ 402 + Challenge ┌────────────┐ -│ │ ──────────────────────> │ │ -│ Client │ │ Server │ -│ │ <────────────────────── │ │ -└─────────┘ Retry + Payment Msg └────────────┘ - │ │ - │ │ Verify - │ ▼ - │ ┌────────────┐ - │ │Facilitator │ - └─────────────────────────────> │ │ - Submit to Chain └────────────┘ +- Real USDC payments +- Real money involved +- Transactions visible on [BaseScan](https://basescan.org) + +### Base Sepolia (Testnet) +```env +NETWORK=base-sepolia ``` +- Test USDC tokens +- No real money +- Get test USDC from faucets +- Transactions visible on [Base Sepolia Explorer](https://sepolia.basescan.org) -## Supported Networks and Currencies +## Important Security Notes -Currently supports: -- **Base Network**: USDC -- **Solana**: USDC (when using SolanaAccount) +⚠️ **NEVER commit real private keys or API secrets to version control** + +- Use environment variables for sensitive data +- Keep your `.env` file in `.gitignore` +- Use separate wallets for testing +- Start with small amounts when testing on mainnet + +## Cost Breakdown + +When using Base mainnet: +- **Gas fees**: ~$0.001 per transaction (Base has very low fees) +- **Facilitator fee**: 0% (Coinbase doesn't charge fees) +- **Total cost**: Resource price + minimal gas + +## Monitoring Transactions + +View your transactions on: +- **Base Mainnet**: [https://basescan.org](https://basescan.org) +- **Base Sepolia**: [https://sepolia.basescan.org](https://sepolia.basescan.org) + +Search by your wallet address or transaction hash. ## Troubleshooting -### Insufficient Funds Error -Ensure your account has enough USDC on the Base network. +### "CDP API keys not configured" +Set `CDP_API_KEY_ID` and `CDP_API_KEY_SECRET` in your `.env` file. + +### "Insufficient USDC balance" +Ensure your wallet has enough USDC on the correct network. -### Network Errors -Check that your RPC URL is correct and accessible. +### "Transaction failed" +Check: +1. Network configuration matches between client and server +2. Wallet has enough USDC and ETH for gas +3. RPC endpoint is working -### Payment Verification Fails -In production, ensure the facilitator service is properly configured. +### "Payment not approved" +The test client auto-approves payments under $0.10. Adjust the limit in `test-client.ts` if needed. + +## Architecture + +``` +┌─────────┐ 402 Challenge ┌─────────┐ +│ Client │ ─────────────────────> │ Server │ +│ (ATXP) │ │(Express)│ +│ │ <───────────────────── │ + X402 │ +└─────────┘ Retry with Payment └─────────┘ + │ │ + │ ▼ + │ ┌──────────────┐ + │ │ Coinbase │ + │ │ Facilitator │ + │ └──────────────┘ + │ │ + └────────────────────────────────────┘ + Submit to Base Blockchain +``` ## Next Steps -To integrate X402 support in your application: +1. **Customize pricing**: Edit the `pricing` object in `server.ts` +2. **Add more endpoints**: Create new protected routes +3. **Implement business logic**: Add real functionality to protected endpoints +4. **Deploy to production**: Use proper hosting with HTTPS +5. **Monitor usage**: Track payments and API usage + +## Resources -1. Wrap your fetch calls with `wrapWithX402` -2. Implement payment approval logic -3. Handle payment events for user feedback -4. Deploy with a real X402 facilitator service \ No newline at end of file +- [X402 Protocol Specification](https://github.com/coinbase/x402) +- [Coinbase Developer Platform](https://portal.cdp.coinbase.com/) +- [Base Documentation](https://docs.base.org/) +- [ATXP Documentation](https://docs.atxp.ai/) \ No newline at end of file diff --git a/examples/x402-server/package.json b/examples/x402-server/package.json index 2f68d4fd..0a731f1e 100644 --- a/examples/x402-server/package.json +++ b/examples/x402-server/package.json @@ -11,6 +11,7 @@ "dependencies": { "@atxp/client": "workspace:*", "@atxp/common": "workspace:*", + "@coinbase/x402": "^0.3.8", "express": "^4.18.2", "cors": "^2.8.5", "bignumber.js": "^9.1.2", diff --git a/examples/x402-server/src/server.ts b/examples/x402-server/src/server.ts index d7e70abb..14ada8b8 100644 --- a/examples/x402-server/src/server.ts +++ b/examples/x402-server/src/server.ts @@ -1,195 +1,42 @@ import express from 'express'; import cors from 'cors'; -import { BigNumber } from 'bignumber.js'; -import { Network, Currency } from '@atxp/common'; -import type { SignedPaymentMessage } from '@atxp/client'; +import { paymentMiddleware, createFacilitatorConfig } from '@coinbase/x402'; +import dotenv from 'dotenv'; + +dotenv.config(); const app = express(); app.use(cors()); app.use(express.json()); -// Mock facilitator for demonstration -// In production, this would be replaced with an actual X402 facilitator -class MockX402Facilitator { - private processedPayments = new Map(); - - async verify(paymentMessage: SignedPaymentMessage): Promise { - // Mock verification - in production this would: - // 1. Verify the signature - // 2. Check account balance - // 3. Verify the payment details match what was requested - console.log('Facilitator: Verifying payment message:', { - from: paymentMessage.from, - to: paymentMessage.to, - amount: paymentMessage.amount.toString(), - currency: paymentMessage.currency, - network: paymentMessage.network - }); - - // Simple mock validation - if (!paymentMessage.signature || !paymentMessage.data) { - console.log('Facilitator: Invalid payment message - missing signature or data'); - return false; - } - - // Check if payment amount is sufficient (mock check) - const requiredAmount = new BigNumber('1'); // 1 USDC - if (paymentMessage.amount.lt(requiredAmount)) { - console.log(`Facilitator: Insufficient payment amount. Required: ${requiredAmount}, Got: ${paymentMessage.amount}`); - return false; +// Configure facilitator (CDP keys for mainnet, or default for demo) +const facilitator = process.env.CDP_API_KEY_ID && process.env.CDP_API_KEY_SECRET + ? createFacilitatorConfig(process.env.CDP_API_KEY_ID, process.env.CDP_API_KEY_SECRET) + : undefined; + +// Single line to enable X402 payments on endpoints +app.use(paymentMiddleware( + process.env.RECIPIENT_ADDRESS || '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb8', + { + '/api/resource': { + price: '$0.01', + network: process.env.NETWORK || 'base' } + }, + facilitator +)); - return true; - } - - async settle(paymentMessage: SignedPaymentMessage): Promise { - // Mock settlement - in production this would submit to blockchain - console.log('Facilitator: Settling payment on blockchain...'); - - // Generate a mock transaction hash - const mockTxHash = '0x' + Math.random().toString(16).substring(2, 66); - - // Mark as processed to prevent replay - this.processedPayments.set(paymentMessage.signature, true); - - console.log(`Facilitator: Payment settled with tx hash: ${mockTxHash}`); - return mockTxHash; - } - - isPaymentProcessed(signature: string): boolean { - return this.processedPayments.has(signature); - } -} - -const facilitator = new MockX402Facilitator(); - -// Protected resource that requires payment -interface ResourceData { - data: string; - timestamp: number; -} - -// Store for accessed resources (in production, this would be a database) -const accessedResources = new Map>(); - -// Example protected endpoint -app.get('/protected-resource/:id', async (req, res) => { - const resourceId = req.params.id; - const paymentHeader = req.headers['x-payment'] as string | undefined; - - console.log(`\n=== Request for resource: ${resourceId} ===`); - - // Check if payment was provided - if (!paymentHeader) { - console.log('No payment provided, sending 402 challenge'); - - // Send X402 payment challenge - const paymentChallenge = { - network: 'base' as Network, - currency: 'USDC' as Currency, - amount: '1', // 1 USDC - recipient: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb8', // Example recipient address - memo: `Payment for resource ${resourceId}` - }; - - res.status(402) - .header('X-Payment', JSON.stringify(paymentChallenge)) - .json({ - error: 'Payment Required', - message: 'This resource requires payment to access', - payment: paymentChallenge - }); - return; - } - - try { - // Parse the payment message from header - console.log('Payment header received:', paymentHeader); - const paymentMessage: SignedPaymentMessage = JSON.parse(paymentHeader); - - // Check if this payment was already processed - if (facilitator.isPaymentProcessed(paymentMessage.signature)) { - console.log('Payment already processed (replay attempt)'); - res.status(400).json({ - error: 'Payment already processed', - message: 'This payment signature has already been used' - }); - return; - } - - // Verify the payment with facilitator - const isValid = await facilitator.verify(paymentMessage); - - if (!isValid) { - console.log('Payment verification failed'); - res.status(400).json({ - error: 'Invalid payment', - message: 'The payment could not be verified' - }); - return; - } - - // Settle the payment - const txHash = await facilitator.settle(paymentMessage); - - // Grant access to the resource - const userAddress = paymentMessage.from; - if (!accessedResources.has(userAddress)) { - accessedResources.set(userAddress, new Set()); - } - accessedResources.get(userAddress)!.add(resourceId); - - console.log(`Access granted to ${userAddress} for resource ${resourceId}`); - - // Return the protected resource - const resource: ResourceData = { - data: `This is protected content for resource ${resourceId}. Thank you for your payment!`, - timestamp: Date.now() - }; - - res.json({ - success: true, - transactionHash: txHash, - resource - }); - - } catch (error) { - console.error('Error processing payment:', error); - res.status(500).json({ - error: 'Payment processing failed', - message: (error as Error).message - }); - } -}); - -// Health check endpoint -app.get('/health', (req, res) => { - res.json({ status: 'ok', facilitator: 'mock' }); -}); - -// List accessed resources for a user -app.get('/user/:address/resources', (req, res) => { - const userAddress = req.params.address; - const resources = accessedResources.get(userAddress); - +// Protected endpoint - X402 middleware handles payment automatically +app.get('/api/resource', (req, res) => { res.json({ - address: userAddress, - resources: resources ? Array.from(resources) : [] + success: true, + data: 'This is protected content that costs $0.01 USDC', + timestamp: Date.now() }); }); const PORT = process.env.PORT || 3001; - app.listen(PORT, () => { - console.log(`X402 Example Server running on http://localhost:${PORT}`); - console.log('\nAvailable endpoints:'); - console.log(` GET /protected-resource/:id - Protected resource requiring X402 payment`); - console.log(` GET /health - Health check`); - console.log(` GET /user/:address/resources - List resources accessed by a user`); - console.log('\nPayment details:'); - console.log(' Network: Base'); - console.log(' Currency: USDC'); - console.log(' Amount: 1 USDC per resource'); - console.log('\nNote: This is a mock implementation for demonstration purposes.'); - console.log('In production, use a real X402 facilitator for payment verification and settlement.'); + console.log(`X402 Server running on http://localhost:${PORT}`); + console.log(`Protected endpoint: GET /api/resource ($0.01 USDC)`); }); \ No newline at end of file diff --git a/examples/x402-server/src/test-client.ts b/examples/x402-server/src/test-client.ts index 2b8cfbe8..cce2c525 100644 --- a/examples/x402-server/src/test-client.ts +++ b/examples/x402-server/src/test-client.ts @@ -1,113 +1,34 @@ -import { wrapWithX402, BaseAccount, type ProspectivePayment } from '@atxp/client'; -import { ConsoleLogger } from '@atxp/common'; -import { BigNumber } from 'bignumber.js'; +import { wrapWithX402, BaseAccount } from '@atxp/client'; import dotenv from 'dotenv'; dotenv.config(); async function testX402Client() { - const logger = new ConsoleLogger(); - // Check for required environment variables if (!process.env.BASE_RPC_URL || !process.env.BASE_PRIVATE_KEY) { - console.error('Missing required environment variables: BASE_RPC_URL and BASE_PRIVATE_KEY'); - console.error('Please create a .env file with:'); - console.error('BASE_RPC_URL=your_base_rpc_url'); - console.error('BASE_PRIVATE_KEY=your_private_key'); + console.error('Missing BASE_RPC_URL and BASE_PRIVATE_KEY'); process.exit(1); } - console.log('=== X402 Client Test ===\n'); - - // Create a Base account + // Create account const account = new BaseAccount( process.env.BASE_RPC_URL, process.env.BASE_PRIVATE_KEY ); - console.log('Account address:', await account.getAddress()); - - // Create X402-wrapped fetch - const x402Fetch = wrapWithX402(fetch as any, { - account, - approvePayment: async (payment: ProspectivePayment) => { - console.log('\n--- Payment Approval Request ---'); - console.log(`Resource: ${payment.resourceUrl}`); - console.log(`Amount: ${payment.amount} ${payment.currency}`); - console.log(`Network: ${payment.network}`); - - // Auto-approve for testing (in production, prompt user) - const approved = true; - console.log(`Approved: ${approved}`); - console.log('-------------------------------\n'); - - return approved; - }, - onPayment: async ({ payment }) => { - console.log(`✅ Payment successful for ${payment.amount} ${payment.currency}`); - }, - onPaymentFailure: async ({ payment, error }) => { - console.error(`❌ Payment failed for ${payment.amount} ${payment.currency}:`, error.message); - }, - logger, - maxRetries: 1 - }); + // Wrap fetch with X402 support + const x402Fetch = wrapWithX402(fetch as any, account); + // Make a single request to the protected endpoint const serverUrl = process.env.X402_SERVER_URL || 'http://localhost:3001'; + const response = await x402Fetch(`${serverUrl}/api/resource`); - try { - // First, check server health - console.log(`\nChecking server health at ${serverUrl}...`); - const healthResponse = await fetch(`${serverUrl}/health`); - const health = await healthResponse.json(); - console.log('Server health:', health); - - // Try to access a protected resource without payment (should fail with regular fetch) - console.log('\n1. Attempting to access protected resource with regular fetch...'); - const regularResponse = await fetch(`${serverUrl}/protected-resource/123`); - console.log(`Response status: ${regularResponse.status} ${regularResponse.statusText}`); - - if (regularResponse.status === 402) { - const errorData = await regularResponse.json(); - console.log('Received 402 Payment Required:', errorData.message); - } - - // Now try with X402-enabled fetch - console.log('\n2. Attempting to access protected resource with X402-enabled fetch...'); - const x402Response = await x402Fetch(`${serverUrl}/protected-resource/123`); - console.log(`Response status: ${x402Response.status} ${x402Response.statusText}`); - - if (x402Response.ok) { - const data = await x402Response.json(); - console.log('\n🎉 Successfully accessed protected resource!'); - console.log('Transaction hash:', data.transactionHash); - console.log('Resource data:', data.resource); - } else { - const errorData = await x402Response.json(); - console.log('Failed to access resource:', errorData); - } - - // Try to access another resource - console.log('\n3. Accessing a second protected resource...'); - const secondResponse = await x402Fetch(`${serverUrl}/protected-resource/456`); - - if (secondResponse.ok) { - const data = await secondResponse.json(); - console.log('\n🎉 Successfully accessed second resource!'); - console.log('Resource data:', data.resource); - } - - // Check what resources we've accessed - const userAddress = await account.getAddress(); - console.log(`\n4. Checking accessed resources for ${userAddress}...`); - const resourcesResponse = await fetch(`${serverUrl}/user/${userAddress}/resources`); - const resourcesData = await resourcesResponse.json(); - console.log('Accessed resources:', resourcesData.resources); - - } catch (error) { - console.error('Test failed:', error); + if (response.ok) { + const data = await response.json(); + console.log('Success:', data); + } else { + console.error('Failed:', response.status, response.statusText); } } -// Run the test testX402Client().catch(console.error); \ No newline at end of file From 3bed43576f45ab0257bdd928489dee4c8175d776 Mon Sep 17 00:00:00 2001 From: bdj Date: Wed, 17 Sep 2025 10:57:30 -0700 Subject: [PATCH 03/61] Simplify wrapper method; remove PaymentMaker.makePayment --- docs/atxp-account-x402-spec.md | 168 +++++++++++++ examples/x402-server/.env.example | 15 +- examples/x402-server/README.md | 238 +++++------------- examples/x402-server/src/server.ts | 18 +- packages/atxp-client/src/atxpAccount.ts | 25 -- packages/atxp-client/src/basePaymentMaker.ts | 65 ++--- packages/atxp-client/src/index.ts | 4 +- .../atxp-client/src/solanaPaymentMaker.ts | 49 +--- packages/atxp-client/src/types.ts | 1 - packages/atxp-client/src/x402Wrapper.ts | 216 ++++------------ 10 files changed, 347 insertions(+), 452 deletions(-) create mode 100644 docs/atxp-account-x402-spec.md diff --git a/docs/atxp-account-x402-spec.md b/docs/atxp-account-x402-spec.md new file mode 100644 index 00000000..dfcbbbb1 --- /dev/null +++ b/docs/atxp-account-x402-spec.md @@ -0,0 +1,168 @@ +# ATXPAccount X402 API Specification + +## Overview + +This specification defines the API changes needed for the ATXP Account service to support X402 payment protocol. The changes enable signing payment messages without immediate blockchain submission, which is required for X402's facilitator-based settlement model. + +## Background + +X402 requires clients to: +1. Sign a payment message locally +2. Send the signed message to the resource server +3. Let the facilitator verify and submit to blockchain + +The current `/pay` endpoint signs and submits in one step. We need to separate these operations. + +## New API Endpoints + +### 1. `/sign-payment` - Create Signed Payment Message + +**Method:** POST +**Authentication:** Basic Auth (connection token) + +**Request Body:** +```json +{ + "amount": "1.00", // String decimal amount + "currency": "USDC", // Currency code + "receiver": "0x...", // Recipient address + "memo": "Payment for..." // Optional memo +} +``` + +**Response (200 OK):** +```json +{ + "data": "0x...", // Encoded transaction data + "signature": "0x...", // Signed transaction + "from": "0x...", // Sender address + "nonce": 123, // Transaction nonce + "gasPrice": "1000000000" // Gas price in wei +} +``` + +**Error Responses:** +- 400: Invalid parameters +- 401: Unauthorized +- 500: Signing failed + +### 2. `/submit-payment` - Submit Pre-signed Payment + +**Method:** POST +**Authentication:** Basic Auth (connection token) + +**Request Body:** +```json +{ + "signature": "0x...", // Signed transaction from /sign-payment + "data": "0x...", // Transaction data + "from": "0x...", // Must match account address + "to": "0x...", // Recipient + "amount": "1.00", // For validation + "currency": "USDC", // For validation + "network": "base" // Network identifier +} +``` + +**Response (200 OK):** +```json +{ + "txHash": "0x..." // Transaction hash +} +``` + +**Error Responses:** +- 400: Invalid signature or parameters +- 401: Unauthorized +- 409: Transaction already submitted +- 500: Submission failed + +## Implementation Notes + +### Signing Without Submission + +The `/sign-payment` endpoint should: +1. Validate the account has sufficient balance +2. Build the transaction (data, gas, nonce) +3. Sign the transaction locally +4. Return the signed transaction WITHOUT broadcasting + +### Nonce Management + +- Track pending nonces to prevent conflicts +- Increment nonce for each signed transaction +- Reset nonce tracking after submission or timeout + +### Security Considerations + +1. **Replay Protection:** Track submitted signatures to prevent replay +2. **Timeout:** Signed transactions should expire after 5 minutes +3. **Rate Limiting:** Limit signing requests per account +4. **Balance Check:** Always verify balance before signing + +## Backwards Compatibility + +The existing `/pay` endpoint remains unchanged and continues to sign+submit atomically. It can be implemented as: +``` +/pay = /sign-payment + /submit-payment +``` + +## Migration Path + +1. Deploy new endpoints alongside existing `/pay` +2. Update SDK to use new endpoints when X402 is detected +3. Monitor usage and deprecate `/pay` in future version + +## Example Usage Flow + +```typescript +// 1. Client requests signing +POST /sign-payment +{ + "amount": "0.01", + "currency": "USDC", + "receiver": "0x123...", + "memo": "X402 payment" +} + +// 2. Server returns signed message +{ + "signature": "0xabc...", + "data": "0xdef...", + "from": "0x456..." +} + +// 3. Client sends to X402 server +// (X402 facilitator verifies and settles) + +// 4. Optional: Client can also submit directly +POST /submit-payment +{ + "signature": "0xabc...", + // ... rest of signed message +} +``` + +## Testing Requirements + +1. Test signing without submission +2. Verify nonce increments correctly +3. Test replay protection +4. Verify timeout enforcement +5. Test concurrent signing requests +6. Validate balance checks + +## Performance Targets + +- `/sign-payment`: < 100ms +- `/submit-payment`: < 2s (includes blockchain confirmation) +- Support 100 concurrent signing operations per account + +## Monitoring + +Track: +- Signing success/failure rates +- Submission success/failure rates +- Expired signatures count +- Replay attempt count +- Average signing latency \ No newline at end of file diff --git a/examples/x402-server/.env.example b/examples/x402-server/.env.example index f28520d5..a1cd4c6e 100644 --- a/examples/x402-server/.env.example +++ b/examples/x402-server/.env.example @@ -1,11 +1,12 @@ -# Coinbase Developer Platform (CDP) API Keys -# Get these from https://portal.cdp.coinbase.com/ -CDP_API_KEY_ID=your_cdp_api_key_id -CDP_API_KEY_SECRET=your_cdp_api_key_secret - # Network Configuration -# Options: "base" (mainnet) or "base-sepolia" (testnet) -NETWORK=base +# Options: "base" (mainnet - requires CDP keys) or "base-sepolia" (testnet - no keys needed!) +NETWORK=base-sepolia + +# Coinbase Developer Platform (CDP) API Keys (ONLY needed for mainnet) +# Get these from https://portal.cdp.coinbase.com/ +# Leave empty to use the public test facilitator on Base Sepolia +CDP_API_KEY_ID= +CDP_API_KEY_SECRET= # Your wallet address to receive payments RECIPIENT_ADDRESS=0xYourWalletAddressHere diff --git a/examples/x402-server/README.md b/examples/x402-server/README.md index 221983c8..b4e8d4e2 100644 --- a/examples/x402-server/README.md +++ b/examples/x402-server/README.md @@ -1,218 +1,108 @@ -# X402 Server Example with Coinbase Facilitator +# X402 Server Example -This example demonstrates how to use ATXP SDK with the real Coinbase X402 facilitator for processing USDC payments on Base. +This example demonstrates X402 payment protocol with ATXP SDK. You can test it immediately using the **public test facilitator** - no API keys required! -## What is X402? +## Quick Start (Testnet - No API Keys!) -X402 is a payment protocol that uses HTTP 402 (Payment Required) status codes with payment headers to enable micropayments for web resources. This example uses the **official Coinbase X402 facilitator** to process real USDC payments on the Base blockchain. - -## Prerequisites - -### 1. Coinbase Developer Platform (CDP) Account -You need CDP API keys to use the Coinbase facilitator: -1. Go to [https://portal.cdp.coinbase.com/](https://portal.cdp.coinbase.com/) -2. Create an account or sign in -3. Generate API keys (API Key ID and Secret) - -### 2. Base Wallet with USDC -For the test client, you need: -- A wallet on Base network with some USDC -- The wallet's private key (for signing payments) -- An RPC endpoint (from Alchemy, Infura, or similar) - -### 3. Recipient Wallet -A Base wallet address where you want to receive payments (for the server) - -## Setup - -1. Install dependencies: +### 1. Install and Configure ```bash npm install -``` - -2. Create a `.env` file: -```bash cp .env.example .env +# Edit .env - set your RECIPIENT_ADDRESS ``` -3. Configure your environment variables: - -```env -# CDP API Keys (required for real payments) -CDP_API_KEY_ID=your_cdp_api_key_id -CDP_API_KEY_SECRET=your_cdp_api_key_secret - -# Network: "base" for mainnet or "base-sepolia" for testnet -NETWORK=base - -# Your wallet to receive payments -RECIPIENT_ADDRESS=0xYourWalletAddressHere - -# For the test client -BASE_RPC_URL=https://base-mainnet.g.alchemy.com/v2/your-api-key -BASE_PRIVATE_KEY=your_private_key_here -``` - -## Running the Example - -### Start the X402 Server +### 2. Get Test USDC +Get free test USDC on Base Sepolia from: +- [Circle USDC Faucet](https://faucet.circle.com/) (recommended) +- Or any Base Sepolia faucet for ETH +### 3. Run Server ```bash npm run dev ``` -The server will start with either: -- **Production Mode**: If CDP API keys are configured (real payments) -- **Demo Mode**: If no CDP API keys (no actual payments) - -### Test with the Client - -In a separate terminal: +The server automatically uses the **public test facilitator** at `https://x402.org/facilitator` - no login or API keys needed! +### 4. Test Client ```bash +# In another terminal npm run test-client ``` -The test client will: -1. Check server configuration -2. Attempt to access protected resources -3. Handle X402 payment challenges automatically -4. Make real USDC payments on Base -5. Display transaction details - -## How It Works - -### Server Flow (with Coinbase Facilitator) - -1. Client requests a protected resource -2. Coinbase middleware returns 402 with payment requirements -3. Client signs and sends payment in X-Payment header -4. Coinbase facilitator: - - Verifies the payment signature - - Checks account balance - - Submits transaction to Base blockchain - - Waits for confirmation -5. Server returns the protected resource - -### Client Flow (ATXP SDK) - -```typescript -// Wrap fetch with X402 support -const x402Fetch = wrapWithX402(fetch, { - account: baseAccount, - approvePayment: async (payment) => { - // Approve payments under 10 cents - return payment.amount.lte(new BigNumber('0.10')); - }, - onPayment: async ({ payment }) => { - console.log('Payment successful:', payment); - } -}); - -// Use like regular fetch - payments handled automatically -const response = await x402Fetch('http://localhost:3001/api/protected-resource'); -``` - -## Pricing Structure +## Configuration Options -The example server has three tiers: - -| Endpoint | Price | Description | -|----------|-------|-------------| -| `/api/protected-resource/:id` | $0.01 | Basic protected content | -| `/api/premium-resource` | $0.10 | Premium features | -| `/api/expensive-resource` | $1.00 | High-value content | - -## Testing on Different Networks - -### Base Mainnet (Production) +### Testnet Mode (Default - No API Keys!) ```env -NETWORK=base +NETWORK=base-sepolia +RECIPIENT_ADDRESS=0xYourWalletAddress +# No CDP keys needed! Uses public facilitator ``` -- Real USDC payments -- Real money involved -- Transactions visible on [BaseScan](https://basescan.org) -### Base Sepolia (Testnet) +### Production Mode (Real Money) ```env -NETWORK=base-sepolia +NETWORK=base +CDP_API_KEY_ID=your_key_id # Get from cdp.coinbase.com +CDP_API_KEY_SECRET=your_key_secret # Get from cdp.coinbase.com +RECIPIENT_ADDRESS=0xYourWalletAddress ``` -- Test USDC tokens -- No real money -- Get test USDC from faucets -- Transactions visible on [Base Sepolia Explorer](https://sepolia.basescan.org) - -## Important Security Notes -⚠️ **NEVER commit real private keys or API secrets to version control** +## How It Works -- Use environment variables for sensitive data -- Keep your `.env` file in `.gitignore` -- Use separate wallets for testing -- Start with small amounts when testing on mainnet +1. Server uses X402 middleware to protect endpoints +2. Client requests protected resource +3. Server returns 402 Payment Required +4. Client signs payment and retries +5. Facilitator verifies and settles on blockchain +6. Server returns protected resource -## Cost Breakdown +## Facilitator Options -When using Base mainnet: -- **Gas fees**: ~$0.001 per transaction (Base has very low fees) -- **Facilitator fee**: 0% (Coinbase doesn't charge fees) -- **Total cost**: Resource price + minimal gas +| Mode | Network | Facilitator | API Keys | Real Money | +|------|---------|------------|----------|------------| +| **Test** (default) | Base Sepolia | `https://x402.org/facilitator` | ❌ None | ❌ Test USDC | +| Production | Base Mainnet | Coinbase CDP | ✅ Required | ✅ Real USDC | -## Monitoring Transactions +## Server Code -View your transactions on: -- **Base Mainnet**: [https://basescan.org](https://basescan.org) -- **Base Sepolia**: [https://sepolia.basescan.org](https://sepolia.basescan.org) +The entire X402 integration is just one middleware line: -Search by your wallet address or transaction hash. +```typescript +app.use(paymentMiddleware( + recipientAddress, + { '/api/resource': { price: '$0.01', network: 'base-sepolia' } }, + { url: 'https://x402.org/facilitator' } // Public test facilitator +)); +``` -## Troubleshooting +## Client Code -### "CDP API keys not configured" -Set `CDP_API_KEY_ID` and `CDP_API_KEY_SECRET` in your `.env` file. +The ATXP SDK handles X402 automatically: -### "Insufficient USDC balance" -Ensure your wallet has enough USDC on the correct network. +```typescript +const x402Fetch = wrapWithX402(fetch, account); +const response = await x402Fetch('http://localhost:3001/api/resource'); +``` -### "Transaction failed" -Check: -1. Network configuration matches between client and server -2. Wallet has enough USDC and ETH for gas -3. RPC endpoint is working +## Cost Structure -### "Payment not approved" -The test client auto-approves payments under $0.10. Adjust the limit in `test-client.ts` if needed. +- **Testnet**: Free (test USDC) +- **Mainnet**: Resource price + ~$0.001 gas (Base has very low fees) -## Architecture +## Troubleshooting -``` -┌─────────┐ 402 Challenge ┌─────────┐ -│ Client │ ─────────────────────> │ Server │ -│ (ATXP) │ │(Express)│ -│ │ <───────────────────── │ + X402 │ -└─────────┘ Retry with Payment └─────────┘ - │ │ - │ ▼ - │ ┌──────────────┐ - │ │ Coinbase │ - │ │ Facilitator │ - │ └──────────────┘ - │ │ - └────────────────────────────────────┘ - Submit to Base Blockchain -``` +### "No payment maker found" +Ensure your account is configured for the correct network (base-sepolia for testnet). -## Next Steps +### "Insufficient balance" +Get test USDC from the Circle faucet for Base Sepolia. -1. **Customize pricing**: Edit the `pricing` object in `server.ts` -2. **Add more endpoints**: Create new protected routes -3. **Implement business logic**: Add real functionality to protected endpoints -4. **Deploy to production**: Use proper hosting with HTTPS -5. **Monitor usage**: Track payments and API usage +### View Transactions +- **Testnet**: [Base Sepolia Explorer](https://sepolia.basescan.org) +- **Mainnet**: [BaseScan](https://basescan.org) ## Resources -- [X402 Protocol Specification](https://github.com/coinbase/x402) -- [Coinbase Developer Platform](https://portal.cdp.coinbase.com/) -- [Base Documentation](https://docs.base.org/) +- [X402 Protocol](https://github.com/coinbase/x402) +- [Circle USDC Faucet](https://faucet.circle.com/) +- [Base Sepolia Info](https://docs.base.org/network-information) - [ATXP Documentation](https://docs.atxp.ai/) \ No newline at end of file diff --git a/examples/x402-server/src/server.ts b/examples/x402-server/src/server.ts index 14ada8b8..8d97af0b 100644 --- a/examples/x402-server/src/server.ts +++ b/examples/x402-server/src/server.ts @@ -9,10 +9,10 @@ const app = express(); app.use(cors()); app.use(express.json()); -// Configure facilitator (CDP keys for mainnet, or default for demo) +// Configure facilitator const facilitator = process.env.CDP_API_KEY_ID && process.env.CDP_API_KEY_SECRET - ? createFacilitatorConfig(process.env.CDP_API_KEY_ID, process.env.CDP_API_KEY_SECRET) - : undefined; + ? createFacilitatorConfig(process.env.CDP_API_KEY_ID, process.env.CDP_API_KEY_SECRET) // Production (mainnet) + : { url: 'https://x402.org/facilitator' }; // Public test facilitator (Base Sepolia) // Single line to enable X402 payments on endpoints app.use(paymentMiddleware( @@ -20,7 +20,7 @@ app.use(paymentMiddleware( { '/api/resource': { price: '$0.01', - network: process.env.NETWORK || 'base' + network: process.env.NETWORK || 'base-sepolia' // Default to testnet } }, facilitator @@ -37,6 +37,16 @@ app.get('/api/resource', (req, res) => { const PORT = process.env.PORT || 3001; app.listen(PORT, () => { + const network = process.env.NETWORK || 'base-sepolia'; + const isTestnet = network === 'base-sepolia'; + console.log(`X402 Server running on http://localhost:${PORT}`); + console.log(`Network: ${network} (${isTestnet ? 'TESTNET - using test USDC' : 'MAINNET - real money!'})`); + console.log(`Facilitator: ${isTestnet ? 'https://x402.org/facilitator (public)' : 'Coinbase CDP (requires API keys)'}`); console.log(`Protected endpoint: GET /api/resource ($0.01 USDC)`); + + if (isTestnet) { + console.log('\n✅ Using public test facilitator - no API keys needed!'); + console.log('Get test USDC from Circle faucet for Base Sepolia to test payments.'); + } }); \ No newline at end of file diff --git a/packages/atxp-client/src/atxpAccount.ts b/packages/atxp-client/src/atxpAccount.ts index b2c457a1..c833646f 100644 --- a/packages/atxp-client/src/atxpAccount.ts +++ b/packages/atxp-client/src/atxpAccount.ts @@ -29,31 +29,6 @@ class ATXPHttpPaymentMaker implements PaymentMaker { this.fetchFn = fetchFn; } - async makePayment(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { - const body = { - amount: amount.toString(), - currency, - receiver, - memo, - }; - const response = await this.fetchFn(`${this.origin}/pay`, { - method: 'POST', - headers: { - 'Authorization': toBasicAuth(this.token), - 'Content-Type': 'application/json', - }, - body: JSON.stringify(body), - }); - if (!response.ok) { - const text = await response.text(); - throw new Error(`ATXPAccount: /pay failed: ${response.status} ${response.statusText} ${text}`); - } - const json = await response.json() as { txHash?: string }; - if (!json?.txHash) { - throw new Error('ATXPAccount: /pay did not return txHash'); - } - return json.txHash; - } async createSignedPaymentMessage(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { // For ATXPAccount, we create a signed payment message via the HTTP endpoint diff --git a/packages/atxp-client/src/basePaymentMaker.ts b/packages/atxp-client/src/basePaymentMaker.ts index ce2818a2..4ed1fb2f 100644 --- a/packages/atxp-client/src/basePaymentMaker.ts +++ b/packages/atxp-client/src/basePaymentMaker.ts @@ -20,7 +20,7 @@ type ExtendedWalletClient = WalletClient & PublicActions; // Helper function to convert to base64url that works in both Node.js and browsers function toBase64Url(data: string): string { // Convert string to base64 - const base64 = typeof Buffer !== 'undefined' + const base64 = typeof Buffer !== 'undefined' ? Buffer.from(data).toString('base64') : btoa(data); // Convert base64 to base64url @@ -63,6 +63,7 @@ const ERC20_ABI = [ export class BasePaymentMaker implements PaymentMaker { protected signingClient: ExtendedWalletClient; protected logger: Logger; + private lastSignedTransaction: string | null = null; constructor(baseRPCUrl: string, walletClient: WalletClient, logger?: Logger) { if (!baseRPCUrl) { @@ -148,23 +149,25 @@ export class BasePaymentMaker implements PaymentMaker { args: [receiver as Address, amountInUSDCUnits], }); - // Create the transaction message - const transactionMessage = { + // Prepare and sign the transaction + const preparedTx = await this.signingClient.prepareTransactionRequest({ chain: base, account: this.signingClient.account!, - to: USDC_CONTRACT_ADDRESS_BASE as Address, + to: USDC_CONTRACT_ADDRESS_BASE, data: data, value: parseEther('0'), maxPriorityFeePerGas: parseEther('0.000000001') - }; + }); - // Sign the transaction without sending it - const signedTx = await this.signingClient.prepareTransactionRequest(transactionMessage); - const signature = await this.signingClient.signTransaction(signedTx); + // Sign the transaction but don't send it + const signedTx = await this.signingClient.signTransaction(preparedTx); + + // Store for potential later submission + this.lastSignedTransaction = signedTx; return { data: data, - signature: signature, + signature: signedTx, // The actual signed transaction from: this.signingClient.account!.address, to: receiver, amount: amount, @@ -182,21 +185,19 @@ export class BasePaymentMaker implements PaymentMaker { } async submitPaymentMessage(signedMessage: SignedPaymentMessage): Promise { - this.logger.info(`Submitting signed payment message to blockchain`); + this.logger.info(`Submitting payment to blockchain`); try { - // For now, we'll re-create and send the transaction - // In a full X402 implementation, this would submit the pre-signed transaction - // to the facilitator which would then submit it to the blockchain - const amountInUSDCUnits = BigInt(signedMessage.amount.multipliedBy(10 ** USDC_DECIMALS).toFixed(0)); + // Use the signed transaction from the message or the stored one + const signedTx = signedMessage.signature || this.lastSignedTransaction; - const hash = await this.signingClient.sendTransaction({ - chain: base, - account: this.signingClient.account!, - to: USDC_CONTRACT_ADDRESS_BASE, - data: signedMessage.data as Hex, - value: parseEther('0'), - maxPriorityFeePerGas: parseEther('0.000000001') + if (!signedTx) { + throw new PaymentNetworkErrorClass('No signed transaction available'); + } + + // Send the pre-signed transaction + const hash = await this.signingClient.sendRawTransaction({ + serializedTransaction: signedTx as Hex }); // Wait for transaction confirmation @@ -212,6 +213,9 @@ export class BasePaymentMaker implements PaymentMaker { this.logger.info(`Transaction confirmed: ${hash} in block ${receipt.blockNumber}`); + // Clear the stored transaction + this.lastSignedTransaction = null; + return hash; } catch (error) { if (error instanceof PaymentNetworkErrorClass) { @@ -222,21 +226,4 @@ export class BasePaymentMaker implements PaymentMaker { throw new PaymentNetworkErrorClass(`Failed to submit payment: ${(error as Error).message}`, error as Error); } } - - async makePayment(amount: BigNumber, currency: Currency, receiver: string, memo: string = ''): Promise { - this.logger.info(`Making payment of ${amount} ${currency} to ${receiver} on Base from ${this.signingClient.account!.address}`); - - try { - // Use the new separated methods - const signedMessage = await this.createSignedPaymentMessage(amount, currency, receiver, memo); - - // For standard ATXP flow, immediately submit the signed payment - const hash = await this.submitPaymentMessage(signedMessage); - - return hash; - } catch (error) { - // Error handling is already done in the individual methods - throw error; - } - } -} +} \ No newline at end of file diff --git a/packages/atxp-client/src/index.ts b/packages/atxp-client/src/index.ts index 2721bbe1..9b71b67f 100644 --- a/packages/atxp-client/src/index.ts +++ b/packages/atxp-client/src/index.ts @@ -63,7 +63,5 @@ export { // X402 support export { - type X402Config, - wrapWithX402, - enableX402Support + wrapWithX402 } from './x402Wrapper.js'; diff --git a/packages/atxp-client/src/solanaPaymentMaker.ts b/packages/atxp-client/src/solanaPaymentMaker.ts index b1e57ac3..dd7cb4b7 100644 --- a/packages/atxp-client/src/solanaPaymentMaker.ts +++ b/packages/atxp-client/src/solanaPaymentMaker.ts @@ -17,7 +17,7 @@ export class SolanaPaymentMaker implements PaymentMaker { private connection: Connection; private source: Keypair; private logger: Logger; - private lastTransaction: Transaction | null = null; + private preparedTransaction: Transaction | null = null; constructor(solanaEndpoint: string, sourceSecretKey: string, logger?: Logger) { if (!solanaEndpoint) { @@ -30,9 +30,9 @@ export class SolanaPaymentMaker implements PaymentMaker { this.source = Keypair.fromSecretKey(bs58.decode(sourceSecretKey)); this.logger = logger ?? new ConsoleLogger(); } - + generateJWT = async({paymentRequestId, codeChallenge}: {paymentRequestId: string, codeChallenge: string}): Promise => { - // Solana/Web3.js secretKey is 64 bytes: + // Solana/Web3.js secretKey is 64 bytes: // first 32 bytes are the private scalar, last 32 are the public key. // JWK expects only the 32-byte private scalar for 'd' const jwk = { @@ -93,18 +93,14 @@ export class SolanaPaymentMaker implements PaymentMaker { transaction.add(modifyComputeUnits); transaction.add(addPriorityFee); - // Sign the transaction - transaction.sign(this.source); - // Store the transaction for later submission - this.lastTransaction = transaction; - - // Serialize the transaction for the signature - const signature = bs58.encode(transaction.serialize()); + this.preparedTransaction = transaction; + // For X402, return a simplified structure + // The actual signing happens when submitted return { - data: signature, - signature: signature, + data: bs58.encode(transaction.serialize({ requireAllSignatures: false })), + signature: '', // Will be signed by facilitator from: this.source.publicKey.toBase58(), to: receiver, amount: amount, @@ -122,23 +118,21 @@ export class SolanaPaymentMaker implements PaymentMaker { } async submitPaymentMessage(signedMessage: SignedPaymentMessage): Promise { - this.logger.info(`Submitting signed payment message to Solana blockchain`); + this.logger.info(`Submitting payment to Solana blockchain`); try { - // For Solana, we need to reconstruct and submit the transaction - // In a full X402 implementation, this would be handled by the facilitator - if (!this.lastTransaction) { + if (!this.preparedTransaction) { throw new PaymentNetworkError('No transaction to submit. Call createSignedPaymentMessage first.'); } const transactionHash = await sendAndConfirmTransaction( this.connection, - this.lastTransaction, + this.preparedTransaction, [this.source], ); // Clear the stored transaction - this.lastTransaction = null; + this.preparedTransaction = null; return transactionHash; } catch (error) { @@ -150,21 +144,4 @@ export class SolanaPaymentMaker implements PaymentMaker { throw new PaymentNetworkError(`Failed to submit payment: ${(error as Error).message}`, error as Error); } } - - makePayment = async (amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise => { - this.logger.info(`Making payment of ${amount} ${currency} to ${receiver} on Solana from ${this.source.publicKey.toBase58()}`); - - try { - // Use the new separated methods - const signedMessage = await this.createSignedPaymentMessage(amount, currency, receiver, memo); - - // For standard ATXP flow, immediately submit the signed payment - const hash = await this.submitPaymentMessage(signedMessage); - - return hash; - } catch (error) { - // Error handling is already done in the individual methods - throw error; - } - } -} +} \ No newline at end of file diff --git a/packages/atxp-client/src/types.ts b/packages/atxp-client/src/types.ts index cf39f296..6b0ee95e 100644 --- a/packages/atxp-client/src/types.ts +++ b/packages/atxp-client/src/types.ts @@ -78,7 +78,6 @@ export type SignedPaymentMessage = { } export interface PaymentMaker { - makePayment: (amount: BigNumber, currency: Currency, receiver: string, memo: string) => Promise; createSignedPaymentMessage: (amount: BigNumber, currency: Currency, receiver: string, memo: string) => Promise; submitPaymentMessage: (signedMessage: SignedPaymentMessage) => Promise; generateJWT: (params: {paymentRequestId: string, codeChallenge: string}) => Promise; diff --git a/packages/atxp-client/src/x402Wrapper.ts b/packages/atxp-client/src/x402Wrapper.ts index da7287bc..2c0e6028 100644 --- a/packages/atxp-client/src/x402Wrapper.ts +++ b/packages/atxp-client/src/x402Wrapper.ts @@ -1,178 +1,68 @@ -import type { Account, ProspectivePayment } from './types.js'; -import { FetchLike, Logger, ConsoleLogger, Currency, Network } from '@atxp/common'; +import type { Account } from './types.js'; +import { FetchLike } from '@atxp/common'; import { BigNumber } from 'bignumber.js'; -export interface X402Config { - account: Account; - approvePayment: (payment: ProspectivePayment) => Promise; - onPayment?: (args: { payment: ProspectivePayment }) => Promise; - onPaymentFailure?: (args: { payment: ProspectivePayment, error: Error }) => Promise; - logger?: Logger; - maxRetries?: number; -} - -interface X402PaymentChallenge { - network: Network; - currency: Currency; - amount: string; - recipient: string; - memo?: string; -} - -export function wrapWithX402(fetchFn: FetchLike, config: X402Config): FetchLike { - const logger = config.logger ?? new ConsoleLogger(); - const maxRetries = config.maxRetries ?? 1; - +export function wrapWithX402(fetchFn: FetchLike, account: Account): FetchLike { return async function x402FetchWrapper(input: RequestInfo | URL, init?: RequestInit): Promise { - let attempt = 0; - - while (attempt <= maxRetries) { - const response = await fetchFn(input, init); - - // Check if this is an X402 payment challenge - if (response.status === 402 && response.headers.has('X-Payment')) { - const paymentHeaderValue = response.headers.get('X-Payment'); - - if (!paymentHeaderValue) { - logger.warn('Received 402 response without X-Payment header'); - return response; - } - - try { - // Parse the X-Payment header to get payment details - const paymentChallenge: X402PaymentChallenge = JSON.parse(paymentHeaderValue); - - const url = typeof input === 'string' ? input : - input instanceof URL ? input.href : - input instanceof Request ? input.url : ''; - - // Find the appropriate payment maker for this network - const paymentMakerKey = `${paymentChallenge.network}:${paymentChallenge.currency}`; - const paymentMaker = config.account.paymentMakers[paymentMakerKey]; - - if (!paymentMaker) { - logger.error(`No payment maker found for ${paymentMakerKey}`); - if (config.onPaymentFailure) { - const payment: ProspectivePayment = { - accountId: config.account.accountId, - resourceUrl: url, - resourceName: url, - network: paymentChallenge.network, - currency: paymentChallenge.currency, - amount: new BigNumber(paymentChallenge.amount), - iss: 'x402-server' - }; - await config.onPaymentFailure({ - payment, - error: new Error(`No payment maker for ${paymentMakerKey}`) - }); - } - return response; - } - - // Create a prospective payment for approval - const payment: ProspectivePayment = { - accountId: config.account.accountId, - resourceUrl: url, - resourceName: url, - network: paymentChallenge.network, - currency: paymentChallenge.currency, - amount: new BigNumber(paymentChallenge.amount), - iss: 'x402-server' - }; + const response = await fetchFn(input, init); - // Check if the payment should be approved - const approved = await config.approvePayment(payment); + // Check if this is an X402 payment challenge + if (response.status === 402) { + const paymentHeader = response.headers.get('X-Payment-Required'); - if (!approved) { - logger.info('Payment not approved by user'); - if (config.onPaymentFailure) { - await config.onPaymentFailure({ - payment, - error: new Error('Payment not approved') - }); - } - return response; - } - - logger.info(`Creating signed payment message for X402 challenge: ${paymentChallenge.amount} ${paymentChallenge.currency}`); - - // Create a signed payment message (but don't submit it to blockchain yet) - const signedMessage = await paymentMaker.createSignedPaymentMessage( - new BigNumber(paymentChallenge.amount), - paymentChallenge.currency, - paymentChallenge.recipient, - paymentChallenge.memo || '' - ); - - // Retry the request with the X-Payment header containing the signed message - const retryInit = { - ...init, - headers: { - ...(init?.headers || {}), - 'X-Payment': JSON.stringify({ - signature: signedMessage.signature, - data: signedMessage.data, - from: signedMessage.from, - to: signedMessage.to, - amount: signedMessage.amount.toString(), - currency: signedMessage.currency, - network: signedMessage.network - }) - } - }; + if (!paymentHeader) { + // Not an X402 response, return as-is + return response; + } - logger.info('Retrying request with X-Payment header'); - const retryResponse = await fetchFn(input, retryInit); + try { + // Parse the X402 payment requirements + const paymentChallenge = JSON.parse(paymentHeader); + const { network, currency, amount, recipient, memo } = paymentChallenge; - // If the payment was accepted, notify success - if (retryResponse.ok) { - if (config.onPayment) { - await config.onPayment({ payment }); - } - logger.info('X402 payment successful'); - } else if (config.onPaymentFailure) { - await config.onPaymentFailure({ - payment, - error: new Error(`Payment failed with status ${retryResponse.status}`) - }); - } + // Find the appropriate payment maker + const paymentMakerKey = `${network}:${currency}`; + const paymentMaker = account.paymentMakers[paymentMakerKey]; - return retryResponse; - } catch (error) { - logger.error('Failed to handle X402 payment challenge:', error); + if (!paymentMaker) { + throw new Error(`No payment maker found for ${paymentMakerKey}`); + } - // If we have a payment failure handler, call it - if (config.onPaymentFailure) { - const payment: ProspectivePayment = { - accountId: config.account.accountId, - resourceUrl: typeof input === 'string' ? input : '', - resourceName: typeof input === 'string' ? input : '', - network: 'base' as Network, // default - currency: 'USDC' as Currency, // default - amount: new BigNumber(0), - iss: 'x402-server' - }; - await config.onPaymentFailure({ payment, error: error as Error }); + // Create a signed payment message + const signedMessage = await paymentMaker.createSignedPaymentMessage( + new BigNumber(amount), + currency, + recipient, + memo || '' + ); + + // Retry the request with the payment + const retryInit = { + ...init, + headers: { + ...(init?.headers || {}), + 'X-Payment': JSON.stringify({ + signature: signedMessage.signature, + data: signedMessage.data, + from: signedMessage.from, + to: signedMessage.to, + amount: signedMessage.amount.toString(), + currency: signedMessage.currency, + network: signedMessage.network + }) } - - return response; - } + }; + + // Retry the request + return await fetchFn(input, retryInit); + } catch (error) { + // If there's an error processing the payment, return the original 402 response + console.error('Failed to handle X402 payment challenge:', error); + return response; } - - // Not a 402 response, return as-is - return response; } - // Should never reach here, but return the last response just in case - return await fetchFn(input, init); - }; -} - -export function enableX402Support(config: X402Config): X402Config & { fetchFn: FetchLike } { - const wrappedFetch = wrapWithX402(fetch as FetchLike, config); - return { - ...config, - fetchFn: wrappedFetch + // Not a 402 response, return as-is + return response; }; } \ No newline at end of file From 5c2b3f8e330950d0d6ed5393b4b9cc2f4ab0ed54 Mon Sep 17 00:00:00 2001 From: bdj Date: Wed, 17 Sep 2025 11:02:43 -0700 Subject: [PATCH 04/61] Update Solana PaymentMaker with signing logic --- .../atxp-client/src/solanaPaymentMaker.ts | 37 ++++++++++++------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/packages/atxp-client/src/solanaPaymentMaker.ts b/packages/atxp-client/src/solanaPaymentMaker.ts index dd7cb4b7..23781303 100644 --- a/packages/atxp-client/src/solanaPaymentMaker.ts +++ b/packages/atxp-client/src/solanaPaymentMaker.ts @@ -17,7 +17,7 @@ export class SolanaPaymentMaker implements PaymentMaker { private connection: Connection; private source: Keypair; private logger: Logger; - private preparedTransaction: Transaction | null = null; + private lastSignedTransaction: string | null = null; constructor(solanaEndpoint: string, sourceSecretKey: string, logger?: Logger) { if (!solanaEndpoint) { @@ -93,14 +93,18 @@ export class SolanaPaymentMaker implements PaymentMaker { transaction.add(modifyComputeUnits); transaction.add(addPriorityFee); - // Store the transaction for later submission - this.preparedTransaction = transaction; + // Sign the transaction + transaction.sign(this.source); + + // Serialize the signed transaction + const signedTx = bs58.encode(transaction.serialize()); + + // Store for potential later submission + this.lastSignedTransaction = signedTx; - // For X402, return a simplified structure - // The actual signing happens when submitted return { data: bs58.encode(transaction.serialize({ requireAllSignatures: false })), - signature: '', // Will be signed by facilitator + signature: signedTx, // The actual signed transaction from: this.source.publicKey.toBase58(), to: receiver, amount: amount, @@ -121,18 +125,25 @@ export class SolanaPaymentMaker implements PaymentMaker { this.logger.info(`Submitting payment to Solana blockchain`); try { - if (!this.preparedTransaction) { - throw new PaymentNetworkError('No transaction to submit. Call createSignedPaymentMessage first.'); + // Use the signed transaction from the message or the stored one + const signedTx = signedMessage.signature || this.lastSignedTransaction; + + if (!signedTx) { + throw new PaymentNetworkError('No signed transaction available'); } - const transactionHash = await sendAndConfirmTransaction( - this.connection, - this.preparedTransaction, - [this.source], + // Deserialize and send the signed transaction + const transaction = Transaction.from(bs58.decode(signedTx)); + + const transactionHash = await this.connection.sendRawTransaction( + transaction.serialize() ); + // Wait for confirmation + await this.connection.confirmTransaction(transactionHash, 'confirmed'); + // Clear the stored transaction - this.preparedTransaction = null; + this.lastSignedTransaction = null; return transactionHash; } catch (error) { From fceeca315818905770e8cafcd4946a18b2835300 Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 10:27:01 -0700 Subject: [PATCH 05/61] Simplify: just add a new signing method --- packages/atxp-client/src/atxpAccount.ts | 49 ++-- packages/atxp-client/src/basePaymentMaker.ts | 267 +++++++----------- .../atxp-client/src/solanaPaymentMaker.ts | 70 ++--- packages/atxp-client/src/types.ts | 30 +- packages/atxp-client/src/x402Wrapper.ts | 17 +- 5 files changed, 166 insertions(+), 267 deletions(-) diff --git a/packages/atxp-client/src/atxpAccount.ts b/packages/atxp-client/src/atxpAccount.ts index c833646f..4408f13d 100644 --- a/packages/atxp-client/src/atxpAccount.ts +++ b/packages/atxp-client/src/atxpAccount.ts @@ -1,4 +1,4 @@ -import type { Account, PaymentMaker, SignedPaymentMessage } from './types.js'; +import type { Account, PaymentMaker, EIP3009Message } from './types.js'; import type { FetchLike, Network, Currency } from '@atxp/common' import BigNumber from 'bignumber.js'; @@ -30,11 +30,9 @@ class ATXPHttpPaymentMaker implements PaymentMaker { } - async createSignedPaymentMessage(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { - // For ATXPAccount, we create a signed payment message via the HTTP endpoint - // This is a placeholder implementation - the actual ATXP server would need - // to provide an endpoint for creating signed messages without submission - const response = await this.fetchFn(`${this.origin}/sign-payment`, { + async makePayment(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { + // Make a regular payment via the /pay endpoint + const response = await this.fetchFn(`${this.origin}/pay`, { method: 'POST', headers: { 'Authorization': toBasicAuth(this.token), @@ -50,42 +48,39 @@ class ATXPHttpPaymentMaker implements PaymentMaker { if (!response.ok) { const text = await response.text(); - throw new Error(`ATXPAccount: /sign-payment failed: ${response.status} ${response.statusText} ${text}`); + throw new Error(`ATXPAccount: /pay failed: ${response.status} ${response.statusText} ${text}`); } - const json = await response.json() as any; - return { - data: json.data || '', - signature: json.signature || '', - from: json.from || '', - to: receiver, - amount, - currency, - network: 'base' as Network, // ATXPAccount uses Base network - }; + const json = await response.json() as { txHash?: string }; + if (!json?.txHash) { + throw new Error('ATXPAccount: /pay did not return txHash'); + } + return json.txHash; } - async submitPaymentMessage(signedMessage: SignedPaymentMessage): Promise { - // Submit a pre-signed payment message - const response = await this.fetchFn(`${this.origin}/submit-payment`, { + async createPaymentAuthorization(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { + // Create an EIP-3009 payment authorization via the HTTP endpoint + const response = await this.fetchFn(`${this.origin}/create-payment-authorization`, { method: 'POST', headers: { 'Authorization': toBasicAuth(this.token), 'Content-Type': 'application/json', }, - body: JSON.stringify(signedMessage), + body: JSON.stringify({ + amount: amount.toString(), + currency, + receiver, + memo, + }), }); if (!response.ok) { const text = await response.text(); - throw new Error(`ATXPAccount: /submit-payment failed: ${response.status} ${response.statusText} ${text}`); + throw new Error(`ATXPAccount: /create-payment-authorization failed: ${response.status} ${response.statusText} ${text}`); } - const json = await response.json() as { txHash?: string }; - if (!json?.txHash) { - throw new Error('ATXPAccount: /submit-payment did not return txHash'); - } - return json.txHash; + // Return the EIP-3009 payment authorization from the accounts service + return await response.json() as EIP3009Message; } async generateJWT(params: { paymentRequestId: string; codeChallenge: string }): Promise { diff --git a/packages/atxp-client/src/basePaymentMaker.ts b/packages/atxp-client/src/basePaymentMaker.ts index 4ed1fb2f..e6aa22b7 100644 --- a/packages/atxp-client/src/basePaymentMaker.ts +++ b/packages/atxp-client/src/basePaymentMaker.ts @@ -1,21 +1,8 @@ -import type { PaymentMaker, Hex, SignedPaymentMessage } from './types.js'; +import type { PaymentMaker, EIP3009Message } from './types.js'; import { InsufficientFundsError as InsufficientFundsErrorClass, PaymentNetworkError as PaymentNetworkErrorClass } from './types.js'; -import { Logger, Currency, Network } from '@atxp/common'; +import { Logger, Currency } from '@atxp/common'; import { ConsoleLogger } from '@atxp/common'; -import { - Address, - parseEther, - publicActions, - encodeFunctionData, - WalletClient, - PublicActions, -} from "viem"; -import { base } from "viem/chains"; import { BigNumber } from "bignumber.js"; -import { USDC_CONTRACT_ADDRESS_BASE } from './baseConstants.js'; - -// Type for the extended wallet client with public actions -type ExtendedWalletClient = WalletClient & PublicActions; // Helper function to convert to base64url that works in both Node.js and browsers function toBase64Url(data: string): string { @@ -27,203 +14,155 @@ function toBase64Url(data: string): string { return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, ''); } -const USDC_DECIMALS = 6; -const ERC20_ABI = [ - { - constant: false, - inputs: [ - { name: "_to", type: "address" }, - { name: "_value", type: "uint256" }, - ], - name: "transfer", - outputs: [{ name: "", type: "bool" }], - type: "function", - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "name": "balance", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - } -]; - export class BasePaymentMaker implements PaymentMaker { - protected signingClient: ExtendedWalletClient; protected logger: Logger; - private lastSignedTransaction: string | null = null; + private accountsServiceUrl: string; + private authToken: string; - constructor(baseRPCUrl: string, walletClient: WalletClient, logger?: Logger) { - if (!baseRPCUrl) { - throw new Error('baseRPCUrl was empty'); + constructor(accountsServiceUrl: string, authToken: string, logger?: Logger) { + if (!accountsServiceUrl) { + throw new Error('accountsServiceUrl was empty'); } - if (!walletClient) { - throw new Error('walletClient was empty'); - } - if(!walletClient.account) { - throw new Error('walletClient.account was empty'); + if (!authToken) { + throw new Error('authToken was empty'); } - this.signingClient = walletClient.extend(publicActions) as ExtendedWalletClient; + this.accountsServiceUrl = accountsServiceUrl.replace(/\/$/, ''); // Remove trailing slash + this.authToken = authToken; this.logger = logger ?? new ConsoleLogger(); } async generateJWT({paymentRequestId, codeChallenge}: {paymentRequestId: string, codeChallenge: string}): Promise { - const headerObj = { alg: 'ES256K' }; - - const payloadObj = { - sub: this.signingClient.account!.address, - iss: 'accounts.atxp.ai', - aud: 'https://auth.atxp.ai', - iat: Math.floor(Date.now() / 1000), - exp: Math.floor(Date.now() / 1000) + 60 * 60, - ...(codeChallenge ? { code_challenge: codeChallenge } : {}), - ...(paymentRequestId ? { payment_request_id: paymentRequestId } : {}), - } as Record; - - const header = toBase64Url(JSON.stringify(headerObj)); - const payload = toBase64Url(JSON.stringify(payloadObj)); - const message = `${header}.${payload}`; - - const messageBytes = typeof Buffer !== 'undefined' - ? Buffer.from(message, 'utf8') - : new TextEncoder().encode(message); - - const signResult = await this.signingClient.signMessage({ - account: this.signingClient.account!, - message: { raw: messageBytes }, + // Call the accounts service /sign endpoint to generate JWT + const response = await fetch(`${this.accountsServiceUrl}/sign`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${this.authToken}` + }, + body: JSON.stringify({ + paymentRequestId, + codeChallenge + }) }); - // For ES256K, signature is typically 65 bytes (r,s,v) - // Server expects the hex signature string (with 0x prefix) to be base64url encoded - // This creates: base64url("0x6eb2565...") not base64url(rawBytes) - // Pass the hex string directly to toBase64Url which will UTF-8 encode and base64url it - const signature = toBase64Url(signResult); + if (!response.ok) { + const error = await response.text(); + throw new PaymentNetworkErrorClass(`Failed to generate JWT: ${error}`); + } - const jwt = `${header}.${payload}.${signature}`; - this.logger.info(`Generated ES256K JWT: ${jwt}`); + const { jwt } = await response.json(); + this.logger.info(`Generated JWT from accounts service`); return jwt; } - async createSignedPaymentMessage(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { + async makePayment(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { if (currency.toUpperCase() !== 'USDC') { throw new PaymentNetworkErrorClass('Only USDC currency is supported; received ' + currency); } - this.logger.info(`Creating signed payment message for ${amount} ${currency} to ${receiver} on Base from ${this.signingClient.account!.address}`); + this.logger.info(`Making payment of ${amount} ${currency} to ${receiver}`); try { - // Check balance before creating payment message - const balanceRaw = await this.signingClient.readContract({ - address: USDC_CONTRACT_ADDRESS_BASE as Address, - abi: ERC20_ABI, - functionName: 'balanceOf', - args: [this.signingClient.account!.address], - }) as bigint; - - const balance = new BigNumber(balanceRaw.toString()).dividedBy(10 ** USDC_DECIMALS); - - if (balance.lt(amount)) { - this.logger.warn(`Insufficient ${currency} balance for payment. Required: ${amount}, Available: ${balance}`); - throw new InsufficientFundsErrorClass(currency, amount, balance, 'base'); - } + // Call the accounts service /pay endpoint for regular payments + const response = await fetch(`${this.accountsServiceUrl}/pay`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${this.authToken}` + }, + body: JSON.stringify({ + amount: amount.toString(), + currency: currency.toUpperCase(), + receiver, + memo + }) + }); - // Convert amount to USDC units (6 decimals) as BigInt - const amountInUSDCUnits = BigInt(amount.multipliedBy(10 ** USDC_DECIMALS).toFixed(0)); + if (!response.ok) { + const error = await response.json().catch(() => ({ error: response.statusText })); - const data = encodeFunctionData({ - abi: ERC20_ABI, - functionName: "transfer", - args: [receiver as Address, amountInUSDCUnits], - }); + // Check for insufficient funds error + if (response.status === 400 && error.error?.includes('Insufficient balance')) { + // Try to parse available balance from error response + const match = error.error.match(/Available: ([\d.]+)/); + const available = match ? new BigNumber(match[1]) : new BigNumber(0); + throw new InsufficientFundsErrorClass(currency, amount, available, 'base'); + } - // Prepare and sign the transaction - const preparedTx = await this.signingClient.prepareTransactionRequest({ - chain: base, - account: this.signingClient.account!, - to: USDC_CONTRACT_ADDRESS_BASE, - data: data, - value: parseEther('0'), - maxPriorityFeePerGas: parseEther('0.000000001') - }); + throw new PaymentNetworkErrorClass( + `Failed to make payment: ${error.error || response.statusText}` + ); + } + + const { txHash } = await response.json(); + this.logger.info(`Payment completed: ${txHash}`); - // Sign the transaction but don't send it - const signedTx = await this.signingClient.signTransaction(preparedTx); - - // Store for potential later submission - this.lastSignedTransaction = signedTx; - - return { - data: data, - signature: signedTx, // The actual signed transaction - from: this.signingClient.account!.address, - to: receiver, - amount: amount, - currency: currency, - network: 'base' as Network - }; + return txHash; } catch (error) { if (error instanceof InsufficientFundsErrorClass || error instanceof PaymentNetworkErrorClass) { throw error; } // Wrap other errors in PaymentNetworkError - throw new PaymentNetworkErrorClass(`Failed to create signed payment message: ${(error as Error).message}`, error as Error); + throw new PaymentNetworkErrorClass( + `Failed to make payment: ${(error as Error).message}`, + error as Error + ); } } - async submitPaymentMessage(signedMessage: SignedPaymentMessage): Promise { - this.logger.info(`Submitting payment to blockchain`); - - try { - // Use the signed transaction from the message or the stored one - const signedTx = signedMessage.signature || this.lastSignedTransaction; + async createPaymentAuthorization(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { + if (currency.toUpperCase() !== 'USDC') { + throw new PaymentNetworkErrorClass('Only USDC currency is supported; received ' + currency); + } - if (!signedTx) { - throw new PaymentNetworkErrorClass('No signed transaction available'); - } + this.logger.info(`Creating EIP-3009 payment authorization for ${amount} ${currency} to ${receiver}`); - // Send the pre-signed transaction - const hash = await this.signingClient.sendRawTransaction({ - serializedTransaction: signedTx as Hex + try { + // Call the accounts service /create-payment-authorization endpoint + const response = await fetch(`${this.accountsServiceUrl}/create-payment-authorization`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${this.authToken}` + }, + body: JSON.stringify({ + amount: amount.toString(), + currency: currency.toUpperCase(), + receiver, + memo + }) }); - // Wait for transaction confirmation - this.logger.info(`Waiting for transaction confirmation: ${hash}`); - const receipt = await this.signingClient.waitForTransactionReceipt({ - hash: hash as Hex, - confirmations: 1 - }); + if (!response.ok) { + const error = await response.json().catch(() => ({ error: response.statusText })); - if (receipt.status === 'reverted') { - throw new PaymentNetworkErrorClass(`Transaction reverted: ${hash}`, new Error('Transaction reverted on chain')); - } + // Check for insufficient funds error + if (response.status === 400 && error.error?.includes('Insufficient balance')) { + const available = new BigNumber(error.available || '0'); + throw new InsufficientFundsErrorClass(currency, amount, available, 'base'); + } - this.logger.info(`Transaction confirmed: ${hash} in block ${receipt.blockNumber}`); + throw new PaymentNetworkErrorClass( + `Failed to create payment authorization: ${error.error || response.statusText}` + ); + } - // Clear the stored transaction - this.lastSignedTransaction = null; + const authorization = await response.json(); + this.logger.info(`Created EIP-3009 payment authorization`); - return hash; + return authorization; } catch (error) { - if (error instanceof PaymentNetworkErrorClass) { + if (error instanceof InsufficientFundsErrorClass || error instanceof PaymentNetworkErrorClass) { throw error; } // Wrap other errors in PaymentNetworkError - throw new PaymentNetworkErrorClass(`Failed to submit payment: ${(error as Error).message}`, error as Error); + throw new PaymentNetworkErrorClass( + `Failed to create payment authorization: ${(error as Error).message}`, + error as Error + ); } } } \ No newline at end of file diff --git a/packages/atxp-client/src/solanaPaymentMaker.ts b/packages/atxp-client/src/solanaPaymentMaker.ts index 23781303..164b2456 100644 --- a/packages/atxp-client/src/solanaPaymentMaker.ts +++ b/packages/atxp-client/src/solanaPaymentMaker.ts @@ -1,4 +1,4 @@ -import type { PaymentMaker, SignedPaymentMessage } from './types.js'; +import type { PaymentMaker, EIP3009Message } from './types.js'; import { InsufficientFundsError, PaymentNetworkError } from './types.js'; import { Keypair, Connection, PublicKey, ComputeBudgetProgram, sendAndConfirmTransaction, Transaction } from "@solana/web3.js"; import { createTransfer, ValidateTransferError as _ValidateTransferError } from "@solana/pay"; @@ -48,13 +48,13 @@ export class SolanaPaymentMaker implements PaymentMaker { return generateJWT(this.source.publicKey.toBase58(), privateKey, paymentRequestId || '', codeChallenge || ''); } - async createSignedPaymentMessage(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { + async makePayment(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { if (currency.toUpperCase() !== 'USDC') { throw new PaymentNetworkError('Only USDC currency is supported; received ' + currency); } const receiverKey = new PublicKey(receiver); - this.logger.info(`Creating signed payment message for ${amount} ${currency} to ${receiver} on Solana from ${this.source.publicKey.toBase58()}`); + this.logger.info(`Making payment of ${amount} ${currency} to ${receiver} on Solana from ${this.source.publicKey.toBase58()}`); try { // Check balance before creating payment message @@ -93,66 +93,28 @@ export class SolanaPaymentMaker implements PaymentMaker { transaction.add(modifyComputeUnits); transaction.add(addPriorityFee); - // Sign the transaction - transaction.sign(this.source); - - // Serialize the signed transaction - const signedTx = bs58.encode(transaction.serialize()); - - // Store for potential later submission - this.lastSignedTransaction = signedTx; + // Sign and send the transaction + const transactionHash = await sendAndConfirmTransaction( + this.connection, + transaction, + [this.source], + { commitment: 'confirmed' } + ); - return { - data: bs58.encode(transaction.serialize({ requireAllSignatures: false })), - signature: signedTx, // The actual signed transaction - from: this.source.publicKey.toBase58(), - to: receiver, - amount: amount, - currency: currency, - network: 'solana' as Network - }; + this.logger.info(`Payment completed: ${transactionHash}`); + return transactionHash; } catch (error) { if (error instanceof InsufficientFundsError || error instanceof PaymentNetworkError) { throw error; } // Wrap other errors in PaymentNetworkError - throw new PaymentNetworkError(`Failed to create signed payment message: ${(error as Error).message}`, error as Error); + throw new PaymentNetworkError(`Failed to make payment: ${(error as Error).message}`, error as Error); } } - async submitPaymentMessage(signedMessage: SignedPaymentMessage): Promise { - this.logger.info(`Submitting payment to Solana blockchain`); - - try { - // Use the signed transaction from the message or the stored one - const signedTx = signedMessage.signature || this.lastSignedTransaction; - - if (!signedTx) { - throw new PaymentNetworkError('No signed transaction available'); - } - - // Deserialize and send the signed transaction - const transaction = Transaction.from(bs58.decode(signedTx)); - - const transactionHash = await this.connection.sendRawTransaction( - transaction.serialize() - ); - - // Wait for confirmation - await this.connection.confirmTransaction(transactionHash, 'confirmed'); - - // Clear the stored transaction - this.lastSignedTransaction = null; - - return transactionHash; - } catch (error) { - if (error instanceof PaymentNetworkError) { - throw error; - } - - // Wrap other errors in PaymentNetworkError - throw new PaymentNetworkError(`Failed to submit payment: ${(error as Error).message}`, error as Error); - } + async createPaymentAuthorization(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { + // EIP-3009 is an Ethereum/EVM standard, not supported on Solana + throw new PaymentNetworkError('EIP-3009 payment authorizations are not supported on Solana'); } } \ No newline at end of file diff --git a/packages/atxp-client/src/types.ts b/packages/atxp-client/src/types.ts index 6b0ee95e..b32ce877 100644 --- a/packages/atxp-client/src/types.ts +++ b/packages/atxp-client/src/types.ts @@ -67,18 +67,28 @@ export class PaymentNetworkError extends Error { } } -export type SignedPaymentMessage = { - data: string; - signature: string; - from: string; - to: string; - amount: BigNumber; - currency: Currency; - network: Network; +export type EIP3009Message = { + // X402 wrapper fields + x402Version: number; + scheme: string; + network: string; + + // EIP-3009 payload for "exact" scheme + payload: { + signature: string; + authorization: { + from: string; + to: string; + value: string; + validAfter: string; + validBefore: string; + nonce: string; + }; + }; } export interface PaymentMaker { - createSignedPaymentMessage: (amount: BigNumber, currency: Currency, receiver: string, memo: string) => Promise; - submitPaymentMessage: (signedMessage: SignedPaymentMessage) => Promise; + makePayment: (amount: BigNumber, currency: Currency, receiver: string, memo: string) => Promise; + createPaymentAuthorization: (amount: BigNumber, currency: Currency, receiver: string, memo: string) => Promise; generateJWT: (params: {paymentRequestId: string, codeChallenge: string}) => Promise; } diff --git a/packages/atxp-client/src/x402Wrapper.ts b/packages/atxp-client/src/x402Wrapper.ts index 2c0e6028..73a0b8aa 100644 --- a/packages/atxp-client/src/x402Wrapper.ts +++ b/packages/atxp-client/src/x402Wrapper.ts @@ -28,28 +28,21 @@ export function wrapWithX402(fetchFn: FetchLike, account: Account): FetchLike { throw new Error(`No payment maker found for ${paymentMakerKey}`); } - // Create a signed payment message - const signedMessage = await paymentMaker.createSignedPaymentMessage( + // Create an EIP-3009 payment authorization for X402 + const authorization = await paymentMaker.createPaymentAuthorization( new BigNumber(amount), currency, recipient, memo || '' ); - // Retry the request with the payment + // The authorization is already in X402 format with EIP-3009 payload + // Send it directly in the X-Payment header const retryInit = { ...init, headers: { ...(init?.headers || {}), - 'X-Payment': JSON.stringify({ - signature: signedMessage.signature, - data: signedMessage.data, - from: signedMessage.from, - to: signedMessage.to, - amount: signedMessage.amount.toString(), - currency: signedMessage.currency, - network: signedMessage.network - }) + 'X-Payment': JSON.stringify(authorization) } }; From beafcfdcb57a89a6e53ebe865716a7da10b2d88e Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 10:35:34 -0700 Subject: [PATCH 06/61] Cleanup --- packages/atxp-client/src/basePaymentMaker.ts | 245 ++++++++++-------- .../atxp-client/src/solanaPaymentMaker.ts | 18 +- 2 files changed, 140 insertions(+), 123 deletions(-) diff --git a/packages/atxp-client/src/basePaymentMaker.ts b/packages/atxp-client/src/basePaymentMaker.ts index e6aa22b7..bdc0887b 100644 --- a/packages/atxp-client/src/basePaymentMaker.ts +++ b/packages/atxp-client/src/basePaymentMaker.ts @@ -1,8 +1,21 @@ -import type { PaymentMaker, EIP3009Message } from './types.js'; +import type { PaymentMaker, Hex, EIP3009Message } from './types.js'; import { InsufficientFundsError as InsufficientFundsErrorClass, PaymentNetworkError as PaymentNetworkErrorClass } from './types.js'; import { Logger, Currency } from '@atxp/common'; import { ConsoleLogger } from '@atxp/common'; +import { + Address, + parseEther, + publicActions, + encodeFunctionData, + WalletClient, + PublicActions, +} from "viem"; +import { base } from "viem/chains"; import { BigNumber } from "bignumber.js"; +import { USDC_CONTRACT_ADDRESS_BASE } from './baseConstants.js'; + +// Type for the extended wallet client with public actions +type ExtendedWalletClient = WalletClient & PublicActions; // Helper function to convert to base64url that works in both Node.js and browsers function toBase64Url(data: string): string { @@ -14,155 +27,161 @@ function toBase64Url(data: string): string { return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, ''); } +const USDC_DECIMALS = 6; +const ERC20_ABI = [ + { + constant: false, + inputs: [ + { name: "_to", type: "address" }, + { name: "_value", type: "uint256" }, + ], + name: "transfer", + outputs: [{ name: "", type: "bool" }], + type: "function", + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "balance", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } +]; + export class BasePaymentMaker implements PaymentMaker { + protected signingClient: ExtendedWalletClient; protected logger: Logger; - private accountsServiceUrl: string; - private authToken: string; - constructor(accountsServiceUrl: string, authToken: string, logger?: Logger) { - if (!accountsServiceUrl) { - throw new Error('accountsServiceUrl was empty'); + constructor(baseRPCUrl: string, walletClient: WalletClient, logger?: Logger) { + if (!baseRPCUrl) { + throw new Error('baseRPCUrl was empty'); + } + if (!walletClient) { + throw new Error('walletClient was empty'); } - if (!authToken) { - throw new Error('authToken was empty'); + if(!walletClient.account) { + throw new Error('walletClient.account was empty'); } - this.accountsServiceUrl = accountsServiceUrl.replace(/\/$/, ''); // Remove trailing slash - this.authToken = authToken; + this.signingClient = walletClient.extend(publicActions) as ExtendedWalletClient; this.logger = logger ?? new ConsoleLogger(); } async generateJWT({paymentRequestId, codeChallenge}: {paymentRequestId: string, codeChallenge: string}): Promise { - // Call the accounts service /sign endpoint to generate JWT - const response = await fetch(`${this.accountsServiceUrl}/sign`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${this.authToken}` - }, - body: JSON.stringify({ - paymentRequestId, - codeChallenge - }) + const headerObj = { alg: 'ES256K' }; + + const payloadObj = { + sub: this.signingClient.account!.address, + iss: 'accounts.atxp.ai', + aud: 'https://auth.atxp.ai', + iat: Math.floor(Date.now() / 1000), + exp: Math.floor(Date.now() / 1000) + 60 * 60, + ...(codeChallenge ? { code_challenge: codeChallenge } : {}), + ...(paymentRequestId ? { payment_request_id: paymentRequestId } : {}), + } as Record; + + const header = toBase64Url(JSON.stringify(headerObj)); + const payload = toBase64Url(JSON.stringify(payloadObj)); + const message = `${header}.${payload}`; + + const messageBytes = typeof Buffer !== 'undefined' + ? Buffer.from(message, 'utf8') + : new TextEncoder().encode(message); + + const signResult = await this.signingClient.signMessage({ + account: this.signingClient.account!, + message: { raw: messageBytes }, }); - if (!response.ok) { - const error = await response.text(); - throw new PaymentNetworkErrorClass(`Failed to generate JWT: ${error}`); - } + // For ES256K, signature is typically 65 bytes (r,s,v) + // Server expects the hex signature string (with 0x prefix) to be base64url encoded + // This creates: base64url("0x6eb2565...") not base64url(rawBytes) + // Pass the hex string directly to toBase64Url which will UTF-8 encode and base64url it + const signature = toBase64Url(signResult); - const { jwt } = await response.json(); - this.logger.info(`Generated JWT from accounts service`); + const jwt = `${header}.${payload}.${signature}`; + this.logger.info(`Generated ES256K JWT: ${jwt}`); return jwt; } - async makePayment(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { + async makePayment(amount: BigNumber, currency: Currency, receiver: string): Promise { if (currency.toUpperCase() !== 'USDC') { throw new PaymentNetworkErrorClass('Only USDC currency is supported; received ' + currency); } - this.logger.info(`Making payment of ${amount} ${currency} to ${receiver}`); + this.logger.info(`Making payment of ${amount} ${currency} to ${receiver} on Base from ${this.signingClient.account!.address}`); try { - // Call the accounts service /pay endpoint for regular payments - const response = await fetch(`${this.accountsServiceUrl}/pay`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${this.authToken}` - }, - body: JSON.stringify({ - amount: amount.toString(), - currency: currency.toUpperCase(), - receiver, - memo - }) - }); - - if (!response.ok) { - const error = await response.json().catch(() => ({ error: response.statusText })); - - // Check for insufficient funds error - if (response.status === 400 && error.error?.includes('Insufficient balance')) { - // Try to parse available balance from error response - const match = error.error.match(/Available: ([\d.]+)/); - const available = match ? new BigNumber(match[1]) : new BigNumber(0); - throw new InsufficientFundsErrorClass(currency, amount, available, 'base'); - } - - throw new PaymentNetworkErrorClass( - `Failed to make payment: ${error.error || response.statusText}` - ); + // Check balance before attempting payment + const balanceRaw = await this.signingClient.readContract({ + address: USDC_CONTRACT_ADDRESS_BASE as Address, + abi: ERC20_ABI, + functionName: 'balanceOf', + args: [this.signingClient.account!.address], + }) as bigint; + + const balance = new BigNumber(balanceRaw.toString()).dividedBy(10 ** USDC_DECIMALS); + + if (balance.lt(amount)) { + this.logger.warn(`Insufficient ${currency} balance for payment. Required: ${amount}, Available: ${balance}`); + throw new InsufficientFundsErrorClass(currency, amount, balance, 'base'); } - const { txHash } = await response.json(); - this.logger.info(`Payment completed: ${txHash}`); - - return txHash; - } catch (error) { - if (error instanceof InsufficientFundsErrorClass || error instanceof PaymentNetworkErrorClass) { - throw error; - } + // Convert amount to USDC units (6 decimals) as BigInt + const amountInUSDCUnits = BigInt(amount.multipliedBy(10 ** USDC_DECIMALS).toFixed(0)); - // Wrap other errors in PaymentNetworkError - throw new PaymentNetworkErrorClass( - `Failed to make payment: ${(error as Error).message}`, - error as Error - ); - } - } - - async createPaymentAuthorization(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { - if (currency.toUpperCase() !== 'USDC') { - throw new PaymentNetworkErrorClass('Only USDC currency is supported; received ' + currency); - } - - this.logger.info(`Creating EIP-3009 payment authorization for ${amount} ${currency} to ${receiver}`); - - try { - // Call the accounts service /create-payment-authorization endpoint - const response = await fetch(`${this.accountsServiceUrl}/create-payment-authorization`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${this.authToken}` - }, - body: JSON.stringify({ - amount: amount.toString(), - currency: currency.toUpperCase(), - receiver, - memo - }) + const data = encodeFunctionData({ + abi: ERC20_ABI, + functionName: "transfer", + args: [receiver as Address, amountInUSDCUnits], + }); + const hash = await this.signingClient.sendTransaction({ + chain: base, + account: this.signingClient.account!, + to: USDC_CONTRACT_ADDRESS_BASE, + data: data, + value: parseEther('0'), + maxPriorityFeePerGas: parseEther('0.000000001') }); - if (!response.ok) { - const error = await response.json().catch(() => ({ error: response.statusText })); - - // Check for insufficient funds error - if (response.status === 400 && error.error?.includes('Insufficient balance')) { - const available = new BigNumber(error.available || '0'); - throw new InsufficientFundsErrorClass(currency, amount, available, 'base'); - } + // Wait for transaction confirmation with more blocks to ensure propagation + this.logger.info(`Waiting for transaction confirmation: ${hash}`); + const receipt = await this.signingClient.waitForTransactionReceipt({ + hash: hash as Hex, + confirmations: 1 + }); - throw new PaymentNetworkErrorClass( - `Failed to create payment authorization: ${error.error || response.statusText}` - ); + if (receipt.status === 'reverted') { + throw new PaymentNetworkErrorClass(`Transaction reverted: ${hash}`, new Error('Transaction reverted on chain')); } - const authorization = await response.json(); - this.logger.info(`Created EIP-3009 payment authorization`); + this.logger.info(`Transaction confirmed: ${hash} in block ${receipt.blockNumber}`); - return authorization; + return hash; } catch (error) { if (error instanceof InsufficientFundsErrorClass || error instanceof PaymentNetworkErrorClass) { throw error; } // Wrap other errors in PaymentNetworkError - throw new PaymentNetworkErrorClass( - `Failed to create payment authorization: ${(error as Error).message}`, - error as Error - ); + throw new PaymentNetworkErrorClass(`Payment failed on Base network: ${(error as Error).message}`, error as Error); } } + + async createPaymentAuthorization(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { + // BasePaymentMaker doesn't have access to accounts service, so throw not-implemented + throw new PaymentNetworkErrorClass('EIP-3009 payment authorizations are not supported by BasePaymentMaker'); + } } \ No newline at end of file diff --git a/packages/atxp-client/src/solanaPaymentMaker.ts b/packages/atxp-client/src/solanaPaymentMaker.ts index 164b2456..8b2258f7 100644 --- a/packages/atxp-client/src/solanaPaymentMaker.ts +++ b/packages/atxp-client/src/solanaPaymentMaker.ts @@ -1,12 +1,14 @@ import type { PaymentMaker, EIP3009Message } from './types.js'; import { InsufficientFundsError, PaymentNetworkError } from './types.js'; -import { Keypair, Connection, PublicKey, ComputeBudgetProgram, sendAndConfirmTransaction, Transaction } from "@solana/web3.js"; +import { Keypair, Connection, PublicKey, ComputeBudgetProgram, sendAndConfirmTransaction } from "@solana/web3.js"; import { createTransfer, ValidateTransferError as _ValidateTransferError } from "@solana/pay"; import { getAccount, getAssociatedTokenAddress } from "@solana/spl-token"; import bs58 from "bs58"; import BigNumber from "bignumber.js"; -import { generateJWT, Currency, Network, Logger, ConsoleLogger } from '@atxp/common'; +import { generateJWT, Currency } from '@atxp/common'; import { importJWK } from 'jose'; +import { Logger } from '@atxp/common'; +import { ConsoleLogger } from '@atxp/common'; // this is a global public key for USDC on the solana mainnet const USDC_MINT = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"); @@ -17,7 +19,6 @@ export class SolanaPaymentMaker implements PaymentMaker { private connection: Connection; private source: Keypair; private logger: Logger; - private lastSignedTransaction: string | null = null; constructor(solanaEndpoint: string, sourceSecretKey: string, logger?: Logger) { if (!solanaEndpoint) { @@ -48,16 +49,17 @@ export class SolanaPaymentMaker implements PaymentMaker { return generateJWT(this.source.publicKey.toBase58(), privateKey, paymentRequestId || '', codeChallenge || ''); } - async makePayment(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { + makePayment = async (amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise => { if (currency.toUpperCase() !== 'USDC') { throw new PaymentNetworkError('Only USDC currency is supported; received ' + currency); } const receiverKey = new PublicKey(receiver); + this.logger.info(`Making payment of ${amount} ${currency} to ${receiver} on Solana from ${this.source.publicKey.toBase58()}`); try { - // Check balance before creating payment message + // Check balance before attempting payment const tokenAccountAddress = await getAssociatedTokenAddress( USDC_MINT, this.source.publicKey @@ -93,15 +95,11 @@ export class SolanaPaymentMaker implements PaymentMaker { transaction.add(modifyComputeUnits); transaction.add(addPriorityFee); - // Sign and send the transaction const transactionHash = await sendAndConfirmTransaction( this.connection, transaction, [this.source], - { commitment: 'confirmed' } ); - - this.logger.info(`Payment completed: ${transactionHash}`); return transactionHash; } catch (error) { if (error instanceof InsufficientFundsError || error instanceof PaymentNetworkError) { @@ -109,7 +107,7 @@ export class SolanaPaymentMaker implements PaymentMaker { } // Wrap other errors in PaymentNetworkError - throw new PaymentNetworkError(`Failed to make payment: ${(error as Error).message}`, error as Error); + throw new PaymentNetworkError(`Payment failed on Solana network: ${(error as Error).message}`, error as Error); } } From bf0cc655c930de1620cd44e34bbed49e380702e0 Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 10:41:38 -0700 Subject: [PATCH 07/61] Separate out x402 from EIP3009 bits --- packages/atxp-client/src/atxpAccount.ts | 8 ++--- packages/atxp-client/src/basePaymentMaker.ts | 4 +-- .../atxp-client/src/solanaPaymentMaker.ts | 4 +-- packages/atxp-client/src/types.ts | 33 ++++++++++--------- packages/atxp-client/src/x402Wrapper.ts | 19 +++++++---- 5 files changed, 38 insertions(+), 30 deletions(-) diff --git a/packages/atxp-client/src/atxpAccount.ts b/packages/atxp-client/src/atxpAccount.ts index 4408f13d..a654e7d7 100644 --- a/packages/atxp-client/src/atxpAccount.ts +++ b/packages/atxp-client/src/atxpAccount.ts @@ -1,4 +1,4 @@ -import type { Account, PaymentMaker, EIP3009Message } from './types.js'; +import type { Account, PaymentMaker, EIP3009Authorization } from './types.js'; import type { FetchLike, Network, Currency } from '@atxp/common' import BigNumber from 'bignumber.js'; @@ -58,7 +58,7 @@ class ATXPHttpPaymentMaker implements PaymentMaker { return json.txHash; } - async createPaymentAuthorization(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { + async createPaymentAuthorization(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { // Create an EIP-3009 payment authorization via the HTTP endpoint const response = await this.fetchFn(`${this.origin}/create-payment-authorization`, { method: 'POST', @@ -79,8 +79,8 @@ class ATXPHttpPaymentMaker implements PaymentMaker { throw new Error(`ATXPAccount: /create-payment-authorization failed: ${response.status} ${response.statusText} ${text}`); } - // Return the EIP-3009 payment authorization from the accounts service - return await response.json() as EIP3009Message; + // Return the EIP-3009 authorization from the accounts service + return await response.json() as EIP3009Authorization; } async generateJWT(params: { paymentRequestId: string; codeChallenge: string }): Promise { diff --git a/packages/atxp-client/src/basePaymentMaker.ts b/packages/atxp-client/src/basePaymentMaker.ts index bdc0887b..8d0037e5 100644 --- a/packages/atxp-client/src/basePaymentMaker.ts +++ b/packages/atxp-client/src/basePaymentMaker.ts @@ -1,4 +1,4 @@ -import type { PaymentMaker, Hex, EIP3009Message } from './types.js'; +import type { PaymentMaker, Hex, EIP3009Authorization } from './types.js'; import { InsufficientFundsError as InsufficientFundsErrorClass, PaymentNetworkError as PaymentNetworkErrorClass } from './types.js'; import { Logger, Currency } from '@atxp/common'; import { ConsoleLogger } from '@atxp/common'; @@ -180,7 +180,7 @@ export class BasePaymentMaker implements PaymentMaker { } } - async createPaymentAuthorization(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { + async createPaymentAuthorization(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { // BasePaymentMaker doesn't have access to accounts service, so throw not-implemented throw new PaymentNetworkErrorClass('EIP-3009 payment authorizations are not supported by BasePaymentMaker'); } diff --git a/packages/atxp-client/src/solanaPaymentMaker.ts b/packages/atxp-client/src/solanaPaymentMaker.ts index 8b2258f7..d976e630 100644 --- a/packages/atxp-client/src/solanaPaymentMaker.ts +++ b/packages/atxp-client/src/solanaPaymentMaker.ts @@ -1,4 +1,4 @@ -import type { PaymentMaker, EIP3009Message } from './types.js'; +import type { PaymentMaker, EIP3009Authorization } from './types.js'; import { InsufficientFundsError, PaymentNetworkError } from './types.js'; import { Keypair, Connection, PublicKey, ComputeBudgetProgram, sendAndConfirmTransaction } from "@solana/web3.js"; import { createTransfer, ValidateTransferError as _ValidateTransferError } from "@solana/pay"; @@ -111,7 +111,7 @@ export class SolanaPaymentMaker implements PaymentMaker { } } - async createPaymentAuthorization(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { + async createPaymentAuthorization(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { // EIP-3009 is an Ethereum/EVM standard, not supported on Solana throw new PaymentNetworkError('EIP-3009 payment authorizations are not supported on Solana'); } diff --git a/packages/atxp-client/src/types.ts b/packages/atxp-client/src/types.ts index b32ce877..984cff1c 100644 --- a/packages/atxp-client/src/types.ts +++ b/packages/atxp-client/src/types.ts @@ -67,28 +67,29 @@ export class PaymentNetworkError extends Error { } } -export type EIP3009Message = { - // X402 wrapper fields +// EIP-3009 TransferWithAuthorization message +export type EIP3009Authorization = { + signature: string; + authorization: { + from: string; + to: string; + value: string; + validAfter: string; + validBefore: string; + nonce: string; + }; +} + +// X402 protocol message wrapper +export type X402Message = { x402Version: number; scheme: string; network: string; - - // EIP-3009 payload for "exact" scheme - payload: { - signature: string; - authorization: { - from: string; - to: string; - value: string; - validAfter: string; - validBefore: string; - nonce: string; - }; - }; + payload: EIP3009Authorization; } export interface PaymentMaker { makePayment: (amount: BigNumber, currency: Currency, receiver: string, memo: string) => Promise; - createPaymentAuthorization: (amount: BigNumber, currency: Currency, receiver: string, memo: string) => Promise; + createPaymentAuthorization: (amount: BigNumber, currency: Currency, receiver: string, memo: string) => Promise; generateJWT: (params: {paymentRequestId: string, codeChallenge: string}) => Promise; } diff --git a/packages/atxp-client/src/x402Wrapper.ts b/packages/atxp-client/src/x402Wrapper.ts index 73a0b8aa..93facad0 100644 --- a/packages/atxp-client/src/x402Wrapper.ts +++ b/packages/atxp-client/src/x402Wrapper.ts @@ -1,4 +1,4 @@ -import type { Account } from './types.js'; +import type { Account, X402Message } from './types.js'; import { FetchLike } from '@atxp/common'; import { BigNumber } from 'bignumber.js'; @@ -28,21 +28,28 @@ export function wrapWithX402(fetchFn: FetchLike, account: Account): FetchLike { throw new Error(`No payment maker found for ${paymentMakerKey}`); } - // Create an EIP-3009 payment authorization for X402 - const authorization = await paymentMaker.createPaymentAuthorization( + // Create an EIP-3009 payment authorization + const eip3009Authorization = await paymentMaker.createPaymentAuthorization( new BigNumber(amount), currency, recipient, memo || '' ); - // The authorization is already in X402 format with EIP-3009 payload - // Send it directly in the X-Payment header + // Wrap the EIP-3009 authorization in X402 protocol format + const x402Message: X402Message = { + x402Version: 1, + scheme: 'exact', + network: network, + payload: eip3009Authorization + }; + + // Send the X402 message in the X-Payment header const retryInit = { ...init, headers: { ...(init?.headers || {}), - 'X-Payment': JSON.stringify(authorization) + 'X-Payment': JSON.stringify(x402Message) } }; From af8821462fa3fcace956251f60e6ae9f08374d56 Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 10:44:42 -0700 Subject: [PATCH 08/61] Clean up: revert README.md and remove docs folder --- README.md | 56 +----- docs/PACKAGE_MANAGER_TESTING.md | 172 ---------------- docs/atxp-account-x402-spec.md | 168 ---------------- docs/bundle-size-analysis.md | 236 ---------------------- docs/package-validation.md | 208 ------------------- docs/x402-integration.md | 340 -------------------------------- 6 files changed, 1 insertion(+), 1179 deletions(-) delete mode 100644 docs/PACKAGE_MANAGER_TESTING.md delete mode 100644 docs/atxp-account-x402-spec.md delete mode 100644 docs/bundle-size-analysis.md delete mode 100644 docs/package-validation.md delete mode 100644 docs/x402-integration.md diff --git a/README.md b/README.md index d119cf68..b49e258f 100644 --- a/README.md +++ b/README.md @@ -1,57 +1,3 @@ # ATXP -ATXP is a framework for building and running agents that can interact with the world. See [docs.atxp.ai](https://docs.atxp.ai) for documentation and examples. - -## Features - -- **OAuth 2.0 Authentication**: Secure authentication flow for accessing protected resources -- **Micropayments**: Built-in support for USDC payments on Base and Solana networks -- **MCP Integration**: Full Model Context Protocol support for AI agents -- **X402 Protocol Support**: Compatible with X402 payment-required servers -- **Multi-Network**: Support for Base, Solana, and ATXP native accounts - -## X402 Support - -ATXP SDK now includes support for the X402 payment protocol, allowing ATXP clients to interact with X402 servers seamlessly. This enables: - -- Automatic handling of HTTP 402 payment challenges -- Signed payment message creation without immediate blockchain submission -- Facilitator-based payment verification and settlement - -For detailed X402 integration instructions, see [X402 Integration Guide](./docs/x402-integration.md) and the [X402 example](./examples/x402-server). - -## Quick Start - -### Basic ATXP Client - -```typescript -import { atxpClient, BaseAccount } from '@atxp/client'; - -const account = new BaseAccount(rpcUrl, privateKey); -const client = await atxpClient({ account, /* ... */ }); -``` - -### With X402 Support - -```typescript -import { wrapWithX402 } from '@atxp/client'; - -const x402Fetch = wrapWithX402(fetch, { - account, - approvePayment: async (payment) => true, - // ... configuration -}); -``` - -## Documentation - -- [ATXP Documentation](https://docs.atxp.ai) -- [X402 Integration Guide](./docs/x402-integration.md) -- [API Reference](https://docs.atxp.ai/api) - -## Examples - -- [Basic ATXP Example](./examples/basic) -- [X402 Server Example](./examples/x402-server) -- [Server Example](./examples/server) -- [Vercel SDK Integration](./examples/vercel-sdk) \ No newline at end of file +ATXP is a framework for building and running agents that can interact with the world. See [docs.atxp.ai](https://docs.atxp.ai) for documentation and examples. \ No newline at end of file diff --git a/docs/PACKAGE_MANAGER_TESTING.md b/docs/PACKAGE_MANAGER_TESTING.md deleted file mode 100644 index c75afd7d..00000000 --- a/docs/PACKAGE_MANAGER_TESTING.md +++ /dev/null @@ -1,172 +0,0 @@ -# Package Manager Integration Testing - -This document describes the integration testing setup for ensuring ATXP packages work correctly across different package managers and prevent crypto module loading regressions. - -## Overview - -The integration tests verify that the `@atxp/common` package works correctly when installed by external consumers using different package managers (npm, pnpm, yarn, bun). - -## What Gets Tested - -### ✅ Package Managers -- **npm** - Standard Node.js package manager -- **pnpm** - Fast, disk space efficient package manager -- **yarn** - Alternative package manager with workspaces support -- **bun** - Fast all-in-one JavaScript runtime (when available) - -### ✅ Crypto Functionality -- **Environment Detection** - Correct Node.js/browser/React Native detection -- **UUID Generation** - `crypto.randomUUID()` produces valid RFC 4122 UUIDs -- **Hash Generation** - `crypto.digest()` SHA-256 hashing with expected outputs -- **Hex Encoding** - `crypto.toHex()` converts byte arrays to hex strings -- **Consistency** - Same inputs produce same outputs, different inputs differ - -### ✅ Cross-Platform Compatibility -- **Linux** (ubuntu-latest) -- **macOS** (macos-latest) -- **Windows** (windows-latest) -- **Node.js versions** 18, 20, 22 - -## Running Tests - -### Locally - -```bash -# Run all package manager integration tests -npm run test:package-managers - -# Run all integration tests (includes Redis tests) -npm run test:integration - -# Run specific package test manually in atxp-common package -cd packages/atxp-common -npm run test:package-managers -``` - -### In CI/CD - -The tests automatically run on: -- Push to `main` branch -- Pull requests to `main` branch -- Changes to platform crypto code -- Manual workflow dispatch - -## Test Structure - -### Test File Location -``` -packages/atxp-common/src/platform/packageManager.integration.test.ts -``` - -### How It Works - -1. **Build & Package** - Creates a tarball of the current `@atxp/common` package -2. **Create Test Projects** - Generates temporary external project directories -3. **Install Package** - Uses each package manager to install the tarball -4. **Run Crypto Tests** - Executes crypto functionality tests as external consumer -5. **Validate Results** - Ensures all crypto functions work correctly -6. **Cleanup** - Removes temporary files and directories - -### Test Timeout -- **Local**: 2 minutes per package manager test -- **CI**: 2 minutes per package manager test -- **Total runtime**: ~8-10 minutes for all package managers - -## Expected Test Output - -### Successful Test -``` -✅ should work when installed with npm -✅ should work when installed with pnpm -✅ should work when installed with yarn -✅ should work when installed with bun -``` - -### Test Failure Indicators -- ❌ `Cannot find module 'crypto'` errors -- ❌ Invalid UUID format errors -- ❌ Hash output mismatches -- ❌ Environment detection failures -- ❌ Package installation failures - -## Adding New Tests - -### Test a New Package Manager - -1. Add the package manager to the `PACKAGE_MANAGERS` array -2. Add installation command logic in the test -3. Update the GitHub Actions workflow to install the package manager - -### Test New Crypto Functionality - -1. Add test logic to `CONSUMER_TEST_SCRIPT` -2. Update expected outputs and validation -3. Document new test cases in this file - -## Troubleshooting - -### Common Issues - -**Test Timeout** -- Increase `TEST_TIMEOUT` or `testTimeout` in vitest config -- Check for slow package installations - -**Package Manager Not Found** -- Tests automatically skip unavailable package managers -- Install missing package managers for local development - -**Hash/UUID Validation Failures** -- Check for crypto implementation regressions -- Verify Web Crypto API vs Node.js crypto module behavior - -**Temporary Directory Cleanup** -- Tests clean up automatically in `afterAll()` -- Manual cleanup: `rm -rf /tmp/atxp-integration-*` - -### Debugging - -```bash -# Run with verbose output -npm run test:package-managers -- --reporter=verbose - -# Run single package manager test -npm run test:package-managers -- --grep "npm" - -# Keep temporary directories for inspection -# (modify test to comment out cleanup in afterAll) -``` - -## CI/CD Integration - -### GitHub Actions Workflow -- **File**: `.github/workflows/package-manager-integration.yml` -- **Triggers**: Push/PR to main, manual dispatch -- **Matrix**: Node.js 18/20/22, Ubuntu/macOS/Windows -- **Artifacts**: Test results uploaded on failure - -### Status Checks -The package manager integration tests are **required status checks** for: -- Pull requests modifying platform crypto code -- Releases of `@atxp/common` package - -## Performance Considerations - -- Tests run in parallel across Node.js versions -- Package installations are cached when possible -- Temporary directories are cleaned up promptly -- Tests skip unavailable package managers automatically - -## Regression Prevention - -These tests prevent regressions by: -1. **Catching crypto loading issues** before they reach consumers -2. **Validating cross-platform compatibility** on multiple OS/Node versions -3. **Testing real-world usage patterns** with actual package installations -4. **Automated CI/CD integration** prevents broken releases - -## Maintenance - -- **Update package manager versions** in GitHub Actions regularly -- **Add new Node.js versions** to test matrix as they're released -- **Review test timeouts** if CI becomes slow -- **Update expected test outputs** when crypto behavior changes intentionally \ No newline at end of file diff --git a/docs/atxp-account-x402-spec.md b/docs/atxp-account-x402-spec.md deleted file mode 100644 index dfcbbbb1..00000000 --- a/docs/atxp-account-x402-spec.md +++ /dev/null @@ -1,168 +0,0 @@ -# ATXPAccount X402 API Specification - -## Overview - -This specification defines the API changes needed for the ATXP Account service to support X402 payment protocol. The changes enable signing payment messages without immediate blockchain submission, which is required for X402's facilitator-based settlement model. - -## Background - -X402 requires clients to: -1. Sign a payment message locally -2. Send the signed message to the resource server -3. Let the facilitator verify and submit to blockchain - -The current `/pay` endpoint signs and submits in one step. We need to separate these operations. - -## New API Endpoints - -### 1. `/sign-payment` - Create Signed Payment Message - -**Method:** POST -**Authentication:** Basic Auth (connection token) - -**Request Body:** -```json -{ - "amount": "1.00", // String decimal amount - "currency": "USDC", // Currency code - "receiver": "0x...", // Recipient address - "memo": "Payment for..." // Optional memo -} -``` - -**Response (200 OK):** -```json -{ - "data": "0x...", // Encoded transaction data - "signature": "0x...", // Signed transaction - "from": "0x...", // Sender address - "nonce": 123, // Transaction nonce - "gasPrice": "1000000000" // Gas price in wei -} -``` - -**Error Responses:** -- 400: Invalid parameters -- 401: Unauthorized -- 500: Signing failed - -### 2. `/submit-payment` - Submit Pre-signed Payment - -**Method:** POST -**Authentication:** Basic Auth (connection token) - -**Request Body:** -```json -{ - "signature": "0x...", // Signed transaction from /sign-payment - "data": "0x...", // Transaction data - "from": "0x...", // Must match account address - "to": "0x...", // Recipient - "amount": "1.00", // For validation - "currency": "USDC", // For validation - "network": "base" // Network identifier -} -``` - -**Response (200 OK):** -```json -{ - "txHash": "0x..." // Transaction hash -} -``` - -**Error Responses:** -- 400: Invalid signature or parameters -- 401: Unauthorized -- 409: Transaction already submitted -- 500: Submission failed - -## Implementation Notes - -### Signing Without Submission - -The `/sign-payment` endpoint should: -1. Validate the account has sufficient balance -2. Build the transaction (data, gas, nonce) -3. Sign the transaction locally -4. Return the signed transaction WITHOUT broadcasting - -### Nonce Management - -- Track pending nonces to prevent conflicts -- Increment nonce for each signed transaction -- Reset nonce tracking after submission or timeout - -### Security Considerations - -1. **Replay Protection:** Track submitted signatures to prevent replay -2. **Timeout:** Signed transactions should expire after 5 minutes -3. **Rate Limiting:** Limit signing requests per account -4. **Balance Check:** Always verify balance before signing - -## Backwards Compatibility - -The existing `/pay` endpoint remains unchanged and continues to sign+submit atomically. It can be implemented as: -``` -/pay = /sign-payment + /submit-payment -``` - -## Migration Path - -1. Deploy new endpoints alongside existing `/pay` -2. Update SDK to use new endpoints when X402 is detected -3. Monitor usage and deprecate `/pay` in future version - -## Example Usage Flow - -```typescript -// 1. Client requests signing -POST /sign-payment -{ - "amount": "0.01", - "currency": "USDC", - "receiver": "0x123...", - "memo": "X402 payment" -} - -// 2. Server returns signed message -{ - "signature": "0xabc...", - "data": "0xdef...", - "from": "0x456..." -} - -// 3. Client sends to X402 server -// (X402 facilitator verifies and settles) - -// 4. Optional: Client can also submit directly -POST /submit-payment -{ - "signature": "0xabc...", - // ... rest of signed message -} -``` - -## Testing Requirements - -1. Test signing without submission -2. Verify nonce increments correctly -3. Test replay protection -4. Verify timeout enforcement -5. Test concurrent signing requests -6. Validate balance checks - -## Performance Targets - -- `/sign-payment`: < 100ms -- `/submit-payment`: < 2s (includes blockchain confirmation) -- Support 100 concurrent signing operations per account - -## Monitoring - -Track: -- Signing success/failure rates -- Submission success/failure rates -- Expired signatures count -- Replay attempt count -- Average signing latency \ No newline at end of file diff --git a/docs/bundle-size-analysis.md b/docs/bundle-size-analysis.md deleted file mode 100644 index 3c262128..00000000 --- a/docs/bundle-size-analysis.md +++ /dev/null @@ -1,236 +0,0 @@ -# Bundle Size Analysis - -This document describes the bundle size analysis tooling implemented for the ATXP SDK packages. - -## Overview - -The ATXP SDK uses [rollup-plugin-analyzer](https://www.npmjs.com/package/rollup-plugin-analyzer) to provide detailed bundle size analysis across all packages. This tooling helps monitor bundle sizes, identify optimization opportunities, and track size changes over time. - -## Features - -### 📊 Detailed Analysis -- **Bundle size**: Total bundle size after rollup processing -- **Code reduction**: Percentage reduction from original source -- **Module breakdown**: Visual chart showing size contribution per module -- **Module count**: Total number of modules in the bundle - -### 🔄 CI Integration -- Automated bundle analysis on pull requests -- Comparison between current and base branch -- Non-blocking analysis (informational only) -- PR comments with detailed reports - -### 🛠 Developer Tools -Multiple npm scripts for different analysis needs: -- `npm run size` - Quick analysis of all packages (live output during build) -- `npm run size:summary` - Summary view with charts (live output during build) -- `npm run size:detailed` - Detailed analysis with top 20 modules (live output during build) -- `npm run size:exports` - Include export usage analysis (live output during build) -- `npm run size:ci` - Generate comprehensive report saved to file with clear file path -- `npm run size:ci:show` - Show comprehensive report directly in terminal - -## Usage - -### Local Development - -#### Quick Analysis -```bash -# Analyze all packages with summary -npm run size:summary -``` - -#### Detailed Analysis -```bash -# Get detailed breakdown of largest modules -npm run size:detailed -``` - -#### Export Analysis -```bash -# See which exports are used/unused -npm run size:exports -``` - -#### CI-Style Analysis -```bash -# Generate markdown report saved to bundle-analysis/ directory -npm run size:ci - -# Show analysis report directly in terminal (no file saved) -npm run size:ci:show - -# Save to specific file -npm run size:ci -- --output=my-analysis.md - -# Get help with all options -npm run size:ci -- --help -``` - -**Output Options:** -- **Default**: Saves timestamped file to `bundle-analysis/` and shows file path -- **`--stdout`**: Prints analysis directly to terminal for immediate viewing -- **`--output=file`**: Saves to specific file location -- **`--json`**: Output in JSON format instead of markdown - -All analysis outputs are saved to the `bundle-analysis/` directory and are automatically ignored by git. - -### Single Package Analysis - -To analyze a specific package: - -```bash -cd packages/atxp-client -ANALYZE_BUNDLE=true npm run build -``` - -### Environment Variables - -The analyzer behavior can be customized with environment variables: - -- `ANALYZE_BUNDLE=true` - Enable bundle analysis -- `ANALYZE_SUMMARY_ONLY=false` - Show detailed module breakdown -- `ANALYZE_LIMIT=20` - Number of modules to show in detailed view -- `ANALYZE_SHOW_EXPORTS=true` - Include export usage information - -## CI Integration - -### GitHub Actions Workflow - -The `bundle-size.yml` workflow runs automatically on pull requests when: -- Package source code changes (`packages/*/src/**`) -- Build configuration changes (`rollup.config.js`, `package.json`) -- Bundle analysis configuration changes - -### Workflow Steps - -1. **Install dependencies** and build packages -2. **Analyze current branch** using rollup-plugin-analyzer -3. **Switch to base branch** and analyze for comparison -4. **Generate comparison report** showing changes -5. **Post/update PR comment** with analysis results -6. **Upload artifacts** for manual inspection - -### Output Directory Structure - -Bundle analysis files are organized in the `bundle-analysis/` directory: - -``` -bundle-analysis/ -├── bundle-analysis-2025-01-15T10-30-45.md # Timestamped reports -├── bundle-analysis-2025-01-15T11-15-20.json # JSON format outputs -├── current-analysis.md # CI: Current branch analysis -├── base-analysis.md # CI: Base branch analysis -└── bundle-report.md # CI: Final comparison report -``` - -**Note**: All files in `bundle-analysis/` are automatically ignored by git to prevent committing generated analysis files. - -### PR Comments - -The workflow automatically posts/updates PR comments with: -- Current bundle size analysis for all packages -- Visual charts showing module size contributions -- Comparison with base branch (when available) -- Tips for bundle size optimization - -## Understanding the Output - -### Analysis Chart Example -``` ------------------------------ -Rollup File Analysis ------------------------------ -bundle size: 38.282 KB -original size: 40.592 KB -code reduction: 5.69 % -module count: 12 - -/src/oAuthResource.ts -█████████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 35.18 % (13.466 KB) -/src/platform/index.ts -██████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 20.79 % (7.958 KB) -/src/mcpJson.ts -██████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 12.78 % (4.893 KB) -``` - -### Key Metrics - -- **Bundle Size**: Final size after bundling and tree-shaking -- **Original Size**: Sum of all source file sizes -- **Code Reduction**: Percentage saved through bundling optimizations -- **Module Count**: Number of distinct modules in the bundle -- **Module Chart**: Visual representation of each module's contribution - -### Optimization Insights - -The analysis helps identify: -1. **Largest modules** that could benefit from code splitting -2. **Unused code** that could be tree-shaken -3. **Duplicate dependencies** across packages -4. **Bundle growth** over time through PR comparisons - -## Bundle Size Thresholds - -### Current Package Sizes (approx.) - -| Package | Bundle Size | Status | Notes | -|---------|-------------|---------|-------| -| @atxp/common | ~39KB | ✅ Good | Core utilities and types | -| @atxp/redis | ~6KB | ✅ Good | Redis OAuth implementation | -| @atxp/sqlite | ~10KB | ✅ Good | SQLite OAuth implementation | -| @atxp/base | ~25KB | ✅ Good | Base blockchain integration | -| @atxp/server | ~404KB | 🔴 Large | MCP server with dependencies | -| @atxp/client | ~576KB | 🔴 Large | Client with blockchain libs | - -### Size Categories - -- ✅ **Good**: < 100KB raw bundle size -- 🟡 **Warning**: 100KB - 500KB raw bundle size -- 🔴 **Large**: > 500KB raw bundle size - -> **Note**: Large sizes for client/server packages are expected due to blockchain and MCP dependencies. The analysis helps track if they grow unexpectedly. - -## Optimization Strategies - -### Tree Shaking -- Use explicit named exports (already implemented) -- Avoid `export *` patterns -- Mark side-effect-free packages with `"sideEffects": false` - -### Code Splitting -- Use dynamic imports for optional features -- Separate blockchain-specific code -- Lazy load large dependencies - -### Dependency Management -- Audit large dependencies regularly -- Use smaller alternatives when possible -- Externalize dependencies that consumers should provide - -### Bundle Analysis -- Monitor size changes in PRs -- Profile largest modules for optimization opportunities -- Track export usage to identify unused code - -## Troubleshooting - -### Analysis Not Running -1. Ensure `ANALYZE_BUNDLE=true` environment variable is set -2. Check that `rollup-plugin-analyzer` is installed -3. Verify rollup configuration includes the analyzer plugin - -### Missing Analysis Output -1. Check that build completes successfully -2. Look for analysis output in build logs -3. Verify analyzer plugin configuration - -### CI Workflow Issues -1. Check workflow file syntax in `.github/workflows/bundle-size.yml` -2. Ensure PR targets correct base branch -3. Check GitHub Actions logs for detailed error messages - -## Related Documentation - -- [Rollup Plugin Analyzer Documentation](https://www.npmjs.com/package/rollup-plugin-analyzer) -- [Bundle Size Best Practices](https://web.dev/reduce-javascript-payloads-with-tree-shaking/) -- [GitHub Actions Workflow Syntax](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions) \ No newline at end of file diff --git a/docs/package-validation.md b/docs/package-validation.md deleted file mode 100644 index aca760a8..00000000 --- a/docs/package-validation.md +++ /dev/null @@ -1,208 +0,0 @@ -# Package Validation and Testing - -This document describes the comprehensive package validation and testing system implemented for ATXP packages. - -## Overview - -The package validation system ensures that all ATXP packages are correctly built, packaged, and can be successfully installed and used by consumers. It includes automated validation, testing, and verification scripts. - -## Features Implemented - -### 1. Package Scripts - -All packages now include these standardized scripts: - -- `prepack`: Runs build and typecheck before packaging -- `pack:dry`: Performs a dry-run pack to validate package contents without creating actual tarball - -**Example package.json scripts section:** -```json -{ - "scripts": { - "build": "rollup -c", - "typecheck": "tsc --noEmit", - "test": "vitest run", - "prepack": "npm run build && npm run typecheck", - "pack:dry": "npm pack --dry-run" - } -} -``` - -### 2. Validation Scripts - -#### Package Validation Script (`scripts/validate-packages.js`) -Comprehensive validation of package structure and configuration: - -- ✅ **Package.json Validation**: Checks required fields, scripts, and structure -- ✅ **Build Artifacts**: Verifies all required dist files exist -- ✅ **TypeScript Declarations**: Ensures .d.ts files are present -- ✅ **Export Maps**: Validates exports configuration -- ✅ **Dependency Management**: Checks for proper peer dependencies -- ✅ **File Inclusion**: Verifies files array includes necessary assets - -**Usage:** -```bash -# Validate all packages -npm run validate:packages - -# Validate specific package -npm run validate:packages atxp-client -``` - -#### Package Installation Test (`scripts/test-package-installation.js`) -End-to-end testing of package installation and usage: - -- 📦 **Pack Testing**: Creates actual package tarballs -- 📥 **Installation Testing**: Installs packages in isolated environments -- 🧪 **Import Testing**: Verifies packages can be imported and used -- 🧹 **Cleanup**: Automatically cleans up test artifacts - -**Usage:** -```bash -# Test all packages -npm run test:package-install - -# Test specific package -npm run test:package-install atxp-server -``` - -### 3. Root Scripts - -New scripts added to root package.json for monorepo management: - -```json -{ - "scripts": { - "validate:packages": "node scripts/validate-packages.js", - "test:package-install": "node scripts/test-package-installation.js", - "pack:all": "npm run pack:dry --workspaces --if-present", - "prepack:all": "npm run prepack --workspaces --if-present" - } -} -``` - -## Validation Checks - -### Required Package Fields -- `name`, `version`, `description`, `license` -- `type: "module"` for ESM support -- `main`, `module`, `types` entry points -- `exports` map configuration -- `files` array including "dist" - -### Required Scripts -- `build`: Build the package -- `typecheck`: TypeScript type checking -- `lint`: Code linting -- `test`: Run tests -- `prepack`: Pre-packaging validation -- `pack:dry`: Dry-run packaging - -### Required Build Artifacts -- `dist/index.js`: ESM entry point -- `dist/index.cjs`: CommonJS entry point -- `dist/index.d.ts`: TypeScript declarations - -### Export Map Validation -- `types`: Points to declaration files -- `import`: Points to ESM build -- `require`: Points to CommonJS build - -## How It Works - -### Prepack Process -When `npm pack` is run (or triggered by `npm publish`): - -1. **prepack script runs automatically** - - Builds the package (`npm run build`) - - Runs type checking (`npm run typecheck`) - - Fails if build or types have errors - -2. **Package creation** - - Creates tarball with only files listed in `files` array - - Includes `dist/` directory with build artifacts - -### Installation Testing Process -The installation test script: - -1. **Validates package** using pack dry-run -2. **Creates actual package** with `npm pack` -3. **Sets up test environment** in temporary directory -4. **Installs package** from tarball -5. **Tests imports** to verify package works -6. **Cleans up** test artifacts - -### Continuous Validation -- All builds now run validation before completion -- Pack dry-run ensures packages are valid before publishing -- Installation tests verify end-to-end functionality - -## Benefits - -### For Development -- ✅ **Early Error Detection**: Catches packaging issues before publishing -- ✅ **Consistent Structure**: Ensures all packages follow same patterns -- ✅ **Automated Validation**: Reduces manual testing overhead - -### For Consumers -- ✅ **Reliable Packages**: Guaranteed to install and import correctly -- ✅ **Proper TypeScript Support**: Declaration files always included -- ✅ **Correct Module Support**: Both ESM and CommonJS entry points - -### for CI/CD -- ✅ **Automated Checks**: Can be integrated into CI pipelines -- ✅ **Fast Feedback**: Quick validation without full publish cycle -- ✅ **Comprehensive Coverage**: Tests entire package lifecycle - -## Usage Examples - -### Development Workflow -```bash -# During development -npm run build # Build packages -npm run validate:packages # Validate package structure - -# Before publishing -npm run pack:all # Dry-run pack all packages -npm run test:package-install # Test installation process -``` - -### CI Integration -```bash -# In CI pipeline -npm run build -npm run validate:packages -npm run test:package-install -# Only publish if all validations pass -``` - -### Single Package Testing -```bash -# Test specific package -npm run validate:packages atxp-client -npm run test:package-install atxp-client - -# In package directory -npm run prepack # Build and typecheck -npm run pack:dry # Test packaging -``` - -## Error Handling - -The validation scripts provide detailed error messages: - -- **Validation Errors**: Missing fields, invalid structure, missing files -- **Build Errors**: TypeScript errors, build failures -- **Installation Errors**: Package installation or import failures -- **Warnings**: Best practice suggestions, dependency recommendations - -## Integration with Existing Workflow - -This system integrates seamlessly with existing package management: - -- **Existing Scripts**: All existing scripts continue to work unchanged -- **Build Process**: Uses existing rollup build configuration -- **Publishing**: Works with existing `npm publish` workflow -- **Development**: Adds validation without disrupting dev experience - -The validation system ensures that ATXP packages are always correctly built, properly configured, and ready for consumer use. \ No newline at end of file diff --git a/docs/x402-integration.md b/docs/x402-integration.md deleted file mode 100644 index 9535b6cd..00000000 --- a/docs/x402-integration.md +++ /dev/null @@ -1,340 +0,0 @@ -# X402 Integration Guide - -## Overview - -The ATXP SDK now includes support for the X402 payment protocol, allowing ATXP clients to seamlessly interact with X402 servers. X402 is a micropayment protocol that uses HTTP 402 (Payment Required) status codes to enable pay-per-use web resources. - -## Key Concepts - -### X402 Protocol Flow - -1. **Payment Challenge**: Server responds with HTTP 402 and payment requirements in `X-Payment` header -2. **Payment Signing**: Client creates and signs a payment message without submitting to blockchain -3. **Payment Verification**: Server's facilitator verifies the signed payment -4. **Payment Settlement**: Facilitator submits the payment to blockchain -5. **Resource Access**: Server grants access to the protected resource - -### Architecture Components - -- **Client**: Uses ATXP SDK with X402 wrapper to handle payment challenges -- **Resource Server**: Protects resources and issues payment challenges -- **Facilitator**: Verifies signatures and settles payments on-chain - -## Implementation - -### Refactored PaymentMaker Interface - -The `PaymentMaker` interface has been extended to support separate signing and submission: - -```typescript -interface PaymentMaker { - // Original method (still supported) - makePayment(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise; - - // New methods for X402 support - createSignedPaymentMessage(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise; - submitPaymentMessage(signedMessage: SignedPaymentMessage): Promise; - - generateJWT(params: {paymentRequestId: string, codeChallenge: string}): Promise; -} -``` - -### SignedPaymentMessage Type - -```typescript -type SignedPaymentMessage = { - data: string; // Transaction data - signature: string; // Signed transaction - from: string; // Sender address - to: string; // Recipient address - amount: BigNumber; // Payment amount - currency: Currency; // Payment currency - network: Network; // Blockchain network -} -``` - -## Usage - -### Basic X402 Integration - -```typescript -import { wrapWithX402, BaseAccount } from '@atxp/client'; - -// Create an account -const account = new BaseAccount(rpcUrl, privateKey); - -// Wrap fetch with X402 support -const x402Fetch = wrapWithX402(fetch, { - account, - approvePayment: async (payment) => { - console.log(`Approve payment of ${payment.amount} ${payment.currency}?`); - return true; // or false to reject - }, - onPayment: async ({ payment }) => { - console.log('Payment successful:', payment); - }, - onPaymentFailure: async ({ payment, error }) => { - console.error('Payment failed:', error); - }, - logger: new ConsoleLogger(), - maxRetries: 1 -}); - -// Use like regular fetch -const response = await x402Fetch('https://x402-server.com/protected-resource'); -const data = await response.json(); -``` - -### Advanced Configuration - -```typescript -import { enableX402Support } from '@atxp/client'; - -const config = enableX402Support({ - account, - approvePayment: async (payment) => { - // Custom approval logic - if (payment.amount.gt(new BigNumber(10))) { - // Require user confirmation for payments > 10 USDC - return await promptUser(payment); - } - return true; - }, - onPayment: async ({ payment }) => { - // Track successful payments - await analytics.track('payment_success', { - amount: payment.amount.toString(), - currency: payment.currency, - resource: payment.resourceUrl - }); - }, - onPaymentFailure: async ({ payment, error }) => { - // Handle payment failures - await analytics.track('payment_failure', { - error: error.message, - resource: payment.resourceUrl - }); - }, - logger: customLogger, - maxRetries: 2 -}); - -// Use the wrapped fetch -const response = await config.fetchFn(url); -``` - -### Integration with Existing ATXP Client - -```typescript -import { atxpClient, wrapWithX402 } from '@atxp/client'; - -// Create ATXP client with X402 support -const clientConfig = buildClientConfig({ - account, - // ... other config - fetchFn: wrapWithX402(fetch, { - account, - approvePayment: async (payment) => true, - // ... X402 config - }) -}); - -const client = await atxpClient(clientConfig); -``` - -## Supported Account Types - -X402 support depends on the facilitator's capabilities. The following account types are expected to work: - -| Account Type | Network | Currency | Status | -|-------------|---------|----------|--------| -| BaseAccount | Base | USDC | ✅ Supported | -| SolanaAccount | Solana | USDC | ✅ Supported | -| ATXPAccount | Base | USDC | ✅ Supported | - -Note: Actual compatibility depends on the X402 facilitator implementation. - -## Payment Approval Strategies - -### Automatic Approval - -```typescript -approvePayment: async (payment) => { - // Auto-approve small payments - const threshold = new BigNumber(1); // 1 USDC - return payment.amount.lte(threshold); -} -``` - -### User Confirmation - -```typescript -approvePayment: async (payment) => { - // Show confirmation dialog - const message = `Approve ${payment.amount} ${payment.currency} payment to access ${payment.resourceName}?`; - return await showConfirmDialog(message); -} -``` - -### Whitelist-based - -```typescript -const trustedServers = ['https://trusted1.com', 'https://trusted2.com']; - -approvePayment: async (payment) => { - const url = new URL(payment.resourceUrl); - return trustedServers.includes(url.origin); -} -``` - -## Error Handling - -The X402 wrapper handles various error scenarios: - -```typescript -onPaymentFailure: async ({ payment, error }) => { - if (error.message.includes('No payment maker')) { - console.error('Unsupported network/currency combination'); - } else if (error.message.includes('Payment not approved')) { - console.log('User rejected payment'); - } else if (error.message.includes('Insufficient funds')) { - console.error('Not enough balance'); - } else { - console.error('Payment failed:', error); - } -} -``` - -## Security Considerations - -1. **Payment Approval**: Always implement proper payment approval logic -2. **Amount Validation**: Verify payment amounts match expected values -3. **Recipient Validation**: Ensure payments go to legitimate recipients -4. **Replay Protection**: Facilitators should prevent payment replay attacks -5. **Private Keys**: Never expose private keys in client-side code - -## Testing - -### Mock X402 Server - -Use the provided example server for testing: - -```bash -cd examples/x402-server -npm install -npm run dev -``` - -### Test Client - -```bash -cd examples/x402-server -npm run test-client -``` - -### Unit Testing - -```typescript -import { wrapWithX402 } from '@atxp/client'; -import { MockAccount } from '@atxp/client/testing'; - -describe('X402 Integration', () => { - it('handles payment challenges', async () => { - const mockAccount = new MockAccount(); - const mockFetch = jest.fn() - .mockReturnValueOnce({ - status: 402, - headers: new Headers({ - 'X-Payment': JSON.stringify({ - network: 'base', - currency: 'USDC', - amount: '1', - recipient: '0x...' - }) - }) - }) - .mockReturnValueOnce({ - ok: true, - json: async () => ({ data: 'protected' }) - }); - - const x402Fetch = wrapWithX402(mockFetch, { - account: mockAccount, - approvePayment: async () => true - }); - - const response = await x402Fetch('https://example.com/protected'); - const data = await response.json(); - - expect(data).toEqual({ data: 'protected' }); - expect(mockFetch).toHaveBeenCalledTimes(2); - }); -}); -``` - -## Migration Guide - -### For Existing ATXP Users - -1. Update your PaymentMaker implementations if you have custom ones -2. Add X402 wrapper to your fetch configuration if needed -3. No changes required if not using X402 servers - -### For X402 Server Operators - -1. Implement standard X402 challenge/response flow -2. Use a compatible facilitator that supports Base/Solana -3. Follow the example server implementation - -## Troubleshooting - -### Common Issues - -| Issue | Solution | -|-------|----------| -| "No payment maker found" | Ensure account has payment maker for required network/currency | -| "Payment not approved" | Check approvePayment callback logic | -| "Insufficient funds" | Ensure account has enough balance | -| "Invalid signature" | Verify facilitator supports your account type | -| "Transaction reverted" | Check recipient address and amount | - -### Debug Logging - -Enable detailed logging for troubleshooting: - -```typescript -import { ConsoleLogger } from '@atxp/common'; - -const logger = new ConsoleLogger(); -logger.level = 'debug'; - -const x402Fetch = wrapWithX402(fetch, { - account, - logger, - // ... other config -}); -``` - -## FAQ - -**Q: Can I use X402 with existing ATXP servers?** -A: No, X402 and ATXP are different protocols. X402 servers specifically implement the X402 payment challenge flow. - -**Q: What happens if payment fails?** -A: The original 402 response is returned, and the `onPaymentFailure` callback is triggered. - -**Q: Can I retry failed payments?** -A: Yes, configure `maxRetries` in the X402 config. - -**Q: Is the payment submitted immediately?** -A: With X402, the client only signs the payment. The facilitator submits it to the blockchain. - -**Q: Can I use custom facilitators?** -A: Yes, as long as they follow the X402 protocol specification. - -## References - -- [X402 Protocol Specification](https://x402.org/spec) -- [ATXP Documentation](https://atxp.ai/docs) -- [Example Implementation](../examples/x402-server) -- [Design Document](./x402-design.md) \ No newline at end of file From c8c753114752630a18231fb24c702b31d24f6101 Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 10:56:44 -0700 Subject: [PATCH 09/61] Restore /docs folder from main branch --- docs/PACKAGE_MANAGER_TESTING.md | 172 +++++++++++++++++++++++ docs/bundle-size-analysis.md | 236 ++++++++++++++++++++++++++++++++ docs/package-validation.md | 208 ++++++++++++++++++++++++++++ 3 files changed, 616 insertions(+) create mode 100644 docs/PACKAGE_MANAGER_TESTING.md create mode 100644 docs/bundle-size-analysis.md create mode 100644 docs/package-validation.md diff --git a/docs/PACKAGE_MANAGER_TESTING.md b/docs/PACKAGE_MANAGER_TESTING.md new file mode 100644 index 00000000..c75afd7d --- /dev/null +++ b/docs/PACKAGE_MANAGER_TESTING.md @@ -0,0 +1,172 @@ +# Package Manager Integration Testing + +This document describes the integration testing setup for ensuring ATXP packages work correctly across different package managers and prevent crypto module loading regressions. + +## Overview + +The integration tests verify that the `@atxp/common` package works correctly when installed by external consumers using different package managers (npm, pnpm, yarn, bun). + +## What Gets Tested + +### ✅ Package Managers +- **npm** - Standard Node.js package manager +- **pnpm** - Fast, disk space efficient package manager +- **yarn** - Alternative package manager with workspaces support +- **bun** - Fast all-in-one JavaScript runtime (when available) + +### ✅ Crypto Functionality +- **Environment Detection** - Correct Node.js/browser/React Native detection +- **UUID Generation** - `crypto.randomUUID()` produces valid RFC 4122 UUIDs +- **Hash Generation** - `crypto.digest()` SHA-256 hashing with expected outputs +- **Hex Encoding** - `crypto.toHex()` converts byte arrays to hex strings +- **Consistency** - Same inputs produce same outputs, different inputs differ + +### ✅ Cross-Platform Compatibility +- **Linux** (ubuntu-latest) +- **macOS** (macos-latest) +- **Windows** (windows-latest) +- **Node.js versions** 18, 20, 22 + +## Running Tests + +### Locally + +```bash +# Run all package manager integration tests +npm run test:package-managers + +# Run all integration tests (includes Redis tests) +npm run test:integration + +# Run specific package test manually in atxp-common package +cd packages/atxp-common +npm run test:package-managers +``` + +### In CI/CD + +The tests automatically run on: +- Push to `main` branch +- Pull requests to `main` branch +- Changes to platform crypto code +- Manual workflow dispatch + +## Test Structure + +### Test File Location +``` +packages/atxp-common/src/platform/packageManager.integration.test.ts +``` + +### How It Works + +1. **Build & Package** - Creates a tarball of the current `@atxp/common` package +2. **Create Test Projects** - Generates temporary external project directories +3. **Install Package** - Uses each package manager to install the tarball +4. **Run Crypto Tests** - Executes crypto functionality tests as external consumer +5. **Validate Results** - Ensures all crypto functions work correctly +6. **Cleanup** - Removes temporary files and directories + +### Test Timeout +- **Local**: 2 minutes per package manager test +- **CI**: 2 minutes per package manager test +- **Total runtime**: ~8-10 minutes for all package managers + +## Expected Test Output + +### Successful Test +``` +✅ should work when installed with npm +✅ should work when installed with pnpm +✅ should work when installed with yarn +✅ should work when installed with bun +``` + +### Test Failure Indicators +- ❌ `Cannot find module 'crypto'` errors +- ❌ Invalid UUID format errors +- ❌ Hash output mismatches +- ❌ Environment detection failures +- ❌ Package installation failures + +## Adding New Tests + +### Test a New Package Manager + +1. Add the package manager to the `PACKAGE_MANAGERS` array +2. Add installation command logic in the test +3. Update the GitHub Actions workflow to install the package manager + +### Test New Crypto Functionality + +1. Add test logic to `CONSUMER_TEST_SCRIPT` +2. Update expected outputs and validation +3. Document new test cases in this file + +## Troubleshooting + +### Common Issues + +**Test Timeout** +- Increase `TEST_TIMEOUT` or `testTimeout` in vitest config +- Check for slow package installations + +**Package Manager Not Found** +- Tests automatically skip unavailable package managers +- Install missing package managers for local development + +**Hash/UUID Validation Failures** +- Check for crypto implementation regressions +- Verify Web Crypto API vs Node.js crypto module behavior + +**Temporary Directory Cleanup** +- Tests clean up automatically in `afterAll()` +- Manual cleanup: `rm -rf /tmp/atxp-integration-*` + +### Debugging + +```bash +# Run with verbose output +npm run test:package-managers -- --reporter=verbose + +# Run single package manager test +npm run test:package-managers -- --grep "npm" + +# Keep temporary directories for inspection +# (modify test to comment out cleanup in afterAll) +``` + +## CI/CD Integration + +### GitHub Actions Workflow +- **File**: `.github/workflows/package-manager-integration.yml` +- **Triggers**: Push/PR to main, manual dispatch +- **Matrix**: Node.js 18/20/22, Ubuntu/macOS/Windows +- **Artifacts**: Test results uploaded on failure + +### Status Checks +The package manager integration tests are **required status checks** for: +- Pull requests modifying platform crypto code +- Releases of `@atxp/common` package + +## Performance Considerations + +- Tests run in parallel across Node.js versions +- Package installations are cached when possible +- Temporary directories are cleaned up promptly +- Tests skip unavailable package managers automatically + +## Regression Prevention + +These tests prevent regressions by: +1. **Catching crypto loading issues** before they reach consumers +2. **Validating cross-platform compatibility** on multiple OS/Node versions +3. **Testing real-world usage patterns** with actual package installations +4. **Automated CI/CD integration** prevents broken releases + +## Maintenance + +- **Update package manager versions** in GitHub Actions regularly +- **Add new Node.js versions** to test matrix as they're released +- **Review test timeouts** if CI becomes slow +- **Update expected test outputs** when crypto behavior changes intentionally \ No newline at end of file diff --git a/docs/bundle-size-analysis.md b/docs/bundle-size-analysis.md new file mode 100644 index 00000000..3c262128 --- /dev/null +++ b/docs/bundle-size-analysis.md @@ -0,0 +1,236 @@ +# Bundle Size Analysis + +This document describes the bundle size analysis tooling implemented for the ATXP SDK packages. + +## Overview + +The ATXP SDK uses [rollup-plugin-analyzer](https://www.npmjs.com/package/rollup-plugin-analyzer) to provide detailed bundle size analysis across all packages. This tooling helps monitor bundle sizes, identify optimization opportunities, and track size changes over time. + +## Features + +### 📊 Detailed Analysis +- **Bundle size**: Total bundle size after rollup processing +- **Code reduction**: Percentage reduction from original source +- **Module breakdown**: Visual chart showing size contribution per module +- **Module count**: Total number of modules in the bundle + +### 🔄 CI Integration +- Automated bundle analysis on pull requests +- Comparison between current and base branch +- Non-blocking analysis (informational only) +- PR comments with detailed reports + +### 🛠 Developer Tools +Multiple npm scripts for different analysis needs: +- `npm run size` - Quick analysis of all packages (live output during build) +- `npm run size:summary` - Summary view with charts (live output during build) +- `npm run size:detailed` - Detailed analysis with top 20 modules (live output during build) +- `npm run size:exports` - Include export usage analysis (live output during build) +- `npm run size:ci` - Generate comprehensive report saved to file with clear file path +- `npm run size:ci:show` - Show comprehensive report directly in terminal + +## Usage + +### Local Development + +#### Quick Analysis +```bash +# Analyze all packages with summary +npm run size:summary +``` + +#### Detailed Analysis +```bash +# Get detailed breakdown of largest modules +npm run size:detailed +``` + +#### Export Analysis +```bash +# See which exports are used/unused +npm run size:exports +``` + +#### CI-Style Analysis +```bash +# Generate markdown report saved to bundle-analysis/ directory +npm run size:ci + +# Show analysis report directly in terminal (no file saved) +npm run size:ci:show + +# Save to specific file +npm run size:ci -- --output=my-analysis.md + +# Get help with all options +npm run size:ci -- --help +``` + +**Output Options:** +- **Default**: Saves timestamped file to `bundle-analysis/` and shows file path +- **`--stdout`**: Prints analysis directly to terminal for immediate viewing +- **`--output=file`**: Saves to specific file location +- **`--json`**: Output in JSON format instead of markdown + +All analysis outputs are saved to the `bundle-analysis/` directory and are automatically ignored by git. + +### Single Package Analysis + +To analyze a specific package: + +```bash +cd packages/atxp-client +ANALYZE_BUNDLE=true npm run build +``` + +### Environment Variables + +The analyzer behavior can be customized with environment variables: + +- `ANALYZE_BUNDLE=true` - Enable bundle analysis +- `ANALYZE_SUMMARY_ONLY=false` - Show detailed module breakdown +- `ANALYZE_LIMIT=20` - Number of modules to show in detailed view +- `ANALYZE_SHOW_EXPORTS=true` - Include export usage information + +## CI Integration + +### GitHub Actions Workflow + +The `bundle-size.yml` workflow runs automatically on pull requests when: +- Package source code changes (`packages/*/src/**`) +- Build configuration changes (`rollup.config.js`, `package.json`) +- Bundle analysis configuration changes + +### Workflow Steps + +1. **Install dependencies** and build packages +2. **Analyze current branch** using rollup-plugin-analyzer +3. **Switch to base branch** and analyze for comparison +4. **Generate comparison report** showing changes +5. **Post/update PR comment** with analysis results +6. **Upload artifacts** for manual inspection + +### Output Directory Structure + +Bundle analysis files are organized in the `bundle-analysis/` directory: + +``` +bundle-analysis/ +├── bundle-analysis-2025-01-15T10-30-45.md # Timestamped reports +├── bundle-analysis-2025-01-15T11-15-20.json # JSON format outputs +├── current-analysis.md # CI: Current branch analysis +├── base-analysis.md # CI: Base branch analysis +└── bundle-report.md # CI: Final comparison report +``` + +**Note**: All files in `bundle-analysis/` are automatically ignored by git to prevent committing generated analysis files. + +### PR Comments + +The workflow automatically posts/updates PR comments with: +- Current bundle size analysis for all packages +- Visual charts showing module size contributions +- Comparison with base branch (when available) +- Tips for bundle size optimization + +## Understanding the Output + +### Analysis Chart Example +``` +----------------------------- +Rollup File Analysis +----------------------------- +bundle size: 38.282 KB +original size: 40.592 KB +code reduction: 5.69 % +module count: 12 + +/src/oAuthResource.ts +█████████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 35.18 % (13.466 KB) +/src/platform/index.ts +██████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 20.79 % (7.958 KB) +/src/mcpJson.ts +██████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 12.78 % (4.893 KB) +``` + +### Key Metrics + +- **Bundle Size**: Final size after bundling and tree-shaking +- **Original Size**: Sum of all source file sizes +- **Code Reduction**: Percentage saved through bundling optimizations +- **Module Count**: Number of distinct modules in the bundle +- **Module Chart**: Visual representation of each module's contribution + +### Optimization Insights + +The analysis helps identify: +1. **Largest modules** that could benefit from code splitting +2. **Unused code** that could be tree-shaken +3. **Duplicate dependencies** across packages +4. **Bundle growth** over time through PR comparisons + +## Bundle Size Thresholds + +### Current Package Sizes (approx.) + +| Package | Bundle Size | Status | Notes | +|---------|-------------|---------|-------| +| @atxp/common | ~39KB | ✅ Good | Core utilities and types | +| @atxp/redis | ~6KB | ✅ Good | Redis OAuth implementation | +| @atxp/sqlite | ~10KB | ✅ Good | SQLite OAuth implementation | +| @atxp/base | ~25KB | ✅ Good | Base blockchain integration | +| @atxp/server | ~404KB | 🔴 Large | MCP server with dependencies | +| @atxp/client | ~576KB | 🔴 Large | Client with blockchain libs | + +### Size Categories + +- ✅ **Good**: < 100KB raw bundle size +- 🟡 **Warning**: 100KB - 500KB raw bundle size +- 🔴 **Large**: > 500KB raw bundle size + +> **Note**: Large sizes for client/server packages are expected due to blockchain and MCP dependencies. The analysis helps track if they grow unexpectedly. + +## Optimization Strategies + +### Tree Shaking +- Use explicit named exports (already implemented) +- Avoid `export *` patterns +- Mark side-effect-free packages with `"sideEffects": false` + +### Code Splitting +- Use dynamic imports for optional features +- Separate blockchain-specific code +- Lazy load large dependencies + +### Dependency Management +- Audit large dependencies regularly +- Use smaller alternatives when possible +- Externalize dependencies that consumers should provide + +### Bundle Analysis +- Monitor size changes in PRs +- Profile largest modules for optimization opportunities +- Track export usage to identify unused code + +## Troubleshooting + +### Analysis Not Running +1. Ensure `ANALYZE_BUNDLE=true` environment variable is set +2. Check that `rollup-plugin-analyzer` is installed +3. Verify rollup configuration includes the analyzer plugin + +### Missing Analysis Output +1. Check that build completes successfully +2. Look for analysis output in build logs +3. Verify analyzer plugin configuration + +### CI Workflow Issues +1. Check workflow file syntax in `.github/workflows/bundle-size.yml` +2. Ensure PR targets correct base branch +3. Check GitHub Actions logs for detailed error messages + +## Related Documentation + +- [Rollup Plugin Analyzer Documentation](https://www.npmjs.com/package/rollup-plugin-analyzer) +- [Bundle Size Best Practices](https://web.dev/reduce-javascript-payloads-with-tree-shaking/) +- [GitHub Actions Workflow Syntax](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions) \ No newline at end of file diff --git a/docs/package-validation.md b/docs/package-validation.md new file mode 100644 index 00000000..aca760a8 --- /dev/null +++ b/docs/package-validation.md @@ -0,0 +1,208 @@ +# Package Validation and Testing + +This document describes the comprehensive package validation and testing system implemented for ATXP packages. + +## Overview + +The package validation system ensures that all ATXP packages are correctly built, packaged, and can be successfully installed and used by consumers. It includes automated validation, testing, and verification scripts. + +## Features Implemented + +### 1. Package Scripts + +All packages now include these standardized scripts: + +- `prepack`: Runs build and typecheck before packaging +- `pack:dry`: Performs a dry-run pack to validate package contents without creating actual tarball + +**Example package.json scripts section:** +```json +{ + "scripts": { + "build": "rollup -c", + "typecheck": "tsc --noEmit", + "test": "vitest run", + "prepack": "npm run build && npm run typecheck", + "pack:dry": "npm pack --dry-run" + } +} +``` + +### 2. Validation Scripts + +#### Package Validation Script (`scripts/validate-packages.js`) +Comprehensive validation of package structure and configuration: + +- ✅ **Package.json Validation**: Checks required fields, scripts, and structure +- ✅ **Build Artifacts**: Verifies all required dist files exist +- ✅ **TypeScript Declarations**: Ensures .d.ts files are present +- ✅ **Export Maps**: Validates exports configuration +- ✅ **Dependency Management**: Checks for proper peer dependencies +- ✅ **File Inclusion**: Verifies files array includes necessary assets + +**Usage:** +```bash +# Validate all packages +npm run validate:packages + +# Validate specific package +npm run validate:packages atxp-client +``` + +#### Package Installation Test (`scripts/test-package-installation.js`) +End-to-end testing of package installation and usage: + +- 📦 **Pack Testing**: Creates actual package tarballs +- 📥 **Installation Testing**: Installs packages in isolated environments +- 🧪 **Import Testing**: Verifies packages can be imported and used +- 🧹 **Cleanup**: Automatically cleans up test artifacts + +**Usage:** +```bash +# Test all packages +npm run test:package-install + +# Test specific package +npm run test:package-install atxp-server +``` + +### 3. Root Scripts + +New scripts added to root package.json for monorepo management: + +```json +{ + "scripts": { + "validate:packages": "node scripts/validate-packages.js", + "test:package-install": "node scripts/test-package-installation.js", + "pack:all": "npm run pack:dry --workspaces --if-present", + "prepack:all": "npm run prepack --workspaces --if-present" + } +} +``` + +## Validation Checks + +### Required Package Fields +- `name`, `version`, `description`, `license` +- `type: "module"` for ESM support +- `main`, `module`, `types` entry points +- `exports` map configuration +- `files` array including "dist" + +### Required Scripts +- `build`: Build the package +- `typecheck`: TypeScript type checking +- `lint`: Code linting +- `test`: Run tests +- `prepack`: Pre-packaging validation +- `pack:dry`: Dry-run packaging + +### Required Build Artifacts +- `dist/index.js`: ESM entry point +- `dist/index.cjs`: CommonJS entry point +- `dist/index.d.ts`: TypeScript declarations + +### Export Map Validation +- `types`: Points to declaration files +- `import`: Points to ESM build +- `require`: Points to CommonJS build + +## How It Works + +### Prepack Process +When `npm pack` is run (or triggered by `npm publish`): + +1. **prepack script runs automatically** + - Builds the package (`npm run build`) + - Runs type checking (`npm run typecheck`) + - Fails if build or types have errors + +2. **Package creation** + - Creates tarball with only files listed in `files` array + - Includes `dist/` directory with build artifacts + +### Installation Testing Process +The installation test script: + +1. **Validates package** using pack dry-run +2. **Creates actual package** with `npm pack` +3. **Sets up test environment** in temporary directory +4. **Installs package** from tarball +5. **Tests imports** to verify package works +6. **Cleans up** test artifacts + +### Continuous Validation +- All builds now run validation before completion +- Pack dry-run ensures packages are valid before publishing +- Installation tests verify end-to-end functionality + +## Benefits + +### For Development +- ✅ **Early Error Detection**: Catches packaging issues before publishing +- ✅ **Consistent Structure**: Ensures all packages follow same patterns +- ✅ **Automated Validation**: Reduces manual testing overhead + +### For Consumers +- ✅ **Reliable Packages**: Guaranteed to install and import correctly +- ✅ **Proper TypeScript Support**: Declaration files always included +- ✅ **Correct Module Support**: Both ESM and CommonJS entry points + +### for CI/CD +- ✅ **Automated Checks**: Can be integrated into CI pipelines +- ✅ **Fast Feedback**: Quick validation without full publish cycle +- ✅ **Comprehensive Coverage**: Tests entire package lifecycle + +## Usage Examples + +### Development Workflow +```bash +# During development +npm run build # Build packages +npm run validate:packages # Validate package structure + +# Before publishing +npm run pack:all # Dry-run pack all packages +npm run test:package-install # Test installation process +``` + +### CI Integration +```bash +# In CI pipeline +npm run build +npm run validate:packages +npm run test:package-install +# Only publish if all validations pass +``` + +### Single Package Testing +```bash +# Test specific package +npm run validate:packages atxp-client +npm run test:package-install atxp-client + +# In package directory +npm run prepack # Build and typecheck +npm run pack:dry # Test packaging +``` + +## Error Handling + +The validation scripts provide detailed error messages: + +- **Validation Errors**: Missing fields, invalid structure, missing files +- **Build Errors**: TypeScript errors, build failures +- **Installation Errors**: Package installation or import failures +- **Warnings**: Best practice suggestions, dependency recommendations + +## Integration with Existing Workflow + +This system integrates seamlessly with existing package management: + +- **Existing Scripts**: All existing scripts continue to work unchanged +- **Build Process**: Uses existing rollup build configuration +- **Publishing**: Works with existing `npm publish` workflow +- **Development**: Adds validation without disrupting dev experience + +The validation system ensures that ATXP packages are always correctly built, properly configured, and ready for consumer use. \ No newline at end of file From 5ba867b2573ff1a24f56d1800712f57187d4074f Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 10:58:21 -0700 Subject: [PATCH 10/61] Update package-lock.json after rebase --- package-lock.json | 854 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 726 insertions(+), 128 deletions(-) diff --git a/package-lock.json b/package-lock.json index f0d31b25..9fb3196b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@atxp/atxp-monorepo", - "version": "0.3.0", + "version": "0.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@atxp/atxp-monorepo", - "version": "0.3.0", + "version": "0.4.0", "license": "MIT", "workspaces": [ "packages/atxp-common", @@ -14,7 +14,9 @@ "packages/atxp-redis", "packages/atxp-server", "packages/atxp-client", - "packages/atxp-base" + "packages/atxp-base", + "packages/atxp-express", + "packages/atxp-cloudflare" ], "dependencies": { "dotenv": "^16.5.0" @@ -70,10 +72,57 @@ "version": "1.11.0", "license": "MIT" }, + "node_modules/@ai-sdk/gateway": { + "version": "1.0.23", + "resolved": "https://registry.npmjs.org/@ai-sdk/gateway/-/gateway-1.0.23.tgz", + "integrity": "sha512-ynV7WxpRK2zWLGkdOtrU2hW22mBVkEYVS3iMg1+ZGmAYSgzCqzC74bfOJZ2GU1UdcrFWUsFI9qAYjsPkd+AebA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@ai-sdk/provider": "2.0.0", + "@ai-sdk/provider-utils": "3.0.9" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4" + } + }, + "node_modules/@ai-sdk/provider": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-2.0.0.tgz", + "integrity": "sha512-6o7Y2SeO9vFKB8lArHXehNuusnpddKPk7xqL7T2/b+OvXMRIXUO1rR4wcv1hAFUAT9avGZshty3Wlua/XA7TvA==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "json-schema": "^0.4.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@ai-sdk/provider-utils": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-3.0.9.tgz", + "integrity": "sha512-Pm571x5efqaI4hf9yW4KsVlDBDme8++UepZRnq+kqVBWWjgvGhQlzU8glaFq0YJEB9kkxZHbRRyVeHoV2sRYaQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@ai-sdk/provider": "2.0.0", + "@standard-schema/spec": "^1.0.0", + "eventsource-parser": "^3.0.5" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4" + } + }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "license": "Apache-2.0", - "peer": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" @@ -107,10 +156,18 @@ "resolved": "packages/atxp-client", "link": true }, + "node_modules/@atxp/cloudflare": { + "resolved": "packages/atxp-cloudflare", + "link": true + }, "node_modules/@atxp/common": { "resolved": "packages/atxp-common", "link": true }, + "node_modules/@atxp/express": { + "resolved": "packages/atxp-express", + "link": true + }, "node_modules/@atxp/redis": { "resolved": "packages/atxp-redis", "link": true @@ -402,7 +459,6 @@ "node_modules/@babel/helper-string-parser": { "version": "7.27.1", "license": "MIT", - "peer": true, "engines": { "node": ">=6.9.0" } @@ -528,7 +584,6 @@ "node_modules/@babel/parser": { "version": "7.27.5", "license": "MIT", - "peer": true, "dependencies": { "@babel/types": "^7.27.3" }, @@ -1437,6 +1492,19 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/runtime-corejs3": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.28.4.tgz", + "integrity": "sha512-h7iEYiW4HebClDEhtvFObtPmIvrd1SSfpI9EhOeKk4CtIK/ngBWFpuhCzhdmRKtg71ylcue+9I6dv54XYO1epQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "core-js-pure": "^3.43.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/template": { "version": "7.27.2", "license": "MIT", @@ -1488,7 +1556,6 @@ "node_modules/@babel/types": { "version": "7.27.3", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" @@ -1560,6 +1627,22 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/@bcoe/v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", + "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@cloudflare/workers-types": { + "version": "4.20250918.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20250918.0.tgz", + "integrity": "sha512-mqTyfBPYUrUfHwnmLOnBTBrtEiuO45MIVxvbJ1blivIZC+0YMFskQnrcPn1txQM2S4LKnwmFv1XMgjt0qMma1Q==", + "license": "MIT OR Apache-2.0" + }, "node_modules/@csstools/color-helpers": { "version": "5.0.2", "dev": true, @@ -3291,7 +3374,6 @@ "node_modules/@isaacs/cliui": { "version": "8.0.2", "license": "ISC", - "peer": true, "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", @@ -3307,7 +3389,6 @@ "node_modules/@isaacs/cliui/node_modules/ansi-regex": { "version": "6.1.0", "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -3318,7 +3399,6 @@ "node_modules/@isaacs/cliui/node_modules/ansi-styles": { "version": "6.2.1", "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -3328,13 +3408,11 @@ }, "node_modules/@isaacs/cliui/node_modules/emoji-regex": { "version": "9.2.2", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@isaacs/cliui/node_modules/string-width": { "version": "5.1.2", "license": "MIT", - "peer": true, "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -3350,7 +3428,6 @@ "node_modules/@isaacs/cliui/node_modules/strip-ansi": { "version": "7.1.0", "license": "MIT", - "peer": true, "dependencies": { "ansi-regex": "^6.0.1" }, @@ -3364,7 +3441,6 @@ "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { "version": "8.1.0", "license": "MIT", - "peer": true, "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -3414,7 +3490,6 @@ "node_modules/@istanbuljs/schema": { "version": "0.1.3", "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -3595,7 +3670,6 @@ "node_modules/@jridgewell/gen-mapping": { "version": "0.3.8", "license": "MIT", - "peer": true, "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -3608,7 +3682,6 @@ "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "license": "MIT", - "peer": true, "engines": { "node": ">=6.0.0" } @@ -3616,7 +3689,6 @@ "node_modules/@jridgewell/set-array": { "version": "1.2.1", "license": "MIT", - "peer": true, "engines": { "node": ">=6.0.0" } @@ -3635,16 +3707,19 @@ "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "license": "MIT", - "peer": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "node_modules/@modelcontextprotocol/sdk": { - "version": "1.15.0", + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.18.1.tgz", + "integrity": "sha512-d//GE8/Yh7aC3e7p+kZG8JqqEAwwDUmAfvH1quogtbk+ksS6E0RR6toKKESPYYZVre0meqkJb27zb+dhqE9Sgw==", "license": "MIT", "dependencies": { "ajv": "^6.12.6", @@ -3729,6 +3804,16 @@ "node": ">= 8" } }, + "node_modules/@opentelemetry/api": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/@paralleldrive/cuid2": { "version": "2.2.2", "dev": true, @@ -4843,6 +4928,13 @@ "node": ">=18" } }, + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", + "license": "MIT", + "peer": true + }, "node_modules/@swc/helpers": { "version": "0.5.17", "dev": true, @@ -4905,6 +4997,16 @@ "@types/node": "*" } }, + "node_modules/@types/chai": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.2.tgz", + "integrity": "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*" + } + }, "node_modules/@types/connect": { "version": "3.4.38", "dev": true, @@ -4923,6 +5025,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -5360,13 +5469,112 @@ "@urql/core": "^5.0.0" } }, + "node_modules/@vitest/coverage-v8": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.2.4.tgz", + "integrity": "sha512-EyF9SXU6kS5Ku/U82E259WSnvg6c8KTjppUncuNdm5QHpe17mwREHnjDzozC8x9MZ0xfBUFSaLkRv4TMA75ALQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.3.0", + "@bcoe/v8-coverage": "^1.0.2", + "ast-v8-to-istanbul": "^0.3.3", + "debug": "^4.4.1", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-lib-source-maps": "^5.0.6", + "istanbul-reports": "^3.1.7", + "magic-string": "^0.30.17", + "magicast": "^0.3.5", + "std-env": "^3.9.0", + "test-exclude": "^7.0.1", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/browser": "3.2.4", + "vitest": "3.2.4" + }, + "peerDependenciesMeta": { + "@vitest/browser": { + "optional": true + } + } + }, + "node_modules/@vitest/coverage-v8/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@vitest/coverage-v8/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vitest/coverage-v8/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vitest/coverage-v8/node_modules/test-exclude": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", + "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^10.4.1", + "minimatch": "^9.0.4" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@vitest/expect": { - "version": "3.1.3", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz", + "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.1.3", - "@vitest/utils": "3.1.3", + "@types/chai": "^5.2.2", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" }, @@ -5375,11 +5583,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "3.1.3", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz", + "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.1.3", + "@vitest/spy": "3.2.4", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, @@ -5388,7 +5598,7 @@ }, "peerDependencies": { "msw": "^2.4.9", - "vite": "^5.0.0 || ^6.0.0" + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "peerDependenciesMeta": { "msw": { @@ -5400,7 +5610,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "3.1.3", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz", + "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", "dev": true, "license": "MIT", "dependencies": { @@ -5411,23 +5623,28 @@ } }, "node_modules/@vitest/runner": { - "version": "3.1.3", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.4.tgz", + "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.1.3", - "pathe": "^2.0.3" + "@vitest/utils": "3.2.4", + "pathe": "^2.0.3", + "strip-literal": "^3.0.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/snapshot": { - "version": "3.1.3", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.4.tgz", + "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.1.3", + "@vitest/pretty-format": "3.2.4", "magic-string": "^0.30.17", "pathe": "^2.0.3" }, @@ -5436,23 +5653,27 @@ } }, "node_modules/@vitest/spy": { - "version": "3.1.3", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz", + "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==", "dev": true, "license": "MIT", "dependencies": { - "tinyspy": "^3.0.2" + "tinyspy": "^4.0.3" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/utils": { - "version": "3.1.3", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz", + "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.1.3", - "loupe": "^3.1.3", + "@vitest/pretty-format": "3.2.4", + "loupe": "^3.1.4", "tinyrainbow": "^2.0.0" }, "funding": { @@ -5551,6 +5772,64 @@ "node": ">= 8.0.0" } }, + "node_modules/agents": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/agents/-/agents-0.1.4.tgz", + "integrity": "sha512-zwNfh69H73DZFrl2c3d0Qd6RDCxtwS+OZ/bPSU/wSDGgWaQx7aOP4cqYLo7uqTpIN/pGQXHznXudrD8z9Do3LA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@modelcontextprotocol/sdk": "^1.18.0", + "ai": "5.0.44", + "cron-schedule": "^5.0.4", + "mimetext": "^3.0.27", + "nanoid": "^5.1.5", + "partyserver": "^0.0.74", + "partysocket": "1.1.5", + "zod": "^3.25.76" + }, + "peerDependencies": { + "react": "*" + } + }, + "node_modules/agents/node_modules/nanoid": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.5.tgz", + "integrity": "sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "bin": { + "nanoid": "bin/nanoid.js" + }, + "engines": { + "node": "^18 || >=20" + } + }, + "node_modules/ai": { + "version": "5.0.44", + "resolved": "https://registry.npmjs.org/ai/-/ai-5.0.44.tgz", + "integrity": "sha512-l/rdoM4LcRpsRBVvZQBwSU73oNoFGlWj+PcH86QRzxDGJgZqgGItWO0QcKjBNcLDmUjGN1VYd/8J0TAXHJleRQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@ai-sdk/gateway": "1.0.23", + "@ai-sdk/provider": "2.0.0", + "@ai-sdk/provider-utils": "3.0.9", + "@opentelemetry/api": "1.9.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4" + } + }, "node_modules/ajv": { "version": "6.12.6", "license": "MIT", @@ -5598,7 +5877,6 @@ "node_modules/ansi-regex": { "version": "5.0.1", "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -5771,12 +6049,33 @@ }, "node_modules/assertion-error": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, "license": "MIT", "engines": { "node": ">=12" } }, + "node_modules/ast-v8-to-istanbul": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.5.tgz", + "integrity": "sha512-9SdXjNheSiE8bALAQCQQuT6fgQaoxJh7IRYrRGZ8/9nv8WhJeC1aXAwN8TbaOssGOukUvyvnkgD9+Yuykvl1aA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.30", + "estree-walker": "^3.0.3", + "js-tokens": "^9.0.1" + } + }, + "node_modules/ast-v8-to-istanbul/node_modules/js-tokens": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", + "dev": true, + "license": "MIT" + }, "node_modules/async-function": { "version": "1.0.0", "dev": true, @@ -6358,6 +6657,8 @@ }, "node_modules/cac": { "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", "dev": true, "license": "MIT", "engines": { @@ -6464,7 +6765,9 @@ "peer": true }, "node_modules/chai": { - "version": "5.2.0", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", + "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", "dev": true, "license": "MIT", "dependencies": { @@ -6475,7 +6778,7 @@ "pathval": "^2.0.0" }, "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/chalk": { @@ -6491,6 +6794,8 @@ }, "node_modules/check-error": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", "dev": true, "license": "MIT", "engines": { @@ -6832,6 +7137,18 @@ "url": "https://opencollective.com/core-js" } }, + "node_modules/core-js-pure": { + "version": "3.45.1", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.45.1.tgz", + "integrity": "sha512-OHnWFKgTUshEU8MK+lOs1H8kC8GkTi9Z1tvNkxrCcw9wl3MJIO7q2ld77wjWn4/xuGrVu2X+nME1iIIPBSdyEQ==", + "hasInstallScript": true, + "license": "MIT", + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/cors": { "version": "2.8.5", "license": "MIT", @@ -6857,6 +7174,16 @@ "node": ">=4" } }, + "node_modules/cron-schedule": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cron-schedule/-/cron-schedule-5.0.4.tgz", + "integrity": "sha512-nH0a49E/kSVk6BeFgKZy4uUsy6D2A16p120h5bYD9ILBhQu7o2sJFH+WI4R731TSBQ0dB1Ik7inB/dRAB4C8QQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + } + }, "node_modules/cross-fetch": { "version": "3.2.0", "dev": true, @@ -7002,7 +7329,9 @@ } }, "node_modules/debug": { - "version": "4.4.0", + "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" @@ -7038,6 +7367,8 @@ }, "node_modules/deep-eql": { "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", "dev": true, "license": "MIT", "engines": { @@ -7233,8 +7564,7 @@ }, "node_modules/eastasianwidth": { "version": "0.2.0", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/ee-first": { "version": "1.1.1", @@ -7247,8 +7577,7 @@ }, "node_modules/emoji-regex": { "version": "8.0.0", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/encodeurl": { "version": "2.0.0", @@ -7384,6 +7713,8 @@ }, "node_modules/es-module-lexer": { "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", "dev": true, "license": "MIT" }, @@ -7874,6 +8205,8 @@ }, "node_modules/estree-walker": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", "dev": true, "license": "MIT", "dependencies": { @@ -7895,6 +8228,13 @@ "node": ">= 0.6" } }, + "node_modules/event-target-polyfill": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/event-target-polyfill/-/event-target-polyfill-0.0.4.tgz", + "integrity": "sha512-Gs6RLjzlLRdT8X9ZipJdIZI/Y6/HhRLyq9RdDlCsnpxr/+Nn6bU2EFGuC94GjxqhM+Nmij2Vcq98yoHrU8uNFQ==", + "license": "MIT", + "peer": true + }, "node_modules/event-target-shim": { "version": "5.0.1", "license": "MIT", @@ -7918,7 +8258,9 @@ } }, "node_modules/eventsource-parser": { - "version": "3.0.2", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz", + "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==", "license": "MIT", "engines": { "node": ">=18.0.0" @@ -8369,9 +8711,14 @@ } }, "node_modules/fdir": { - "version": "6.4.4", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, "peerDependencies": { "picomatch": "^3 || ^4" }, @@ -8491,7 +8838,6 @@ "node_modules/foreground-child": { "version": "3.3.1", "license": "ISC", - "peer": true, "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" @@ -8506,7 +8852,6 @@ "node_modules/foreground-child/node_modules/signal-exit": { "version": "4.1.0", "license": "ISC", - "peer": true, "engines": { "node": ">=14" }, @@ -8967,6 +9312,13 @@ "node": ">=18" } }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, "node_modules/http-errors": { "version": "2.0.0", "license": "MIT", @@ -9332,7 +9684,6 @@ "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -9606,7 +9957,6 @@ "node_modules/istanbul-lib-coverage": { "version": "3.2.2", "license": "BSD-3-Clause", - "peer": true, "engines": { "node": ">=8" } @@ -9634,10 +9984,66 @@ "semver": "bin/semver.js" } }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/jackspeak": { "version": "3.4.3", "license": "BlueOak-1.0.0", - "peer": true, "dependencies": { "@isaacs/cliui": "^8.0.2" }, @@ -9973,7 +10379,6 @@ }, "node_modules/js-base64": { "version": "3.7.7", - "dev": true, "license": "BSD-3-Clause" }, "node_modules/js-tokens": { @@ -10116,6 +10521,13 @@ "license": "MIT", "peer": true }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "license": "(AFL-2.1 OR BSD-3-Clause)", + "peer": true + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "license": "MIT" @@ -10375,7 +10787,9 @@ } }, "node_modules/loupe": { - "version": "3.1.3", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", + "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", "dev": true, "license": "MIT" }, @@ -10395,6 +10809,34 @@ "@jridgewell/sourcemap-codec": "^1.5.0" } }, + "node_modules/magicast": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz", + "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.25.4", + "@babel/types": "^7.25.4", + "source-map-js": "^1.2.0" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/makeerror": { "version": "1.0.12", "license": "BSD-3-Clause", @@ -10863,6 +11305,46 @@ "node": ">= 0.6" } }, + "node_modules/mimetext": { + "version": "3.0.27", + "resolved": "https://registry.npmjs.org/mimetext/-/mimetext-3.0.27.tgz", + "integrity": "sha512-mUhWAsZD1N/K6dbN4+a5Yq78OPnYQw1ubOSMasBntsLQ2S7KVNlvDEA8dwpr4a7PszWMzeslKahAprtwYMgaBA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.26.0", + "@babel/runtime-corejs3": "^7.26.0", + "js-base64": "^3.7.7", + "mime-types": "^2.1.35" + }, + "funding": { + "type": "patreon", + "url": "https://patreon.com/muratgozel" + } + }, + "node_modules/mimetext/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", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimetext/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", + "peer": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/mimic-fn": { "version": "1.2.0", "license": "MIT", @@ -10903,7 +11385,6 @@ "node_modules/minipass": { "version": "7.1.2", "license": "ISC", - "peer": true, "engines": { "node": ">=16 || 14 >=14.17" } @@ -11552,8 +12033,7 @@ }, "node_modules/package-json-from-dist": { "version": "1.0.1", - "license": "BlueOak-1.0.0", - "peer": true + "license": "BlueOak-1.0.0" }, "node_modules/parent-module": { "version": "1.0.1", @@ -11615,6 +12095,48 @@ "node": ">= 0.8" } }, + "node_modules/partyserver": { + "version": "0.0.74", + "resolved": "https://registry.npmjs.org/partyserver/-/partyserver-0.0.74.tgz", + "integrity": "sha512-5cx+Hpg8UWFh/S6azhbnvrTAfM0k+/NxEfyaLwHdqQEzvYVFmLkLCZNbolyc0NKfDhU27a0itEJfz0jF8cFuFw==", + "license": "ISC", + "peer": true, + "dependencies": { + "nanoid": "^5.1.5" + }, + "peerDependencies": { + "@cloudflare/workers-types": "^4.20240729.0" + } + }, + "node_modules/partyserver/node_modules/nanoid": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.5.tgz", + "integrity": "sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "bin": { + "nanoid": "bin/nanoid.js" + }, + "engines": { + "node": "^18 || >=20" + } + }, + "node_modules/partysocket": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/partysocket/-/partysocket-1.1.5.tgz", + "integrity": "sha512-8uw9foq9bij4sKLCtTSHvyqMrMTQ5FJjrHc7BjoM2s95Vu7xYCN63ABpI7OZHC7ZMP5xaom/A+SsoFPXmTV6ZQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "event-target-polyfill": "^0.0.4" + } + }, "node_modules/path-exists": { "version": "4.0.0", "license": "MIT", @@ -11644,7 +12166,6 @@ "node_modules/path-scurry": { "version": "1.11.1", "license": "BlueOak-1.0.0", - "peer": true, "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" @@ -11658,8 +12179,7 @@ }, "node_modules/path-scurry/node_modules/lru-cache": { "version": "10.4.3", - "license": "ISC", - "peer": true + "license": "ISC" }, "node_modules/path-to-regexp": { "version": "8.2.0", @@ -11670,11 +12190,15 @@ }, "node_modules/pathe": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "dev": true, "license": "MIT" }, "node_modules/pathval": { - "version": "2.0.0", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", "dev": true, "license": "MIT", "engines": { @@ -11686,7 +12210,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.2", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", "engines": { @@ -11741,7 +12267,9 @@ } }, "node_modules/postcss": { - "version": "8.5.3", + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "dev": true, "funding": [ { @@ -11759,7 +12287,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.8", + "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -13185,7 +13713,6 @@ "node_modules/string-width": { "version": "4.2.3", "license": "MIT", - "peer": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -13199,7 +13726,6 @@ "name": "string-width", "version": "4.2.3", "license": "MIT", - "peer": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -13265,7 +13791,6 @@ "node_modules/strip-ansi": { "version": "6.0.1", "license": "MIT", - "peer": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -13277,7 +13802,6 @@ "name": "strip-ansi", "version": "6.0.1", "license": "MIT", - "peer": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -13300,6 +13824,26 @@ "node": ">=0.10.0" } }, + "node_modules/strip-literal": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.0.0.tgz", + "integrity": "sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^9.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/strip-literal/node_modules/js-tokens": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", + "dev": true, + "license": "MIT" + }, "node_modules/structured-headers": { "version": "0.4.1", "license": "MIT", @@ -13646,12 +14190,14 @@ "license": "MIT" }, "node_modules/tinyglobby": { - "version": "0.2.13", + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "dev": true, "license": "MIT", "dependencies": { - "fdir": "^6.4.4", - "picomatch": "^4.0.2" + "fdir": "^6.5.0", + "picomatch": "^4.0.3" }, "engines": { "node": ">=12.0.0" @@ -13661,7 +14207,9 @@ } }, "node_modules/tinypool": { - "version": "1.0.2", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", "dev": true, "license": "MIT", "engines": { @@ -13677,7 +14225,9 @@ } }, "node_modules/tinyspy": { - "version": "3.0.2", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.4.tgz", + "integrity": "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==", "dev": true, "license": "MIT", "engines": { @@ -14158,22 +14708,24 @@ } }, "node_modules/vite": { - "version": "6.3.5", + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.6.tgz", + "integrity": "sha512-SRYIB8t/isTwNn8vMB3MR6E+EQZM/WG1aKmmIUCfDXfVvKfc20ZpamngWHKzAmmu9ppsgxsg4b2I7c90JZudIQ==", "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.25.0", - "fdir": "^6.4.4", - "picomatch": "^4.0.2", - "postcss": "^8.5.3", - "rollup": "^4.34.9", - "tinyglobby": "^0.2.13" + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + "node": "^20.19.0 || >=22.12.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" @@ -14182,14 +14734,14 @@ "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", - "less": "*", + "less": "^4.0.0", "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" @@ -14231,15 +14783,17 @@ } }, "node_modules/vite-node": { - "version": "3.1.3", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz", + "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", "dev": true, "license": "MIT", "dependencies": { "cac": "^6.7.14", - "debug": "^4.4.0", + "debug": "^4.4.1", "es-module-lexer": "^1.7.0", "pathe": "^2.0.3", - "vite": "^5.0.0 || ^6.0.0" + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "bin": { "vite-node": "vite-node.mjs" @@ -14252,30 +14806,34 @@ } }, "node_modules/vitest": { - "version": "3.1.3", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.4.tgz", + "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "3.1.3", - "@vitest/mocker": "3.1.3", - "@vitest/pretty-format": "^3.1.3", - "@vitest/runner": "3.1.3", - "@vitest/snapshot": "3.1.3", - "@vitest/spy": "3.1.3", - "@vitest/utils": "3.1.3", + "@types/chai": "^5.2.2", + "@vitest/expect": "3.2.4", + "@vitest/mocker": "3.2.4", + "@vitest/pretty-format": "^3.2.4", + "@vitest/runner": "3.2.4", + "@vitest/snapshot": "3.2.4", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", "chai": "^5.2.0", - "debug": "^4.4.0", + "debug": "^4.4.1", "expect-type": "^1.2.1", "magic-string": "^0.30.17", "pathe": "^2.0.3", + "picomatch": "^4.0.2", "std-env": "^3.9.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", - "tinyglobby": "^0.2.13", - "tinypool": "^1.0.2", + "tinyglobby": "^0.2.14", + "tinypool": "^1.1.1", "tinyrainbow": "^2.0.0", - "vite": "^5.0.0 || ^6.0.0", - "vite-node": "3.1.3", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", + "vite-node": "3.2.4", "why-is-node-running": "^2.3.0" }, "bin": { @@ -14291,8 +14849,8 @@ "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.1.3", - "@vitest/ui": "3.1.3", + "@vitest/browser": "3.2.4", + "@vitest/ui": "3.2.4", "happy-dom": "*", "jsdom": "*" }, @@ -14573,7 +15131,6 @@ "name": "wrap-ansi", "version": "7.0.0", "license": "MIT", - "peer": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -14589,7 +15146,6 @@ "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { "version": "4.3.0", "license": "MIT", - "peer": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -14759,7 +15315,9 @@ } }, "node_modules/zod": { - "version": "3.25.42", + "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" @@ -14801,11 +15359,11 @@ }, "packages/atxp-base": { "name": "@atxp/base", - "version": "0.3.0", + "version": "0.4.0", "license": "MIT", "dependencies": { - "@atxp/client": "0.3.0", - "@atxp/common": "0.3.0", + "@atxp/client": "0.4.0", + "@atxp/common": "0.4.0", "@base-org/account": "^2.1.0", "bignumber.js": "^9.3.0" }, @@ -14829,10 +15387,10 @@ }, "packages/atxp-client": { "name": "@atxp/client", - "version": "0.3.0", + "version": "0.4.0", "license": "MIT", "dependencies": { - "@atxp/common": "0.3.0", + "@atxp/common": "0.4.0", "@modelcontextprotocol/sdk": "^1.15.0", "bignumber.js": "^9.3.0", "oauth4webapi": "^3.5.0" @@ -14864,9 +15422,32 @@ "viem": "^2.34.0" } }, + "packages/atxp-cloudflare": { + "name": "@atxp/cloudflare", + "version": "0.4.0", + "license": "MIT", + "dependencies": { + "@atxp/common": "0.4.0", + "@atxp/server": "0.4.0" + }, + "devDependencies": { + "@cloudflare/workers-types": "^4.20241022.0", + "@types/node": "^22.13.0", + "@typescript-eslint/eslint-plugin": "^8.38.0", + "@typescript-eslint/parser": "^8.38.0", + "@vitest/coverage-v8": "^3.2.4", + "bignumber.js": "^9.1.2", + "eslint": "^9.32.0", + "typescript": "^5.7.3", + "vitest": "^3.0.9" + }, + "peerDependencies": { + "agents": "^0.1.2" + } + }, "packages/atxp-common": { "name": "@atxp/common", - "version": "0.3.0", + "version": "0.4.0", "license": "MIT", "dependencies": { "bignumber.js": "^9.3.0", @@ -15076,12 +15657,35 @@ "node": ">=18" } }, + "packages/atxp-express": { + "name": "@atxp/express", + "version": "0.4.0", + "license": "MIT", + "dependencies": { + "@atxp/server": "0.4.0" + }, + "devDependencies": { + "@types/express": "^5.0.0", + "@types/node": "^22.13.0", + "@types/supertest": "^6.0.3", + "@typescript-eslint/eslint-plugin": "^8.38.0", + "@typescript-eslint/parser": "^8.38.0", + "eslint": "^9.32.0", + "express": "^5.0.0", + "supertest": "^7.1.4", + "typescript": "^5.7.3", + "vitest": "^3.0.9" + }, + "peerDependencies": { + "express": "^5.0.0" + } + }, "packages/atxp-redis": { "name": "@atxp/redis", - "version": "0.3.0", + "version": "0.4.0", "license": "MIT", "dependencies": { - "@atxp/common": "0.3.0", + "@atxp/common": "0.4.0", "ioredis": "^5.7.0" }, "devDependencies": { @@ -15095,39 +15699,33 @@ }, "packages/atxp-server": { "name": "@atxp/server", - "version": "0.3.0", + "version": "0.4.0", "license": "MIT", "dependencies": { - "@atxp/common": "0.3.0", + "@atxp/common": "0.4.0", "@modelcontextprotocol/sdk": "^1.15.0", "bignumber.js": "^9.3.0", "oauth4webapi": "^3.5.0" }, "devDependencies": { - "@types/express": "^5.0.0", "@types/node": "^22.13.0", - "@types/supertest": "^6.0.3", "@typescript-eslint/eslint-plugin": "^8.38.0", "@typescript-eslint/parser": "^8.38.0", "eslint": "^9.32.0", - "express": "^5.0.0", "node-mocks-http": "^1.17.2", - "supertest": "^7.1.4", "typescript": "^5.7.3", "vitest": "^3.0.9" }, "peerDependencies": { - "content-type": "^1.0.5", - "express": "^5.0.0", - "raw-body": "^3.0.0" + "content-type": "^1.0.5" } }, "packages/atxp-sqlite": { "name": "@atxp/sqlite", - "version": "0.3.0", + "version": "0.4.0", "license": "MIT", "dependencies": { - "@atxp/common": "0.3.0", + "@atxp/common": "0.4.0", "better-sqlite3": "^12.2.0" }, "devDependencies": { From b9a2a58ad328c894c8da4025762f3bc255c2869f Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 11:05:42 -0700 Subject: [PATCH 11/61] Fix type errors and lint issues for X402 support --- packages/atxp-base/src/baseAppPaymentMaker.ts | 7 ++++++- packages/atxp-base/src/mainWalletPaymentMaker.ts | 7 ++++++- packages/atxp-client/src/index.ts | 3 ++- packages/atxp-client/src/x402Wrapper.ts | 4 ++-- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/packages/atxp-base/src/baseAppPaymentMaker.ts b/packages/atxp-base/src/baseAppPaymentMaker.ts index 6a87a4c0..70db2f44 100644 --- a/packages/atxp-base/src/baseAppPaymentMaker.ts +++ b/packages/atxp-base/src/baseAppPaymentMaker.ts @@ -1,4 +1,4 @@ -import { USDC_CONTRACT_ADDRESS_BASE, type PaymentMaker } from '@atxp/client'; +import { USDC_CONTRACT_ADDRESS_BASE, type PaymentMaker, type EIP3009Authorization, PaymentNetworkError } from '@atxp/client'; import { Logger, Currency, ConsoleLogger } from '@atxp/common'; import { Address, encodeFunctionData, Hex, parseEther } from 'viem'; import { SpendPermission } from './types.js'; @@ -184,6 +184,11 @@ export class BaseAppPaymentMaker implements PaymentMaker { return txHash; } + async createPaymentAuthorization(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { + // BaseApp doesn't support EIP-3009 payment authorizations + throw new PaymentNetworkError('EIP-3009 payment authorizations are not supported by BaseAppPaymentMaker'); + } + /** * Dynamically import the appropriate spend-permission module based on environment. * Uses browser or node version as appropriate since prepareSpendCallData exists in both. diff --git a/packages/atxp-base/src/mainWalletPaymentMaker.ts b/packages/atxp-base/src/mainWalletPaymentMaker.ts index a1fbeb2b..d3dc7848 100644 --- a/packages/atxp-base/src/mainWalletPaymentMaker.ts +++ b/packages/atxp-base/src/mainWalletPaymentMaker.ts @@ -1,4 +1,4 @@ -import { PaymentMaker } from '@atxp/client'; +import { PaymentMaker, EIP3009Authorization, PaymentNetworkError } from '@atxp/client'; import { encodeFunctionData, toHex } from 'viem'; import { USDC_CONTRACT_ADDRESS_BASE, type Hex } from '@atxp/client'; import BigNumber from 'bignumber.js'; @@ -183,4 +183,9 @@ export class MainWalletPaymentMaker implements PaymentMaker { this.logger.info(`Transaction confirmed with ${confirmations} confirmations`); } + + async createPaymentAuthorization(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { + // MainWalletPaymentMaker doesn't support EIP-3009 payment authorizations + throw new PaymentNetworkError('EIP-3009 payment authorizations are not supported by MainWalletPaymentMaker'); + } } diff --git a/packages/atxp-client/src/index.ts b/packages/atxp-client/src/index.ts index 9b71b67f..7732b3a8 100644 --- a/packages/atxp-client/src/index.ts +++ b/packages/atxp-client/src/index.ts @@ -58,7 +58,8 @@ export { InsufficientFundsError, PaymentNetworkError, type PaymentMaker, - type SignedPaymentMessage + type EIP3009Authorization, + type X402Message } from './types.js'; // X402 support diff --git a/packages/atxp-client/src/x402Wrapper.ts b/packages/atxp-client/src/x402Wrapper.ts index 93facad0..5493dc8b 100644 --- a/packages/atxp-client/src/x402Wrapper.ts +++ b/packages/atxp-client/src/x402Wrapper.ts @@ -4,7 +4,7 @@ import { BigNumber } from 'bignumber.js'; export function wrapWithX402(fetchFn: FetchLike, account: Account): FetchLike { return async function x402FetchWrapper(input: RequestInfo | URL, init?: RequestInit): Promise { - const response = await fetchFn(input, init); + const response = await fetchFn(input as any, init); // Check if this is an X402 payment challenge if (response.status === 402) { @@ -54,7 +54,7 @@ export function wrapWithX402(fetchFn: FetchLike, account: Account): FetchLike { }; // Retry the request - return await fetchFn(input, retryInit); + return await fetchFn(input as any, retryInit); } catch (error) { // If there's an error processing the payment, return the original 402 response console.error('Failed to handle X402 payment challenge:', error); From e3411abf1f0ea068f20ffcf49b841ebb9724dedb Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 11:08:23 -0700 Subject: [PATCH 12/61] Fix lint errors: prefix unused parameters with underscore --- packages/atxp-base/src/baseAppPaymentMaker.ts | 2 +- packages/atxp-base/src/mainWalletPaymentMaker.ts | 2 +- packages/atxp-client/src/basePaymentMaker.ts | 2 +- packages/atxp-client/src/solanaPaymentMaker.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/atxp-base/src/baseAppPaymentMaker.ts b/packages/atxp-base/src/baseAppPaymentMaker.ts index 70db2f44..a36eb8c8 100644 --- a/packages/atxp-base/src/baseAppPaymentMaker.ts +++ b/packages/atxp-base/src/baseAppPaymentMaker.ts @@ -184,7 +184,7 @@ export class BaseAppPaymentMaker implements PaymentMaker { return txHash; } - async createPaymentAuthorization(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { + async createPaymentAuthorization(_amount: BigNumber, _currency: Currency, _receiver: string, _memo: string): Promise { // BaseApp doesn't support EIP-3009 payment authorizations throw new PaymentNetworkError('EIP-3009 payment authorizations are not supported by BaseAppPaymentMaker'); } diff --git a/packages/atxp-base/src/mainWalletPaymentMaker.ts b/packages/atxp-base/src/mainWalletPaymentMaker.ts index d3dc7848..ec7b6888 100644 --- a/packages/atxp-base/src/mainWalletPaymentMaker.ts +++ b/packages/atxp-base/src/mainWalletPaymentMaker.ts @@ -184,7 +184,7 @@ export class MainWalletPaymentMaker implements PaymentMaker { this.logger.info(`Transaction confirmed with ${confirmations} confirmations`); } - async createPaymentAuthorization(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { + async createPaymentAuthorization(_amount: BigNumber, _currency: Currency, _receiver: string, _memo: string): Promise { // MainWalletPaymentMaker doesn't support EIP-3009 payment authorizations throw new PaymentNetworkError('EIP-3009 payment authorizations are not supported by MainWalletPaymentMaker'); } diff --git a/packages/atxp-client/src/basePaymentMaker.ts b/packages/atxp-client/src/basePaymentMaker.ts index 8d0037e5..9471b4f2 100644 --- a/packages/atxp-client/src/basePaymentMaker.ts +++ b/packages/atxp-client/src/basePaymentMaker.ts @@ -180,7 +180,7 @@ export class BasePaymentMaker implements PaymentMaker { } } - async createPaymentAuthorization(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { + async createPaymentAuthorization(_amount: BigNumber, _currency: Currency, _receiver: string, _memo: string): Promise { // BasePaymentMaker doesn't have access to accounts service, so throw not-implemented throw new PaymentNetworkErrorClass('EIP-3009 payment authorizations are not supported by BasePaymentMaker'); } diff --git a/packages/atxp-client/src/solanaPaymentMaker.ts b/packages/atxp-client/src/solanaPaymentMaker.ts index d976e630..d8594a26 100644 --- a/packages/atxp-client/src/solanaPaymentMaker.ts +++ b/packages/atxp-client/src/solanaPaymentMaker.ts @@ -111,7 +111,7 @@ export class SolanaPaymentMaker implements PaymentMaker { } } - async createPaymentAuthorization(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { + async createPaymentAuthorization(_amount: BigNumber, _currency: Currency, _receiver: string, _memo: string): Promise { // EIP-3009 is an Ethereum/EVM standard, not supported on Solana throw new PaymentNetworkError('EIP-3009 payment authorizations are not supported on Solana'); } From 02b786a765a05c3ba0aa9c26850d53f496029b9f Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 11:10:14 -0700 Subject: [PATCH 13/61] Fix lint warnings in x402Wrapper.ts --- packages/atxp-client/src/x402Wrapper.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/atxp-client/src/x402Wrapper.ts b/packages/atxp-client/src/x402Wrapper.ts index 5493dc8b..f258e329 100644 --- a/packages/atxp-client/src/x402Wrapper.ts +++ b/packages/atxp-client/src/x402Wrapper.ts @@ -4,7 +4,7 @@ import { BigNumber } from 'bignumber.js'; export function wrapWithX402(fetchFn: FetchLike, account: Account): FetchLike { return async function x402FetchWrapper(input: RequestInfo | URL, init?: RequestInit): Promise { - const response = await fetchFn(input as any, init); + const response = await fetchFn(input as RequestInfo | URL, init); // Check if this is an X402 payment challenge if (response.status === 402) { @@ -54,10 +54,10 @@ export function wrapWithX402(fetchFn: FetchLike, account: Account): FetchLike { }; // Retry the request - return await fetchFn(input as any, retryInit); - } catch (error) { + return await fetchFn(input as RequestInfo | URL, retryInit); + } catch { // If there's an error processing the payment, return the original 402 response - console.error('Failed to handle X402 payment challenge:', error); + // Error is logged by the payment maker if needed return response; } } From 8f91b71f3a0a9476c323ae2c37d31450423e2f79 Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 11:12:28 -0700 Subject: [PATCH 14/61] Add Logger support to x402Wrapper with proper logging throughout --- examples/x402-server/src/test-client.ts | 6 ++++- packages/atxp-client/src/x402Wrapper.ts | 29 ++++++++++++++++++++----- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/examples/x402-server/src/test-client.ts b/examples/x402-server/src/test-client.ts index cce2c525..29610735 100644 --- a/examples/x402-server/src/test-client.ts +++ b/examples/x402-server/src/test-client.ts @@ -1,4 +1,5 @@ import { wrapWithX402, BaseAccount } from '@atxp/client'; +import { ConsoleLogger } from '@atxp/common'; import dotenv from 'dotenv'; dotenv.config(); @@ -16,8 +17,11 @@ async function testX402Client() { process.env.BASE_PRIVATE_KEY ); + // Create a logger (optional - defaults to ConsoleLogger if not provided) + const logger = new ConsoleLogger(); + // Wrap fetch with X402 support - const x402Fetch = wrapWithX402(fetch as any, account); + const x402Fetch = wrapWithX402(fetch as any, account, logger); // Make a single request to the protected endpoint const serverUrl = process.env.X402_SERVER_URL || 'http://localhost:3001'; diff --git a/packages/atxp-client/src/x402Wrapper.ts b/packages/atxp-client/src/x402Wrapper.ts index f258e329..9a1edb47 100644 --- a/packages/atxp-client/src/x402Wrapper.ts +++ b/packages/atxp-client/src/x402Wrapper.ts @@ -1,8 +1,9 @@ import type { Account, X402Message } from './types.js'; -import { FetchLike } from '@atxp/common'; +import { FetchLike, Logger, ConsoleLogger } from '@atxp/common'; import { BigNumber } from 'bignumber.js'; -export function wrapWithX402(fetchFn: FetchLike, account: Account): FetchLike { +export function wrapWithX402(fetchFn: FetchLike, account: Account, logger?: Logger): FetchLike { + const log = logger ?? new ConsoleLogger(); return async function x402FetchWrapper(input: RequestInfo | URL, init?: RequestInit): Promise { const response = await fetchFn(input as RequestInfo | URL, init); @@ -12,22 +13,30 @@ export function wrapWithX402(fetchFn: FetchLike, account: Account): FetchLike { if (!paymentHeader) { // Not an X402 response, return as-is + log.debug('Received 402 response without X-Payment-Required header'); return response; } + log.info('Received X402 payment challenge'); + try { // Parse the X402 payment requirements const paymentChallenge = JSON.parse(paymentHeader); const { network, currency, amount, recipient, memo } = paymentChallenge; + log.debug(`Payment required: ${amount} ${currency} on ${network} to ${recipient}`); + // Find the appropriate payment maker const paymentMakerKey = `${network}:${currency}`; const paymentMaker = account.paymentMakers[paymentMakerKey]; if (!paymentMaker) { + log.error(`No payment maker found for ${paymentMakerKey}`); throw new Error(`No payment maker found for ${paymentMakerKey}`); } + log.debug(`Creating EIP-3009 payment authorization`); + // Create an EIP-3009 payment authorization const eip3009Authorization = await paymentMaker.createPaymentAuthorization( new BigNumber(amount), @@ -53,11 +62,21 @@ export function wrapWithX402(fetchFn: FetchLike, account: Account): FetchLike { } }; + log.info('Retrying request with X-Payment header'); + // Retry the request - return await fetchFn(input as RequestInfo | URL, retryInit); - } catch { + const retryResponse = await fetchFn(input as RequestInfo | URL, retryInit); + + if (retryResponse.ok) { + log.info('X402 payment accepted, request successful'); + } else { + log.warn(`Request failed after payment with status ${retryResponse.status}`); + } + + return retryResponse; + } catch (error) { // If there's an error processing the payment, return the original 402 response - // Error is logged by the payment maker if needed + log.error('Failed to handle X402 payment challenge:', error); return response; } } From dbeb8ff972586b2e879b33c94ad629195d6d1a58 Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 11:15:38 -0700 Subject: [PATCH 15/61] Fix typecheck errors: correct FetchLike type signature and logger.error call --- packages/atxp-client/src/x402Wrapper.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/atxp-client/src/x402Wrapper.ts b/packages/atxp-client/src/x402Wrapper.ts index 9a1edb47..99264d8f 100644 --- a/packages/atxp-client/src/x402Wrapper.ts +++ b/packages/atxp-client/src/x402Wrapper.ts @@ -4,8 +4,8 @@ import { BigNumber } from 'bignumber.js'; export function wrapWithX402(fetchFn: FetchLike, account: Account, logger?: Logger): FetchLike { const log = logger ?? new ConsoleLogger(); - return async function x402FetchWrapper(input: RequestInfo | URL, init?: RequestInit): Promise { - const response = await fetchFn(input as RequestInfo | URL, init); + return async function x402FetchWrapper(input: string | URL, init?: RequestInit): Promise { + const response = await fetchFn(input, init); // Check if this is an X402 payment challenge if (response.status === 402) { @@ -65,7 +65,7 @@ export function wrapWithX402(fetchFn: FetchLike, account: Account, logger?: Logg log.info('Retrying request with X-Payment header'); // Retry the request - const retryResponse = await fetchFn(input as RequestInfo | URL, retryInit); + const retryResponse = await fetchFn(input, retryInit); if (retryResponse.ok) { log.info('X402 payment accepted, request successful'); @@ -76,7 +76,7 @@ export function wrapWithX402(fetchFn: FetchLike, account: Account, logger?: Logg return retryResponse; } catch (error) { // If there's an error processing the payment, return the original 402 response - log.error('Failed to handle X402 payment challenge:', error); + log.error(`Failed to handle X402 payment challenge: ${error}`); return response; } } From 44f7c5702df8b700386df7942a058e3829606f1e Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 11:40:08 -0700 Subject: [PATCH 16/61] Tests --- packages/atxp-client/src/x402Wrapper.test.ts | 133 +++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 packages/atxp-client/src/x402Wrapper.test.ts diff --git a/packages/atxp-client/src/x402Wrapper.test.ts b/packages/atxp-client/src/x402Wrapper.test.ts new file mode 100644 index 00000000..15deb29b --- /dev/null +++ b/packages/atxp-client/src/x402Wrapper.test.ts @@ -0,0 +1,133 @@ +import { describe, it, expect, vi } from 'vitest'; +import { wrapWithX402 } from './x402Wrapper.js'; +import type { Account, EIP3009Authorization, X402Message } from './types.js'; +import { BigNumber } from 'bignumber.js'; + +describe('X402 Wrapper', () => { + it('should produce valid X402 message structure matching protocol specification', async () => { + // Mock account with test payment maker + const mockAccount: Account = { + paymentMakers: { + 'base:USDC': { + async createPaymentAuthorization( + amount: BigNumber, + currency: string, + receiver: string, + memo: string + ): Promise { + // Mock EIP-3009 authorization response + return { + signature: '0xabcdef123456789', + authorization: { + from: '0x1234567890123456789012345678901234567890', + to: receiver, + value: amount.multipliedBy(1e6).toFixed(0), // USDC has 6 decimals + validAfter: Math.floor(Date.now() / 1000).toString(), + validBefore: (Math.floor(Date.now() / 1000) + 3600).toString(), + nonce: '0x' + '0'.repeat(64) + } + }; + } + } + } + }; + + // Mock fetch that returns 402 with payment requirements + const mockFetch = vi.fn(async (url: string | URL, init?: RequestInit) => { + if (!init?.headers || !(init.headers as any)['X-Payment']) { + // First request - return 402 challenge + return { + status: 402, + headers: { + get: (name: string) => { + if (name === 'X-Payment-Required') { + return JSON.stringify({ + network: 'base', + currency: 'USDC', + amount: '0.01', + recipient: '0xrecipient123', + memo: 'test payment' + }); + } + return null; + } + } + }; + } + + // Second request with payment - verify X402 message structure + const x402Message = JSON.parse((init.headers as any)['X-Payment']) as X402Message; + + // Verify top-level X402 protocol fields + expect(x402Message).toHaveProperty('x402Version'); + expect(x402Message).toHaveProperty('scheme'); + expect(x402Message).toHaveProperty('network'); + expect(x402Message).toHaveProperty('payload'); + + expect(x402Message.x402Version).toBe(1); + expect(x402Message.scheme).toBe('exact'); + expect(x402Message.network).toBe('base'); + + // Verify EIP-3009 payload structure + expect(x402Message.payload).toHaveProperty('signature'); + expect(x402Message.payload).toHaveProperty('authorization'); + + const auth = x402Message.payload.authorization; + expect(auth).toHaveProperty('from'); + expect(auth).toHaveProperty('to'); + expect(auth).toHaveProperty('value'); + expect(auth).toHaveProperty('validAfter'); + expect(auth).toHaveProperty('validBefore'); + expect(auth).toHaveProperty('nonce'); + + // Verify value is correctly converted to USDC units (6 decimals) + expect(auth.value).toBe('10000'); // 0.01 USDC = 10000 units + expect(auth.to).toBe('0xrecipient123'); + + return { + status: 200, + ok: true, + json: async () => ({ success: true }) + }; + }); + + const wrappedFetch = wrapWithX402(mockFetch as any, mockAccount); + const response = await wrappedFetch('https://example.com/api/resource'); + + expect(response.status).toBe(200); + expect(mockFetch).toHaveBeenCalledTimes(2); + }); + + it('should handle non-402 responses without modification', async () => { + const mockAccount: Account = { paymentMakers: {} }; + const mockFetch = vi.fn(async () => ({ + status: 200, + ok: true, + headers: { + get: () => null + } + })); + + const wrappedFetch = wrapWithX402(mockFetch as any, mockAccount); + const response = await wrappedFetch('https://example.com/api/resource'); + + expect(response.status).toBe(200); + expect(mockFetch).toHaveBeenCalledTimes(1); + }); + + it('should handle 402 responses without X-Payment-Required header', async () => { + const mockAccount: Account = { paymentMakers: {} }; + const mockFetch = vi.fn(async () => ({ + status: 402, + headers: { + get: () => null + } + })); + + const wrappedFetch = wrapWithX402(mockFetch as any, mockAccount); + const response = await wrappedFetch('https://example.com/api/resource'); + + expect(response.status).toBe(402); + expect(mockFetch).toHaveBeenCalledTimes(1); + }); +}); \ No newline at end of file From 409bf19b345647f1a7b2979757378341fd9d1503 Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 11:44:12 -0700 Subject: [PATCH 17/61] Lint --- packages/atxp-client/src/x402Wrapper.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/atxp-client/src/x402Wrapper.test.ts b/packages/atxp-client/src/x402Wrapper.test.ts index 15deb29b..49d47466 100644 --- a/packages/atxp-client/src/x402Wrapper.test.ts +++ b/packages/atxp-client/src/x402Wrapper.test.ts @@ -11,9 +11,9 @@ describe('X402 Wrapper', () => { 'base:USDC': { async createPaymentAuthorization( amount: BigNumber, - currency: string, + _currency: string, receiver: string, - memo: string + _memo: string ): Promise { // Mock EIP-3009 authorization response return { From c5e20a62acd8f2d38c7b5ee2d78b699c7731ab5c Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 12:34:41 -0700 Subject: [PATCH 18/61] Localhost test --- examples/x402-server/.env.example | 10 +- examples/x402-server/package-lock.json | 9442 +++++++++++++++++++++++ examples/x402-server/package.json | 16 +- examples/x402-server/src/server.ts | 76 +- examples/x402-server/src/test-client.ts | 14 +- 5 files changed, 9512 insertions(+), 46 deletions(-) create mode 100644 examples/x402-server/package-lock.json diff --git a/examples/x402-server/.env.example b/examples/x402-server/.env.example index a1cd4c6e..110a2629 100644 --- a/examples/x402-server/.env.example +++ b/examples/x402-server/.env.example @@ -1,6 +1,9 @@ +# Required: Your wallet address to receive payments (must start with 0x) +ATXP_DESTINATION=0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb8 + # Network Configuration -# Options: "base" (mainnet - requires CDP keys) or "base-sepolia" (testnet - no keys needed!) -NETWORK=base-sepolia +# Options: "mainnet" (uses CDP facilitator) or leave empty for testnet +NETWORK= # Coinbase Developer Platform (CDP) API Keys (ONLY needed for mainnet) # Get these from https://portal.cdp.coinbase.com/ @@ -8,9 +11,6 @@ NETWORK=base-sepolia CDP_API_KEY_ID= CDP_API_KEY_SECRET= -# Your wallet address to receive payments -RECIPIENT_ADDRESS=0xYourWalletAddressHere - # Base network RPC URL (for the test client) # You can get one from https://www.alchemy.com/ or https://www.infura.io/ BASE_RPC_URL=https://base-mainnet.g.alchemy.com/v2/your-api-key diff --git a/examples/x402-server/package-lock.json b/examples/x402-server/package-lock.json new file mode 100644 index 00000000..b4548fac --- /dev/null +++ b/examples/x402-server/package-lock.json @@ -0,0 +1,9442 @@ +{ + "name": "@atxp/x402-server-example", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@atxp/x402-server-example", + "version": "1.0.0", + "dependencies": { + "@atxp/client": "file:../../packages/atxp-client", + "@atxp/common": "file:../../packages/atxp-common", + "@coinbase/x402": "^0.3.8", + "bignumber.js": "^9.1.2", + "cors": "^2.8.5", + "dotenv": "^16.0.3", + "express": "^4.18.2", + "x402": "^0.6.1", + "x402-express": "^0.6.1" + }, + "devDependencies": { + "@types/cors": "^2.8.13", + "@types/express": "^4.17.17", + "@types/node": "^20.0.0", + "tsx": "^4.0.0", + "typescript": "^5.0.0" + } + }, + "../../packages/atxp-client": { + "name": "@atxp/client", + "version": "0.4.0", + "license": "MIT", + "dependencies": { + "@atxp/common": "0.4.0", + "@modelcontextprotocol/sdk": "^1.15.0", + "bignumber.js": "^9.3.0", + "oauth4webapi": "^3.5.0" + }, + "devDependencies": { + "@solana/pay": "^0.2.5", + "@solana/web3.js": "^1.98.1", + "@types/node": "^22.13.0", + "@types/supertest": "^6.0.3", + "@typescript-eslint/eslint-plugin": "^8.38.0", + "@typescript-eslint/parser": "^8.38.0", + "bs58": "^6.0.0", + "eslint": "^9.32.0", + "fetch-mock": "^12.5.2", + "happy-dom": "^15.11.6", + "jsdom": "^25.0.1", + "react-native-url-polyfill": "^2.0.0", + "supertest": "^7.1.4", + "typescript": "^5.7.3", + "viem": "^2.34.0", + "vitest": "^3.0.9" + }, + "peerDependencies": { + "@solana/pay": "^0.2.5", + "@solana/web3.js": "^1.98.1", + "bs58": "^6.0.0", + "expo-crypto": ">=14.0.0", + "react-native-url-polyfill": "^2.0.0", + "viem": "^2.34.0" + } + }, + "../../packages/atxp-common": { + "name": "@atxp/common", + "version": "0.4.0", + "license": "MIT", + "dependencies": { + "bignumber.js": "^9.3.0", + "jose": "^6.0.11", + "oauth4webapi": "^3.5.0", + "tweetnacl": "^1.0.3", + "tweetnacl-util": "^0.15.1" + }, + "devDependencies": { + "@types/node": "^22.13.0", + "@typescript-eslint/eslint-plugin": "^8.38.0", + "@typescript-eslint/parser": "^8.38.0", + "eslint": "^9.32.0", + "jsdom": "^25.0.1", + "typescript": "^5.7.3", + "vitest": "^3.0.9" + } + }, + "node_modules/@adraffy/ens-normalize": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.11.0.tgz", + "integrity": "sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg==", + "license": "MIT" + }, + "node_modules/@atxp/client": { + "resolved": "../../packages/atxp-client", + "link": true + }, + "node_modules/@atxp/common": { + "resolved": "../../packages/atxp-common", + "link": true + }, + "node_modules/@babel/runtime": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@base-org/account": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@base-org/account/-/account-1.1.1.tgz", + "integrity": "sha512-IfVJPrDPhHfqXRDb89472hXkpvJuQQR7FDI9isLPHEqSYt/45whIoBxSPgZ0ssTt379VhQo4+87PWI1DoLSfAQ==", + "license": "Apache-2.0", + "dependencies": { + "@noble/hashes": "1.4.0", + "clsx": "1.2.1", + "eventemitter3": "5.0.1", + "idb-keyval": "6.2.1", + "ox": "0.6.9", + "preact": "10.24.2", + "viem": "^2.31.7", + "zustand": "5.0.3" + } + }, + "node_modules/@base-org/account/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/@base-org/account/node_modules/ox": { + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.6.9.tgz", + "integrity": "sha512-wi5ShvzE4eOcTwQVsIPdFr+8ycyX+5le/96iAJutaZAvCes1J0+RvpEPg5QDPDiaR0XQQAvZVl7AwqQcINuUug==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@adraffy/ens-normalize": "^1.10.1", + "@noble/curves": "^1.6.0", + "@noble/hashes": "^1.5.0", + "@scure/bip32": "^1.5.0", + "@scure/bip39": "^1.4.0", + "abitype": "^1.0.6", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@base-org/account/node_modules/ox/node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@coinbase/cdp-sdk": { + "version": "1.38.1", + "resolved": "https://registry.npmjs.org/@coinbase/cdp-sdk/-/cdp-sdk-1.38.1.tgz", + "integrity": "sha512-UOGDjv8KM+bdKF3nl/CxLytcN2SNXgKlQVA6hfAvQNPSRBW3VE4sx7OdVszDqO7fkVcxNZu91Qwfi+ARE8H76g==", + "license": "MIT", + "dependencies": { + "@solana/spl-token": "^0.4.13", + "@solana/web3.js": "^1.98.1", + "abitype": "1.0.6", + "axios": "^1.12.2", + "axios-retry": "^4.5.0", + "jose": "^6.0.8", + "md5": "^2.3.0", + "uncrypto": "^0.1.3", + "viem": "^2.21.26", + "zod": "^3.24.4" + } + }, + "node_modules/@coinbase/wallet-sdk": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/@coinbase/wallet-sdk/-/wallet-sdk-4.3.6.tgz", + "integrity": "sha512-4q8BNG1ViL4mSAAvPAtpwlOs1gpC+67eQtgIwNvT3xyeyFFd+guwkc8bcX5rTmQhXpqnhzC4f0obACbP9CqMSA==", + "license": "Apache-2.0", + "dependencies": { + "@noble/hashes": "1.4.0", + "clsx": "1.2.1", + "eventemitter3": "5.0.1", + "idb-keyval": "6.2.1", + "ox": "0.6.9", + "preact": "10.24.2", + "viem": "^2.27.2", + "zustand": "5.0.3" + } + }, + "node_modules/@coinbase/wallet-sdk/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/@coinbase/wallet-sdk/node_modules/ox": { + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.6.9.tgz", + "integrity": "sha512-wi5ShvzE4eOcTwQVsIPdFr+8ycyX+5le/96iAJutaZAvCes1J0+RvpEPg5QDPDiaR0XQQAvZVl7AwqQcINuUug==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@adraffy/ens-normalize": "^1.10.1", + "@noble/curves": "^1.6.0", + "@noble/hashes": "^1.5.0", + "@scure/bip32": "^1.5.0", + "@scure/bip39": "^1.4.0", + "abitype": "^1.0.6", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@coinbase/wallet-sdk/node_modules/ox/node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@coinbase/x402": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@coinbase/x402/-/x402-0.3.8.tgz", + "integrity": "sha512-qEjxQRefXCyTfxXf4LJtB5CQZAVqjVulbol5fjcYMrA6buA1ZCq7J+l2IJVVYfeJTv70s5atLEi35xxWNobLTQ==", + "license": "Apache-2.0", + "dependencies": { + "@coinbase/cdp-sdk": "^1.1.1", + "viem": "^2.23.1", + "x402": "^0.3.7", + "zod": "^3.24.2" + } + }, + "node_modules/@coinbase/x402/node_modules/x402": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/x402/-/x402-0.3.7.tgz", + "integrity": "sha512-8g2sXjWX7UbUNg9wJqgSBoYP7QV3/7qYYssdfPiQM5XDDThuVy7+MnH4cCuQ4UGGn2SVz1hpzWpwxMC3nwp+zA==", + "license": "Apache-2.0", + "dependencies": { + "viem": "^2.23.1", + "zod": "^3.24.2" + } + }, + "node_modules/@ecies/ciphers": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@ecies/ciphers/-/ciphers-0.2.4.tgz", + "integrity": "sha512-t+iX+Wf5nRKyNzk8dviW3Ikb/280+aEJAnw9YXvCp2tYGPSkMki+NRY+8aNLmVFv3eNtMdvViPNOPxS8SZNP+w==", + "license": "MIT", + "engines": { + "bun": ">=1", + "deno": ">=2", + "node": ">=16" + }, + "peerDependencies": { + "@noble/ciphers": "^1.0.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.10.tgz", + "integrity": "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.10.tgz", + "integrity": "sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.10.tgz", + "integrity": "sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.10.tgz", + "integrity": "sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.10.tgz", + "integrity": "sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.10.tgz", + "integrity": "sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.10.tgz", + "integrity": "sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.10.tgz", + "integrity": "sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.10.tgz", + "integrity": "sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.10.tgz", + "integrity": "sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.10.tgz", + "integrity": "sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.10.tgz", + "integrity": "sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.10.tgz", + "integrity": "sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.10.tgz", + "integrity": "sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.10.tgz", + "integrity": "sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.10.tgz", + "integrity": "sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.10.tgz", + "integrity": "sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.10.tgz", + "integrity": "sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.10.tgz", + "integrity": "sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.10.tgz", + "integrity": "sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.10.tgz", + "integrity": "sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.10.tgz", + "integrity": "sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.10.tgz", + "integrity": "sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.10.tgz", + "integrity": "sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.10.tgz", + "integrity": "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.10.tgz", + "integrity": "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@ethereumjs/common": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-3.2.0.tgz", + "integrity": "sha512-pksvzI0VyLgmuEF2FA/JR/4/y6hcPq8OUail3/AvycBaW1d5VSauOZzqGvJ3RTmR4MU35lWE8KseKOsEhrFRBA==", + "license": "MIT", + "dependencies": { + "@ethereumjs/util": "^8.1.0", + "crc-32": "^1.2.0" + } + }, + "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/@ethereumjs/tx": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-4.2.0.tgz", + "integrity": "sha512-1nc6VO4jtFd172BbSnTnDQVr9IYBFl1y4xPzZdtkrkKIncBCkdbgfdRV+MiTkJYAtTxvV12GRZLqBFT1PNK6Yw==", + "license": "MPL-2.0", + "dependencies": { + "@ethereumjs/common": "^3.2.0", + "@ethereumjs/rlp": "^4.0.1", + "@ethereumjs/util": "^8.1.0", + "ethereum-cryptography": "^2.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@ethereumjs/util": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/util/-/util-8.1.0.tgz", + "integrity": "sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==", + "license": "MPL-2.0", + "dependencies": { + "@ethereumjs/rlp": "^4.0.1", + "ethereum-cryptography": "^2.0.0", + "micro-ftch": "^0.3.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@gemini-wallet/core": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@gemini-wallet/core/-/core-0.2.0.tgz", + "integrity": "sha512-vv9aozWnKrrPWQ3vIFcWk7yta4hQW1Ie0fsNNPeXnjAxkbXr2hqMagEptLuMxpEP2W3mnRu05VDNKzcvAuuZDw==", + "license": "MIT", + "dependencies": { + "@metamask/rpc-errors": "7.0.2", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "viem": ">=2.0.0" + } + }, + "node_modules/@lit-labs/ssr-dom-shim": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.4.0.tgz", + "integrity": "sha512-ficsEARKnmmW5njugNYKipTm4SFnbik7CXtoencDZzmzo/dQ+2Q0bgkzJuoJP20Aj0F+izzJjOqsnkd6F/o1bw==", + "license": "BSD-3-Clause" + }, + "node_modules/@lit/reactive-element": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.1.1.tgz", + "integrity": "sha512-N+dm5PAYdQ8e6UlywyyrgI2t++wFGXfHx+dSJ1oBrg6FAxUj40jId++EaRm80MKX5JnlH1sBsyZ5h0bcZKemCg==", + "license": "BSD-3-Clause", + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.4.0" + } + }, + "node_modules/@metamask/eth-json-rpc-provider": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@metamask/eth-json-rpc-provider/-/eth-json-rpc-provider-1.0.1.tgz", + "integrity": "sha512-whiUMPlAOrVGmX8aKYVPvlKyG4CpQXiNNyt74vE1xb5sPvmx5oA7B/kOi/JdBvhGQq97U1/AVdXEdk2zkP8qyA==", + "dependencies": { + "@metamask/json-rpc-engine": "^7.0.0", + "@metamask/safe-event-emitter": "^3.0.0", + "@metamask/utils": "^5.0.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@metamask/eth-json-rpc-provider/node_modules/@metamask/json-rpc-engine": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@metamask/json-rpc-engine/-/json-rpc-engine-7.3.3.tgz", + "integrity": "sha512-dwZPq8wx9yV3IX2caLi9q9xZBw2XeIoYqdyihDDDpuHVCEiqadJLwqM3zy+uwf6F1QYQ65A8aOMQg1Uw7LMLNg==", + "license": "ISC", + "dependencies": { + "@metamask/rpc-errors": "^6.2.1", + "@metamask/safe-event-emitter": "^3.0.0", + "@metamask/utils": "^8.3.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@metamask/eth-json-rpc-provider/node_modules/@metamask/json-rpc-engine/node_modules/@metamask/utils": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-8.5.0.tgz", + "integrity": "sha512-I6bkduevXb72TIM9q2LRO63JSsF9EXduh3sBr9oybNX2hNNpr/j1tEjXrsG0Uabm4MJ1xkGAQEMwifvKZIkyxQ==", + "license": "ISC", + "dependencies": { + "@ethereumjs/tx": "^4.2.0", + "@metamask/superstruct": "^3.0.0", + "@noble/hashes": "^1.3.1", + "@scure/base": "^1.1.3", + "@types/debug": "^4.1.7", + "debug": "^4.3.4", + "pony-cause": "^2.1.10", + "semver": "^7.5.4", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@metamask/eth-json-rpc-provider/node_modules/@metamask/rpc-errors": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@metamask/rpc-errors/-/rpc-errors-6.4.0.tgz", + "integrity": "sha512-1ugFO1UoirU2esS3juZanS/Fo8C8XYocCuBpfZI5N7ECtoG+zu0wF+uWZASik6CkO6w9n/Iebt4iI4pT0vptpg==", + "license": "MIT", + "dependencies": { + "@metamask/utils": "^9.0.0", + "fast-safe-stringify": "^2.0.6" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@metamask/eth-json-rpc-provider/node_modules/@metamask/rpc-errors/node_modules/@metamask/utils": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-9.3.0.tgz", + "integrity": "sha512-w8CVbdkDrVXFJbfBSlDfafDR6BAkpDmv1bC1UJVCoVny5tW2RKAdn9i68Xf7asYT4TnUhl/hN4zfUiKQq9II4g==", + "license": "ISC", + "dependencies": { + "@ethereumjs/tx": "^4.2.0", + "@metamask/superstruct": "^3.1.0", + "@noble/hashes": "^1.3.1", + "@scure/base": "^1.1.3", + "@types/debug": "^4.1.7", + "debug": "^4.3.4", + "pony-cause": "^2.1.10", + "semver": "^7.5.4", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@metamask/eth-json-rpc-provider/node_modules/@metamask/utils": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-5.0.2.tgz", + "integrity": "sha512-yfmE79bRQtnMzarnKfX7AEJBwFTxvTyw3nBQlu/5rmGXrjAeAMltoGxO62TFurxrQAFMNa/fEjIHNvungZp0+g==", + "license": "ISC", + "dependencies": { + "@ethereumjs/tx": "^4.1.2", + "@types/debug": "^4.1.7", + "debug": "^4.3.4", + "semver": "^7.3.8", + "superstruct": "^1.0.3" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@metamask/eth-json-rpc-provider/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/@metamask/eth-json-rpc-provider/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/@metamask/eth-json-rpc-provider/node_modules/superstruct": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-1.0.4.tgz", + "integrity": "sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@metamask/eth-json-rpc-provider/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@metamask/json-rpc-engine": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@metamask/json-rpc-engine/-/json-rpc-engine-8.0.2.tgz", + "integrity": "sha512-IoQPmql8q7ABLruW7i4EYVHWUbF74yrp63bRuXV5Zf9BQwcn5H9Ww1eLtROYvI1bUXwOiHZ6qT5CWTrDc/t/AA==", + "license": "ISC", + "dependencies": { + "@metamask/rpc-errors": "^6.2.1", + "@metamask/safe-event-emitter": "^3.0.0", + "@metamask/utils": "^8.3.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@metamask/json-rpc-engine/node_modules/@metamask/rpc-errors": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@metamask/rpc-errors/-/rpc-errors-6.4.0.tgz", + "integrity": "sha512-1ugFO1UoirU2esS3juZanS/Fo8C8XYocCuBpfZI5N7ECtoG+zu0wF+uWZASik6CkO6w9n/Iebt4iI4pT0vptpg==", + "license": "MIT", + "dependencies": { + "@metamask/utils": "^9.0.0", + "fast-safe-stringify": "^2.0.6" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@metamask/json-rpc-engine/node_modules/@metamask/rpc-errors/node_modules/@metamask/utils": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-9.3.0.tgz", + "integrity": "sha512-w8CVbdkDrVXFJbfBSlDfafDR6BAkpDmv1bC1UJVCoVny5tW2RKAdn9i68Xf7asYT4TnUhl/hN4zfUiKQq9II4g==", + "license": "ISC", + "dependencies": { + "@ethereumjs/tx": "^4.2.0", + "@metamask/superstruct": "^3.1.0", + "@noble/hashes": "^1.3.1", + "@scure/base": "^1.1.3", + "@types/debug": "^4.1.7", + "debug": "^4.3.4", + "pony-cause": "^2.1.10", + "semver": "^7.5.4", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@metamask/json-rpc-engine/node_modules/@metamask/utils": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-8.5.0.tgz", + "integrity": "sha512-I6bkduevXb72TIM9q2LRO63JSsF9EXduh3sBr9oybNX2hNNpr/j1tEjXrsG0Uabm4MJ1xkGAQEMwifvKZIkyxQ==", + "license": "ISC", + "dependencies": { + "@ethereumjs/tx": "^4.2.0", + "@metamask/superstruct": "^3.0.0", + "@noble/hashes": "^1.3.1", + "@scure/base": "^1.1.3", + "@types/debug": "^4.1.7", + "debug": "^4.3.4", + "pony-cause": "^2.1.10", + "semver": "^7.5.4", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@metamask/json-rpc-engine/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/@metamask/json-rpc-engine/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/@metamask/json-rpc-engine/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@metamask/json-rpc-middleware-stream": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@metamask/json-rpc-middleware-stream/-/json-rpc-middleware-stream-7.0.2.tgz", + "integrity": "sha512-yUdzsJK04Ev98Ck4D7lmRNQ8FPioXYhEUZOMS01LXW8qTvPGiRVXmVltj2p4wrLkh0vW7u6nv0mNl5xzC5Qmfg==", + "license": "ISC", + "dependencies": { + "@metamask/json-rpc-engine": "^8.0.2", + "@metamask/safe-event-emitter": "^3.0.0", + "@metamask/utils": "^8.3.0", + "readable-stream": "^3.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@metamask/json-rpc-middleware-stream/node_modules/@metamask/utils": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-8.5.0.tgz", + "integrity": "sha512-I6bkduevXb72TIM9q2LRO63JSsF9EXduh3sBr9oybNX2hNNpr/j1tEjXrsG0Uabm4MJ1xkGAQEMwifvKZIkyxQ==", + "license": "ISC", + "dependencies": { + "@ethereumjs/tx": "^4.2.0", + "@metamask/superstruct": "^3.0.0", + "@noble/hashes": "^1.3.1", + "@scure/base": "^1.1.3", + "@types/debug": "^4.1.7", + "debug": "^4.3.4", + "pony-cause": "^2.1.10", + "semver": "^7.5.4", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@metamask/json-rpc-middleware-stream/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/@metamask/json-rpc-middleware-stream/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/@metamask/json-rpc-middleware-stream/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@metamask/object-multiplex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@metamask/object-multiplex/-/object-multiplex-2.1.0.tgz", + "integrity": "sha512-4vKIiv0DQxljcXwfpnbsXcfa5glMj5Zg9mqn4xpIWqkv6uJ2ma5/GtUfLFSxhlxnR8asRMv8dDmWya1Tc1sDFA==", + "license": "ISC", + "dependencies": { + "once": "^1.4.0", + "readable-stream": "^3.6.2" + }, + "engines": { + "node": "^16.20 || ^18.16 || >=20" + } + }, + "node_modules/@metamask/onboarding": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@metamask/onboarding/-/onboarding-1.0.1.tgz", + "integrity": "sha512-FqHhAsCI+Vacx2qa5mAFcWNSrTcVGMNjzxVgaX8ECSny/BJ9/vgXP9V7WF/8vb9DltPeQkxr+Fnfmm6GHfmdTQ==", + "license": "MIT", + "dependencies": { + "bowser": "^2.9.0" + } + }, + "node_modules/@metamask/providers": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@metamask/providers/-/providers-16.1.0.tgz", + "integrity": "sha512-znVCvux30+3SaUwcUGaSf+pUckzT5ukPRpcBmy+muBLC0yaWnBcvDqGfcsw6CBIenUdFrVoAFa8B6jsuCY/a+g==", + "license": "MIT", + "dependencies": { + "@metamask/json-rpc-engine": "^8.0.1", + "@metamask/json-rpc-middleware-stream": "^7.0.1", + "@metamask/object-multiplex": "^2.0.0", + "@metamask/rpc-errors": "^6.2.1", + "@metamask/safe-event-emitter": "^3.1.1", + "@metamask/utils": "^8.3.0", + "detect-browser": "^5.2.0", + "extension-port-stream": "^3.0.0", + "fast-deep-equal": "^3.1.3", + "is-stream": "^2.0.0", + "readable-stream": "^3.6.2", + "webextension-polyfill": "^0.10.0" + }, + "engines": { + "node": "^18.18 || >=20" + } + }, + "node_modules/@metamask/providers/node_modules/@metamask/rpc-errors": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@metamask/rpc-errors/-/rpc-errors-6.4.0.tgz", + "integrity": "sha512-1ugFO1UoirU2esS3juZanS/Fo8C8XYocCuBpfZI5N7ECtoG+zu0wF+uWZASik6CkO6w9n/Iebt4iI4pT0vptpg==", + "license": "MIT", + "dependencies": { + "@metamask/utils": "^9.0.0", + "fast-safe-stringify": "^2.0.6" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@metamask/providers/node_modules/@metamask/rpc-errors/node_modules/@metamask/utils": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-9.3.0.tgz", + "integrity": "sha512-w8CVbdkDrVXFJbfBSlDfafDR6BAkpDmv1bC1UJVCoVny5tW2RKAdn9i68Xf7asYT4TnUhl/hN4zfUiKQq9II4g==", + "license": "ISC", + "dependencies": { + "@ethereumjs/tx": "^4.2.0", + "@metamask/superstruct": "^3.1.0", + "@noble/hashes": "^1.3.1", + "@scure/base": "^1.1.3", + "@types/debug": "^4.1.7", + "debug": "^4.3.4", + "pony-cause": "^2.1.10", + "semver": "^7.5.4", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@metamask/providers/node_modules/@metamask/utils": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-8.5.0.tgz", + "integrity": "sha512-I6bkduevXb72TIM9q2LRO63JSsF9EXduh3sBr9oybNX2hNNpr/j1tEjXrsG0Uabm4MJ1xkGAQEMwifvKZIkyxQ==", + "license": "ISC", + "dependencies": { + "@ethereumjs/tx": "^4.2.0", + "@metamask/superstruct": "^3.0.0", + "@noble/hashes": "^1.3.1", + "@scure/base": "^1.1.3", + "@types/debug": "^4.1.7", + "debug": "^4.3.4", + "pony-cause": "^2.1.10", + "semver": "^7.5.4", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@metamask/providers/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/@metamask/providers/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/@metamask/providers/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@metamask/rpc-errors": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@metamask/rpc-errors/-/rpc-errors-7.0.2.tgz", + "integrity": "sha512-YYYHsVYd46XwY2QZzpGeU4PSdRhHdxnzkB8piWGvJW2xbikZ3R+epAYEL4q/K8bh9JPTucsUdwRFnACor1aOYw==", + "license": "MIT", + "dependencies": { + "@metamask/utils": "^11.0.1", + "fast-safe-stringify": "^2.0.6" + }, + "engines": { + "node": "^18.20 || ^20.17 || >=22" + } + }, + "node_modules/@metamask/safe-event-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@metamask/safe-event-emitter/-/safe-event-emitter-3.1.2.tgz", + "integrity": "sha512-5yb2gMI1BDm0JybZezeoX/3XhPDOtTbcFvpTXM9kxsoZjPZFh4XciqRbpD6N86HYZqWDhEaKUDuOyR0sQHEjMA==", + "license": "ISC", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@metamask/sdk": { + "version": "0.32.0", + "resolved": "https://registry.npmjs.org/@metamask/sdk/-/sdk-0.32.0.tgz", + "integrity": "sha512-WmGAlP1oBuD9hk4CsdlG1WJFuPtYJY+dnTHJMeCyohTWD2GgkcLMUUuvu9lO1/NVzuOoSi1OrnjbuY1O/1NZ1g==", + "dependencies": { + "@babel/runtime": "^7.26.0", + "@metamask/onboarding": "^1.0.1", + "@metamask/providers": "16.1.0", + "@metamask/sdk-communication-layer": "0.32.0", + "@metamask/sdk-install-modal-web": "0.32.0", + "@paulmillr/qr": "^0.2.1", + "bowser": "^2.9.0", + "cross-fetch": "^4.0.0", + "debug": "^4.3.4", + "eciesjs": "^0.4.11", + "eth-rpc-errors": "^4.0.3", + "eventemitter2": "^6.4.9", + "obj-multiplex": "^1.0.0", + "pump": "^3.0.0", + "readable-stream": "^3.6.2", + "socket.io-client": "^4.5.1", + "tslib": "^2.6.0", + "util": "^0.12.4", + "uuid": "^8.3.2" + } + }, + "node_modules/@metamask/sdk-communication-layer": { + "version": "0.32.0", + "resolved": "https://registry.npmjs.org/@metamask/sdk-communication-layer/-/sdk-communication-layer-0.32.0.tgz", + "integrity": "sha512-dmj/KFjMi1fsdZGIOtbhxdg3amxhKL/A5BqSU4uh/SyDKPub/OT+x5pX8bGjpTL1WPWY/Q0OIlvFyX3VWnT06Q==", + "dependencies": { + "bufferutil": "^4.0.8", + "date-fns": "^2.29.3", + "debug": "^4.3.4", + "utf-8-validate": "^5.0.2", + "uuid": "^8.3.2" + }, + "peerDependencies": { + "cross-fetch": "^4.0.0", + "eciesjs": "*", + "eventemitter2": "^6.4.9", + "readable-stream": "^3.6.2", + "socket.io-client": "^4.5.1" + } + }, + "node_modules/@metamask/sdk-communication-layer/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/@metamask/sdk-communication-layer/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/@metamask/sdk-install-modal-web": { + "version": "0.32.0", + "resolved": "https://registry.npmjs.org/@metamask/sdk-install-modal-web/-/sdk-install-modal-web-0.32.0.tgz", + "integrity": "sha512-TFoktj0JgfWnQaL3yFkApqNwcaqJ+dw4xcnrJueMP3aXkSNev2Ido+WVNOg4IIMxnmOrfAC9t0UJ0u/dC9MjOQ==", + "dependencies": { + "@paulmillr/qr": "^0.2.1" + } + }, + "node_modules/@metamask/sdk/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/@metamask/sdk/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/@metamask/superstruct": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@metamask/superstruct/-/superstruct-3.2.1.tgz", + "integrity": "sha512-fLgJnDOXFmuVlB38rUN5SmU7hAFQcCjrg3Vrxz67KTY7YHFnSNEKvX4avmEBdOI0yTCxZjwMCFEqsC8k2+Wd3g==", + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@metamask/utils": { + "version": "11.8.0", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-11.8.0.tgz", + "integrity": "sha512-EJqiuvVBAjV1vd1kBhmVmRtGfadrBfY3ImcAMjl+8MSSByTB3VNwvlIBLQdp+TwdAomUdenJCx2BvOSQykm8Hg==", + "license": "ISC", + "dependencies": { + "@ethereumjs/tx": "^4.2.0", + "@metamask/superstruct": "^3.1.0", + "@noble/hashes": "^1.3.1", + "@scure/base": "^1.1.3", + "@types/debug": "^4.1.7", + "@types/lodash": "^4.17.20", + "debug": "^4.3.4", + "lodash": "^4.17.21", + "pony-cause": "^2.1.10", + "semver": "^7.5.4", + "uuid": "^9.0.1" + }, + "engines": { + "node": "^18.18 || ^20.14 || >=22" + } + }, + "node_modules/@metamask/utils/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/@metamask/utils/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/@metamask/utils/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "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/@paulmillr/qr": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@paulmillr/qr/-/qr-0.2.1.tgz", + "integrity": "sha512-IHnV6A+zxU7XwmKFinmYjUcwlyK9+xkG3/s9KcQhI9BjQKycrJ1JRO+FbNYPwZiPKW3je/DR0k7w8/gLa5eaxQ==", + "deprecated": "The package is now available as \"qr\": npm install qr", + "license": "(MIT OR Apache-2.0)", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@reown/appkit/-/appkit-1.7.8.tgz", + "integrity": "sha512-51kTleozhA618T1UvMghkhKfaPcc9JlKwLJ5uV+riHyvSoWPKPRIa5A6M1Wano5puNyW0s3fwywhyqTHSilkaA==", + "license": "Apache-2.0", + "dependencies": { + "@reown/appkit-common": "1.7.8", + "@reown/appkit-controllers": "1.7.8", + "@reown/appkit-pay": "1.7.8", + "@reown/appkit-polyfills": "1.7.8", + "@reown/appkit-scaffold-ui": "1.7.8", + "@reown/appkit-ui": "1.7.8", + "@reown/appkit-utils": "1.7.8", + "@reown/appkit-wallet": "1.7.8", + "@walletconnect/types": "2.21.0", + "@walletconnect/universal-provider": "2.21.0", + "bs58": "6.0.0", + "valtio": "1.13.2", + "viem": ">=2.29.0" + } + }, + "node_modules/@reown/appkit-common": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@reown/appkit-common/-/appkit-common-1.7.8.tgz", + "integrity": "sha512-ridIhc/x6JOp7KbDdwGKY4zwf8/iK8EYBl+HtWrruutSLwZyVi5P8WaZa+8iajL6LcDcDF7LoyLwMTym7SRuwQ==", + "license": "Apache-2.0", + "dependencies": { + "big.js": "6.2.2", + "dayjs": "1.11.13", + "viem": ">=2.29.0" + } + }, + "node_modules/@reown/appkit-controllers": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@reown/appkit-controllers/-/appkit-controllers-1.7.8.tgz", + "integrity": "sha512-IdXlJlivrlj6m63VsGLsjtPHHsTWvKGVzWIP1fXZHVqmK+rZCBDjCi9j267Rb9/nYRGHWBtlFQhO8dK35WfeDA==", + "license": "Apache-2.0", + "dependencies": { + "@reown/appkit-common": "1.7.8", + "@reown/appkit-wallet": "1.7.8", + "@walletconnect/universal-provider": "2.21.0", + "valtio": "1.13.2", + "viem": ">=2.29.0" + } + }, + "node_modules/@reown/appkit-controllers/node_modules/@noble/ciphers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.2.1.tgz", + "integrity": "sha512-rONPWMC7PeExE077uLE4oqWrZ1IvAfz3oH9LibVAcVCopJiA9R62uavnbEzdkVmJYI6M6Zgkbeb07+tWjlq2XA==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit-controllers/node_modules/@noble/curves": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.1.tgz", + "integrity": "sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.7.1" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit-controllers/node_modules/@noble/hashes": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz", + "integrity": "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit-controllers/node_modules/@scure/bip32": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.6.2.tgz", + "integrity": "sha512-t96EPDMbtGgtb7onKKqxRLfE5g05k7uHnHRM2xdE6BP/ZmxaLtPek4J4KfVn/90IQNrU1IOAqMgiDtUdtbe3nw==", + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.8.1", + "@noble/hashes": "~1.7.1", + "@scure/base": "~1.2.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit-controllers/node_modules/@scure/bip39": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.5.4.tgz", + "integrity": "sha512-TFM4ni0vKvCfBpohoh+/lY05i9gRbSwXWngAsF4CABQxoaOHijxuaZ2R6cStDQ5CHtHO9aGJTr4ksVJASRRyMA==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.7.1", + "@scure/base": "~1.2.4" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit-controllers/node_modules/@walletconnect/core": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@walletconnect/core/-/core-2.21.0.tgz", + "integrity": "sha512-o6R7Ua4myxR8aRUAJ1z3gT9nM+jd2B2mfamu6arzy1Cc6vi10fIwFWb6vg3bC8xJ6o9H3n/cN5TOW3aA9Y1XVw==", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-provider": "1.0.14", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/jsonrpc-ws-connection": "1.0.16", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "2.1.2", + "@walletconnect/relay-api": "1.0.11", + "@walletconnect/relay-auth": "1.1.0", + "@walletconnect/safe-json": "1.0.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.21.0", + "@walletconnect/utils": "2.21.0", + "@walletconnect/window-getters": "1.0.1", + "es-toolkit": "1.33.0", + "events": "3.3.0", + "uint8arrays": "3.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@reown/appkit-controllers/node_modules/@walletconnect/sign-client": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@walletconnect/sign-client/-/sign-client-2.21.0.tgz", + "integrity": "sha512-z7h+PeLa5Au2R591d/8ZlziE0stJvdzP9jNFzFolf2RG/OiXulgFKum8PrIyXy+Rg2q95U9nRVUF9fWcn78yBA==", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/core": "2.21.0", + "@walletconnect/events": "1.0.1", + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/logger": "2.1.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.21.0", + "@walletconnect/utils": "2.21.0", + "events": "3.3.0" + } + }, + "node_modules/@reown/appkit-controllers/node_modules/@walletconnect/types": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-2.21.0.tgz", + "integrity": "sha512-ll+9upzqt95ZBWcfkOszXZkfnpbJJ2CmxMfGgE5GmhdxxxCcO5bGhXkI+x8OpiS555RJ/v/sXJYMSOLkmu4fFw==", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/events": "1.0.1", + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "2.1.2", + "events": "3.3.0" + } + }, + "node_modules/@reown/appkit-controllers/node_modules/@walletconnect/universal-provider": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@walletconnect/universal-provider/-/universal-provider-2.21.0.tgz", + "integrity": "sha512-mtUQvewt+X0VBQay/xOJBvxsB3Xsm1lTwFjZ6WUwSOTR1X+FNb71hSApnV5kbsdDIpYPXeQUbGt2se1n5E5UBg==", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/events": "1.0.1", + "@walletconnect/jsonrpc-http-connection": "1.0.8", + "@walletconnect/jsonrpc-provider": "1.0.14", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "2.1.2", + "@walletconnect/sign-client": "2.21.0", + "@walletconnect/types": "2.21.0", + "@walletconnect/utils": "2.21.0", + "es-toolkit": "1.33.0", + "events": "3.3.0" + } + }, + "node_modules/@reown/appkit-controllers/node_modules/@walletconnect/utils": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@walletconnect/utils/-/utils-2.21.0.tgz", + "integrity": "sha512-zfHLiUoBrQ8rP57HTPXW7rQMnYxYI4gT9yTACxVW6LhIFROTF6/ytm5SKNoIvi4a5nX5dfXG4D9XwQUCu8Ilig==", + "license": "Apache-2.0", + "dependencies": { + "@noble/ciphers": "1.2.1", + "@noble/curves": "1.8.1", + "@noble/hashes": "1.7.1", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/relay-api": "1.0.11", + "@walletconnect/relay-auth": "1.1.0", + "@walletconnect/safe-json": "1.0.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.21.0", + "@walletconnect/window-getters": "1.0.1", + "@walletconnect/window-metadata": "1.0.1", + "bs58": "6.0.0", + "detect-browser": "5.3.0", + "query-string": "7.1.3", + "uint8arrays": "3.1.0", + "viem": "2.23.2" + } + }, + "node_modules/@reown/appkit-controllers/node_modules/@walletconnect/utils/node_modules/viem": { + "version": "2.23.2", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.23.2.tgz", + "integrity": "sha512-NVmW/E0c5crMOtbEAqMF0e3NmvQykFXhLOc/CkLIXOlzHSA6KXVz3CYVmaKqBF8/xtjsjHAGjdJN3Ru1kFJLaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@noble/curves": "1.8.1", + "@noble/hashes": "1.7.1", + "@scure/bip32": "1.6.2", + "@scure/bip39": "1.5.4", + "abitype": "1.0.8", + "isows": "1.0.6", + "ox": "0.6.7", + "ws": "8.18.0" + }, + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@reown/appkit-controllers/node_modules/abitype": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.8.tgz", + "integrity": "sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/wevm" + }, + "peerDependencies": { + "typescript": ">=5.0.4", + "zod": "^3 >=3.22.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, + "node_modules/@reown/appkit-controllers/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/@reown/appkit-controllers/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/@reown/appkit-controllers/node_modules/isows": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.6.tgz", + "integrity": "sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/@reown/appkit-controllers/node_modules/ox": { + "version": "0.6.7", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.6.7.tgz", + "integrity": "sha512-17Gk/eFsFRAZ80p5eKqv89a57uXjd3NgIf1CaXojATPBuujVc/fQSVhBeAU9JCRB+k7J50WQAyWTxK19T9GgbA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@adraffy/ens-normalize": "^1.10.1", + "@noble/curves": "^1.6.0", + "@noble/hashes": "^1.5.0", + "@scure/bip32": "^1.5.0", + "@scure/bip39": "^1.4.0", + "abitype": "^1.0.6", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@reown/appkit-controllers/node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "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/@reown/appkit-pay": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@reown/appkit-pay/-/appkit-pay-1.7.8.tgz", + "integrity": "sha512-OSGQ+QJkXx0FEEjlpQqIhT8zGJKOoHzVnyy/0QFrl3WrQTjCzg0L6+i91Ad5Iy1zb6V5JjqtfIFpRVRWN4M3pw==", + "license": "Apache-2.0", + "dependencies": { + "@reown/appkit-common": "1.7.8", + "@reown/appkit-controllers": "1.7.8", + "@reown/appkit-ui": "1.7.8", + "@reown/appkit-utils": "1.7.8", + "lit": "3.3.0", + "valtio": "1.13.2" + } + }, + "node_modules/@reown/appkit-polyfills": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@reown/appkit-polyfills/-/appkit-polyfills-1.7.8.tgz", + "integrity": "sha512-W/kq786dcHHAuJ3IV2prRLEgD/2iOey4ueMHf1sIFjhhCGMynMkhsOhQMUH0tzodPqUgAC494z4bpIDYjwWXaA==", + "license": "Apache-2.0", + "dependencies": { + "buffer": "6.0.3" + } + }, + "node_modules/@reown/appkit-scaffold-ui": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@reown/appkit-scaffold-ui/-/appkit-scaffold-ui-1.7.8.tgz", + "integrity": "sha512-RCeHhAwOrIgcvHwYlNWMcIDibdI91waaoEYBGw71inE0kDB8uZbE7tE6DAXJmDkvl0qPh+DqlC4QbJLF1FVYdQ==", + "license": "Apache-2.0", + "dependencies": { + "@reown/appkit-common": "1.7.8", + "@reown/appkit-controllers": "1.7.8", + "@reown/appkit-ui": "1.7.8", + "@reown/appkit-utils": "1.7.8", + "@reown/appkit-wallet": "1.7.8", + "lit": "3.3.0" + } + }, + "node_modules/@reown/appkit-ui": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@reown/appkit-ui/-/appkit-ui-1.7.8.tgz", + "integrity": "sha512-1hjCKjf6FLMFzrulhl0Y9Vb9Fu4royE+SXCPSWh4VhZhWqlzUFc7kutnZKx8XZFVQH4pbBvY62SpRC93gqoHow==", + "license": "Apache-2.0", + "dependencies": { + "@reown/appkit-common": "1.7.8", + "@reown/appkit-controllers": "1.7.8", + "@reown/appkit-wallet": "1.7.8", + "lit": "3.3.0", + "qrcode": "1.5.3" + } + }, + "node_modules/@reown/appkit-utils": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@reown/appkit-utils/-/appkit-utils-1.7.8.tgz", + "integrity": "sha512-8X7UvmE8GiaoitCwNoB86pttHgQtzy4ryHZM9kQpvjQ0ULpiER44t1qpVLXNM4X35O0v18W0Dk60DnYRMH2WRw==", + "license": "Apache-2.0", + "dependencies": { + "@reown/appkit-common": "1.7.8", + "@reown/appkit-controllers": "1.7.8", + "@reown/appkit-polyfills": "1.7.8", + "@reown/appkit-wallet": "1.7.8", + "@walletconnect/logger": "2.1.2", + "@walletconnect/universal-provider": "2.21.0", + "valtio": "1.13.2", + "viem": ">=2.29.0" + }, + "peerDependencies": { + "valtio": "1.13.2" + } + }, + "node_modules/@reown/appkit-utils/node_modules/@noble/ciphers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.2.1.tgz", + "integrity": "sha512-rONPWMC7PeExE077uLE4oqWrZ1IvAfz3oH9LibVAcVCopJiA9R62uavnbEzdkVmJYI6M6Zgkbeb07+tWjlq2XA==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit-utils/node_modules/@noble/curves": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.1.tgz", + "integrity": "sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.7.1" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit-utils/node_modules/@noble/hashes": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz", + "integrity": "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit-utils/node_modules/@scure/bip32": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.6.2.tgz", + "integrity": "sha512-t96EPDMbtGgtb7onKKqxRLfE5g05k7uHnHRM2xdE6BP/ZmxaLtPek4J4KfVn/90IQNrU1IOAqMgiDtUdtbe3nw==", + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.8.1", + "@noble/hashes": "~1.7.1", + "@scure/base": "~1.2.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit-utils/node_modules/@scure/bip39": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.5.4.tgz", + "integrity": "sha512-TFM4ni0vKvCfBpohoh+/lY05i9gRbSwXWngAsF4CABQxoaOHijxuaZ2R6cStDQ5CHtHO9aGJTr4ksVJASRRyMA==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.7.1", + "@scure/base": "~1.2.4" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit-utils/node_modules/@walletconnect/core": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@walletconnect/core/-/core-2.21.0.tgz", + "integrity": "sha512-o6R7Ua4myxR8aRUAJ1z3gT9nM+jd2B2mfamu6arzy1Cc6vi10fIwFWb6vg3bC8xJ6o9H3n/cN5TOW3aA9Y1XVw==", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-provider": "1.0.14", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/jsonrpc-ws-connection": "1.0.16", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "2.1.2", + "@walletconnect/relay-api": "1.0.11", + "@walletconnect/relay-auth": "1.1.0", + "@walletconnect/safe-json": "1.0.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.21.0", + "@walletconnect/utils": "2.21.0", + "@walletconnect/window-getters": "1.0.1", + "es-toolkit": "1.33.0", + "events": "3.3.0", + "uint8arrays": "3.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@reown/appkit-utils/node_modules/@walletconnect/sign-client": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@walletconnect/sign-client/-/sign-client-2.21.0.tgz", + "integrity": "sha512-z7h+PeLa5Au2R591d/8ZlziE0stJvdzP9jNFzFolf2RG/OiXulgFKum8PrIyXy+Rg2q95U9nRVUF9fWcn78yBA==", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/core": "2.21.0", + "@walletconnect/events": "1.0.1", + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/logger": "2.1.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.21.0", + "@walletconnect/utils": "2.21.0", + "events": "3.3.0" + } + }, + "node_modules/@reown/appkit-utils/node_modules/@walletconnect/types": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-2.21.0.tgz", + "integrity": "sha512-ll+9upzqt95ZBWcfkOszXZkfnpbJJ2CmxMfGgE5GmhdxxxCcO5bGhXkI+x8OpiS555RJ/v/sXJYMSOLkmu4fFw==", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/events": "1.0.1", + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "2.1.2", + "events": "3.3.0" + } + }, + "node_modules/@reown/appkit-utils/node_modules/@walletconnect/universal-provider": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@walletconnect/universal-provider/-/universal-provider-2.21.0.tgz", + "integrity": "sha512-mtUQvewt+X0VBQay/xOJBvxsB3Xsm1lTwFjZ6WUwSOTR1X+FNb71hSApnV5kbsdDIpYPXeQUbGt2se1n5E5UBg==", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/events": "1.0.1", + "@walletconnect/jsonrpc-http-connection": "1.0.8", + "@walletconnect/jsonrpc-provider": "1.0.14", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "2.1.2", + "@walletconnect/sign-client": "2.21.0", + "@walletconnect/types": "2.21.0", + "@walletconnect/utils": "2.21.0", + "es-toolkit": "1.33.0", + "events": "3.3.0" + } + }, + "node_modules/@reown/appkit-utils/node_modules/@walletconnect/utils": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@walletconnect/utils/-/utils-2.21.0.tgz", + "integrity": "sha512-zfHLiUoBrQ8rP57HTPXW7rQMnYxYI4gT9yTACxVW6LhIFROTF6/ytm5SKNoIvi4a5nX5dfXG4D9XwQUCu8Ilig==", + "license": "Apache-2.0", + "dependencies": { + "@noble/ciphers": "1.2.1", + "@noble/curves": "1.8.1", + "@noble/hashes": "1.7.1", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/relay-api": "1.0.11", + "@walletconnect/relay-auth": "1.1.0", + "@walletconnect/safe-json": "1.0.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.21.0", + "@walletconnect/window-getters": "1.0.1", + "@walletconnect/window-metadata": "1.0.1", + "bs58": "6.0.0", + "detect-browser": "5.3.0", + "query-string": "7.1.3", + "uint8arrays": "3.1.0", + "viem": "2.23.2" + } + }, + "node_modules/@reown/appkit-utils/node_modules/@walletconnect/utils/node_modules/viem": { + "version": "2.23.2", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.23.2.tgz", + "integrity": "sha512-NVmW/E0c5crMOtbEAqMF0e3NmvQykFXhLOc/CkLIXOlzHSA6KXVz3CYVmaKqBF8/xtjsjHAGjdJN3Ru1kFJLaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@noble/curves": "1.8.1", + "@noble/hashes": "1.7.1", + "@scure/bip32": "1.6.2", + "@scure/bip39": "1.5.4", + "abitype": "1.0.8", + "isows": "1.0.6", + "ox": "0.6.7", + "ws": "8.18.0" + }, + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@reown/appkit-utils/node_modules/abitype": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.8.tgz", + "integrity": "sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/wevm" + }, + "peerDependencies": { + "typescript": ">=5.0.4", + "zod": "^3 >=3.22.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, + "node_modules/@reown/appkit-utils/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/@reown/appkit-utils/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/@reown/appkit-utils/node_modules/isows": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.6.tgz", + "integrity": "sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/@reown/appkit-utils/node_modules/ox": { + "version": "0.6.7", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.6.7.tgz", + "integrity": "sha512-17Gk/eFsFRAZ80p5eKqv89a57uXjd3NgIf1CaXojATPBuujVc/fQSVhBeAU9JCRB+k7J50WQAyWTxK19T9GgbA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@adraffy/ens-normalize": "^1.10.1", + "@noble/curves": "^1.6.0", + "@noble/hashes": "^1.5.0", + "@scure/bip32": "^1.5.0", + "@scure/bip39": "^1.4.0", + "abitype": "^1.0.6", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@reown/appkit-utils/node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "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/@reown/appkit-wallet": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@reown/appkit-wallet/-/appkit-wallet-1.7.8.tgz", + "integrity": "sha512-kspz32EwHIOT/eg/ZQbFPxgXq0B/olDOj3YMu7gvLEFz4xyOFd/wgzxxAXkp5LbG4Cp++s/elh79rVNmVFdB9A==", + "license": "Apache-2.0", + "dependencies": { + "@reown/appkit-common": "1.7.8", + "@reown/appkit-polyfills": "1.7.8", + "@walletconnect/logger": "2.1.2", + "zod": "3.22.4" + } + }, + "node_modules/@reown/appkit-wallet/node_modules/zod": { + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", + "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@reown/appkit/node_modules/@noble/ciphers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.2.1.tgz", + "integrity": "sha512-rONPWMC7PeExE077uLE4oqWrZ1IvAfz3oH9LibVAcVCopJiA9R62uavnbEzdkVmJYI6M6Zgkbeb07+tWjlq2XA==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit/node_modules/@noble/curves": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.1.tgz", + "integrity": "sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.7.1" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit/node_modules/@noble/hashes": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz", + "integrity": "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit/node_modules/@scure/bip32": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.6.2.tgz", + "integrity": "sha512-t96EPDMbtGgtb7onKKqxRLfE5g05k7uHnHRM2xdE6BP/ZmxaLtPek4J4KfVn/90IQNrU1IOAqMgiDtUdtbe3nw==", + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.8.1", + "@noble/hashes": "~1.7.1", + "@scure/base": "~1.2.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit/node_modules/@scure/bip39": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.5.4.tgz", + "integrity": "sha512-TFM4ni0vKvCfBpohoh+/lY05i9gRbSwXWngAsF4CABQxoaOHijxuaZ2R6cStDQ5CHtHO9aGJTr4ksVJASRRyMA==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.7.1", + "@scure/base": "~1.2.4" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit/node_modules/@walletconnect/core": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@walletconnect/core/-/core-2.21.0.tgz", + "integrity": "sha512-o6R7Ua4myxR8aRUAJ1z3gT9nM+jd2B2mfamu6arzy1Cc6vi10fIwFWb6vg3bC8xJ6o9H3n/cN5TOW3aA9Y1XVw==", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-provider": "1.0.14", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/jsonrpc-ws-connection": "1.0.16", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "2.1.2", + "@walletconnect/relay-api": "1.0.11", + "@walletconnect/relay-auth": "1.1.0", + "@walletconnect/safe-json": "1.0.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.21.0", + "@walletconnect/utils": "2.21.0", + "@walletconnect/window-getters": "1.0.1", + "es-toolkit": "1.33.0", + "events": "3.3.0", + "uint8arrays": "3.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@reown/appkit/node_modules/@walletconnect/sign-client": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@walletconnect/sign-client/-/sign-client-2.21.0.tgz", + "integrity": "sha512-z7h+PeLa5Au2R591d/8ZlziE0stJvdzP9jNFzFolf2RG/OiXulgFKum8PrIyXy+Rg2q95U9nRVUF9fWcn78yBA==", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/core": "2.21.0", + "@walletconnect/events": "1.0.1", + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/logger": "2.1.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.21.0", + "@walletconnect/utils": "2.21.0", + "events": "3.3.0" + } + }, + "node_modules/@reown/appkit/node_modules/@walletconnect/types": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-2.21.0.tgz", + "integrity": "sha512-ll+9upzqt95ZBWcfkOszXZkfnpbJJ2CmxMfGgE5GmhdxxxCcO5bGhXkI+x8OpiS555RJ/v/sXJYMSOLkmu4fFw==", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/events": "1.0.1", + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "2.1.2", + "events": "3.3.0" + } + }, + "node_modules/@reown/appkit/node_modules/@walletconnect/universal-provider": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@walletconnect/universal-provider/-/universal-provider-2.21.0.tgz", + "integrity": "sha512-mtUQvewt+X0VBQay/xOJBvxsB3Xsm1lTwFjZ6WUwSOTR1X+FNb71hSApnV5kbsdDIpYPXeQUbGt2se1n5E5UBg==", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/events": "1.0.1", + "@walletconnect/jsonrpc-http-connection": "1.0.8", + "@walletconnect/jsonrpc-provider": "1.0.14", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "2.1.2", + "@walletconnect/sign-client": "2.21.0", + "@walletconnect/types": "2.21.0", + "@walletconnect/utils": "2.21.0", + "es-toolkit": "1.33.0", + "events": "3.3.0" + } + }, + "node_modules/@reown/appkit/node_modules/@walletconnect/utils": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@walletconnect/utils/-/utils-2.21.0.tgz", + "integrity": "sha512-zfHLiUoBrQ8rP57HTPXW7rQMnYxYI4gT9yTACxVW6LhIFROTF6/ytm5SKNoIvi4a5nX5dfXG4D9XwQUCu8Ilig==", + "license": "Apache-2.0", + "dependencies": { + "@noble/ciphers": "1.2.1", + "@noble/curves": "1.8.1", + "@noble/hashes": "1.7.1", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/relay-api": "1.0.11", + "@walletconnect/relay-auth": "1.1.0", + "@walletconnect/safe-json": "1.0.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.21.0", + "@walletconnect/window-getters": "1.0.1", + "@walletconnect/window-metadata": "1.0.1", + "bs58": "6.0.0", + "detect-browser": "5.3.0", + "query-string": "7.1.3", + "uint8arrays": "3.1.0", + "viem": "2.23.2" + } + }, + "node_modules/@reown/appkit/node_modules/@walletconnect/utils/node_modules/viem": { + "version": "2.23.2", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.23.2.tgz", + "integrity": "sha512-NVmW/E0c5crMOtbEAqMF0e3NmvQykFXhLOc/CkLIXOlzHSA6KXVz3CYVmaKqBF8/xtjsjHAGjdJN3Ru1kFJLaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@noble/curves": "1.8.1", + "@noble/hashes": "1.7.1", + "@scure/bip32": "1.6.2", + "@scure/bip39": "1.5.4", + "abitype": "1.0.8", + "isows": "1.0.6", + "ox": "0.6.7", + "ws": "8.18.0" + }, + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@reown/appkit/node_modules/abitype": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.8.tgz", + "integrity": "sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/wevm" + }, + "peerDependencies": { + "typescript": ">=5.0.4", + "zod": "^3 >=3.22.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, + "node_modules/@reown/appkit/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/@reown/appkit/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/@reown/appkit/node_modules/isows": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.6.tgz", + "integrity": "sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/@reown/appkit/node_modules/ox": { + "version": "0.6.7", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.6.7.tgz", + "integrity": "sha512-17Gk/eFsFRAZ80p5eKqv89a57uXjd3NgIf1CaXojATPBuujVc/fQSVhBeAU9JCRB+k7J50WQAyWTxK19T9GgbA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@adraffy/ens-normalize": "^1.10.1", + "@noble/curves": "^1.6.0", + "@noble/hashes": "^1.5.0", + "@scure/bip32": "^1.5.0", + "@scure/bip39": "^1.4.0", + "abitype": "^1.0.6", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@reown/appkit/node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "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-global/safe-apps-provider": { + "version": "0.18.6", + "resolved": "https://registry.npmjs.org/@safe-global/safe-apps-provider/-/safe-apps-provider-0.18.6.tgz", + "integrity": "sha512-4LhMmjPWlIO8TTDC2AwLk44XKXaK6hfBTWyljDm0HQ6TWlOEijVWNrt2s3OCVMSxlXAcEzYfqyu1daHZooTC2Q==", + "license": "MIT", + "dependencies": { + "@safe-global/safe-apps-sdk": "^9.1.0", + "events": "^3.3.0" + } + }, + "node_modules/@safe-global/safe-apps-sdk": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@safe-global/safe-apps-sdk/-/safe-apps-sdk-9.1.0.tgz", + "integrity": "sha512-N5p/ulfnnA2Pi2M3YeWjULeWbjo7ei22JwU/IXnhoHzKq3pYCN6ynL9mJBOlvDVv892EgLPCWCOwQk/uBT2v0Q==", + "license": "MIT", + "dependencies": { + "@safe-global/safe-gateway-typescript-sdk": "^3.5.3", + "viem": "^2.1.1" + } + }, + "node_modules/@safe-global/safe-gateway-typescript-sdk": { + "version": "3.23.1", + "resolved": "https://registry.npmjs.org/@safe-global/safe-gateway-typescript-sdk/-/safe-gateway-typescript-sdk-3.23.1.tgz", + "integrity": "sha512-6ORQfwtEJYpalCeVO21L4XXGSdbEMfyp2hEv6cP82afKXSwvse6d3sdelgaPWUxHIsFRkWvHDdzh8IyyKHZKxw==", + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "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/@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-program/compute-budget": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@solana-program/compute-budget/-/compute-budget-0.8.0.tgz", + "integrity": "sha512-qPKxdxaEsFxebZ4K5RPuy7VQIm/tfJLa1+Nlt3KNA8EYQkz9Xm8htdoEaXVrer9kpgzzp9R3I3Bh6omwCM06tQ==", + "license": "Apache-2.0", + "peerDependencies": { + "@solana/kit": "^2.1.0" + } + }, + "node_modules/@solana-program/token": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@solana-program/token/-/token-0.5.1.tgz", + "integrity": "sha512-bJvynW5q9SFuVOZ5vqGVkmaPGA0MCC+m9jgJj1nk5m20I389/ms69ASnhWGoOPNcie7S9OwBX0gTj2fiyWpfag==", + "license": "Apache-2.0", + "peerDependencies": { + "@solana/kit": "^2.1.0" + } + }, + "node_modules/@solana-program/token-2022": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@solana-program/token-2022/-/token-2022-0.4.2.tgz", + "integrity": "sha512-zIpR5t4s9qEU3hZKupzIBxJ6nUV5/UVyIT400tu9vT1HMs5JHxaTTsb5GUhYjiiTvNwU0MQavbwc4Dl29L0Xvw==", + "license": "Apache-2.0", + "peerDependencies": { + "@solana/kit": "^2.1.0", + "@solana/sysvars": "^2.1.0" + } + }, + "node_modules/@solana/accounts": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/accounts/-/accounts-2.3.0.tgz", + "integrity": "sha512-QgQTj404Z6PXNOyzaOpSzjgMOuGwG8vC66jSDB+3zHaRcEPRVRd2sVSrd1U6sHtnV3aiaS6YyDuPQMheg4K2jw==", + "license": "MIT", + "dependencies": { + "@solana/addresses": "2.3.0", + "@solana/codecs-core": "2.3.0", + "@solana/codecs-strings": "2.3.0", + "@solana/errors": "2.3.0", + "@solana/rpc-spec": "2.3.0", + "@solana/rpc-types": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/accounts/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/accounts/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/accounts/node_modules/@solana/codecs-strings": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-strings/-/codecs-strings-2.3.0.tgz", + "integrity": "sha512-y5pSBYwzVziXu521hh+VxqUtp0hYGTl1eWGoc1W+8mdvBdC1kTqm/X7aYQw33J42hw03JjryvYOvmGgk3Qz/Ug==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "fastestsmallesttextencoderdecoder": "^1.0.22", + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/accounts/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/accounts/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/addresses": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/addresses/-/addresses-2.3.0.tgz", + "integrity": "sha512-ypTNkY2ZaRFpHLnHAgaW8a83N0/WoqdFvCqf4CQmnMdFsZSdC7qOwcbd7YzdaQn9dy+P2hybewzB+KP7LutxGA==", + "license": "MIT", + "dependencies": { + "@solana/assertions": "2.3.0", + "@solana/codecs-core": "2.3.0", + "@solana/codecs-strings": "2.3.0", + "@solana/errors": "2.3.0", + "@solana/nominal-types": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/addresses/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/addresses/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/addresses/node_modules/@solana/codecs-strings": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-strings/-/codecs-strings-2.3.0.tgz", + "integrity": "sha512-y5pSBYwzVziXu521hh+VxqUtp0hYGTl1eWGoc1W+8mdvBdC1kTqm/X7aYQw33J42hw03JjryvYOvmGgk3Qz/Ug==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "fastestsmallesttextencoderdecoder": "^1.0.22", + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/addresses/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/addresses/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/assertions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/assertions/-/assertions-2.3.0.tgz", + "integrity": "sha512-Ekoet3khNg3XFLN7MIz8W31wPQISpKUGDGTylLptI+JjCDWx3PIa88xjEMqFo02WJ8sBj2NLV64Xg1sBcsHjZQ==", + "license": "MIT", + "dependencies": { + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/assertions/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/assertions/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "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.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": { + "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-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": { + "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/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/fast-stable-stringify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/fast-stable-stringify/-/fast-stable-stringify-2.3.0.tgz", + "integrity": "sha512-KfJPrMEieUg6D3hfQACoPy0ukrAV8Kio883llt/8chPEG3FVTX9z/Zuf4O01a15xZmBbmQ7toil2Dp0sxMJSxw==", + "license": "MIT", + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/functional": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/functional/-/functional-2.3.0.tgz", + "integrity": "sha512-AgsPh3W3tE+nK3eEw/W9qiSfTGwLYEvl0rWaxHht/lRcuDVwfKRzeSa5G79eioWFFqr+pTtoCr3D3OLkwKz02Q==", + "license": "MIT", + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/instructions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/instructions/-/instructions-2.3.0.tgz", + "integrity": "sha512-PLMsmaIKu7hEAzyElrk2T7JJx4D+9eRwebhFZpy2PXziNSmFF929eRHKUsKqBFM3cYR1Yy3m6roBZfA+bGE/oQ==", + "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/instructions/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/instructions/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/instructions/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/keys": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/keys/-/keys-2.3.0.tgz", + "integrity": "sha512-ZVVdga79pNH+2pVcm6fr2sWz9HTwfopDVhYb0Lh3dh+WBmJjwkabXEIHey2rUES7NjFa/G7sV8lrUn/v8LDCCQ==", + "license": "MIT", + "dependencies": { + "@solana/assertions": "2.3.0", + "@solana/codecs-core": "2.3.0", + "@solana/codecs-strings": "2.3.0", + "@solana/errors": "2.3.0", + "@solana/nominal-types": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/keys/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/keys/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/keys/node_modules/@solana/codecs-strings": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-strings/-/codecs-strings-2.3.0.tgz", + "integrity": "sha512-y5pSBYwzVziXu521hh+VxqUtp0hYGTl1eWGoc1W+8mdvBdC1kTqm/X7aYQw33J42hw03JjryvYOvmGgk3Qz/Ug==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "fastestsmallesttextencoderdecoder": "^1.0.22", + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/keys/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/keys/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/kit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/kit/-/kit-2.3.0.tgz", + "integrity": "sha512-sb6PgwoW2LjE5oTFu4lhlS/cGt/NB3YrShEyx7JgWFWysfgLdJnhwWThgwy/4HjNsmtMrQGWVls0yVBHcMvlMQ==", + "license": "MIT", + "dependencies": { + "@solana/accounts": "2.3.0", + "@solana/addresses": "2.3.0", + "@solana/codecs": "2.3.0", + "@solana/errors": "2.3.0", + "@solana/functional": "2.3.0", + "@solana/instructions": "2.3.0", + "@solana/keys": "2.3.0", + "@solana/programs": "2.3.0", + "@solana/rpc": "2.3.0", + "@solana/rpc-parsed-types": "2.3.0", + "@solana/rpc-spec-types": "2.3.0", + "@solana/rpc-subscriptions": "2.3.0", + "@solana/rpc-types": "2.3.0", + "@solana/signers": "2.3.0", + "@solana/sysvars": "2.3.0", + "@solana/transaction-confirmation": "2.3.0", + "@solana/transaction-messages": "2.3.0", + "@solana/transactions": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/kit/node_modules/@solana/codecs": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs/-/codecs-2.3.0.tgz", + "integrity": "sha512-JVqGPkzoeyU262hJGdH64kNLH0M+Oew2CIPOa/9tR3++q2pEd4jU2Rxdfye9sd0Ce3XJrR5AIa8ZfbyQXzjh+g==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-data-structures": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/codecs-strings": "2.3.0", + "@solana/options": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/kit/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/kit/node_modules/@solana/codecs-data-structures": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-data-structures/-/codecs-data-structures-2.3.0.tgz", + "integrity": "sha512-qvU5LE5DqEdYMYgELRHv+HMOx73sSoV1ZZkwIrclwUmwTbTaH8QAJURBj0RhQ/zCne7VuLLOZFFGv6jGigWhSw==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/kit/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/kit/node_modules/@solana/codecs-strings": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-strings/-/codecs-strings-2.3.0.tgz", + "integrity": "sha512-y5pSBYwzVziXu521hh+VxqUtp0hYGTl1eWGoc1W+8mdvBdC1kTqm/X7aYQw33J42hw03JjryvYOvmGgk3Qz/Ug==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "fastestsmallesttextencoderdecoder": "^1.0.22", + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/kit/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/kit/node_modules/@solana/options": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/options/-/options-2.3.0.tgz", + "integrity": "sha512-PPnnZBRCWWoZQ11exPxf//DRzN2C6AoFsDI/u2AsQfYih434/7Kp4XLpfOMT/XESi+gdBMFNNfbES5zg3wAIkw==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-data-structures": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/codecs-strings": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/kit/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/nominal-types": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/nominal-types/-/nominal-types-2.3.0.tgz", + "integrity": "sha512-uKlMnlP4PWW5UTXlhKM8lcgIaNj8dvd8xO4Y9l+FVvh9RvW2TO0GwUO6JCo7JBzCB0PSqRJdWWaQ8pu1Ti/OkA==", + "license": "MIT", + "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/programs": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/programs/-/programs-2.3.0.tgz", + "integrity": "sha512-UXKujV71VCI5uPs+cFdwxybtHZAIZyQkqDiDnmK+DawtOO9mBn4Nimdb/6RjR2CXT78mzO9ZCZ3qfyX+ydcB7w==", + "license": "MIT", + "dependencies": { + "@solana/addresses": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/programs/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/programs/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/promises": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/promises/-/promises-2.3.0.tgz", + "integrity": "sha512-GjVgutZKXVuojd9rWy1PuLnfcRfqsaCm7InCiZc8bqmJpoghlyluweNc7ml9Y5yQn1P2IOyzh9+p/77vIyNybQ==", + "license": "MIT", + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/rpc": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/rpc/-/rpc-2.3.0.tgz", + "integrity": "sha512-ZWN76iNQAOCpYC7yKfb3UNLIMZf603JckLKOOLTHuy9MZnTN8XV6uwvDFhf42XvhglgUjGCEnbUqWtxQ9pa/pQ==", + "license": "MIT", + "dependencies": { + "@solana/errors": "2.3.0", + "@solana/fast-stable-stringify": "2.3.0", + "@solana/functional": "2.3.0", + "@solana/rpc-api": "2.3.0", + "@solana/rpc-spec": "2.3.0", + "@solana/rpc-spec-types": "2.3.0", + "@solana/rpc-transformers": "2.3.0", + "@solana/rpc-transport-http": "2.3.0", + "@solana/rpc-types": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/rpc-api": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/rpc-api/-/rpc-api-2.3.0.tgz", + "integrity": "sha512-UUdiRfWoyYhJL9PPvFeJr4aJ554ob2jXcpn4vKmRVn9ire0sCbpQKYx6K8eEKHZWXKrDW8IDspgTl0gT/aJWVg==", + "license": "MIT", + "dependencies": { + "@solana/addresses": "2.3.0", + "@solana/codecs-core": "2.3.0", + "@solana/codecs-strings": "2.3.0", + "@solana/errors": "2.3.0", + "@solana/keys": "2.3.0", + "@solana/rpc-parsed-types": "2.3.0", + "@solana/rpc-spec": "2.3.0", + "@solana/rpc-transformers": "2.3.0", + "@solana/rpc-types": "2.3.0", + "@solana/transaction-messages": "2.3.0", + "@solana/transactions": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/rpc-api/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/rpc-api/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/rpc-api/node_modules/@solana/codecs-strings": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-strings/-/codecs-strings-2.3.0.tgz", + "integrity": "sha512-y5pSBYwzVziXu521hh+VxqUtp0hYGTl1eWGoc1W+8mdvBdC1kTqm/X7aYQw33J42hw03JjryvYOvmGgk3Qz/Ug==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "fastestsmallesttextencoderdecoder": "^1.0.22", + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/rpc-api/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/rpc-api/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/rpc-parsed-types": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/rpc-parsed-types/-/rpc-parsed-types-2.3.0.tgz", + "integrity": "sha512-B5pHzyEIbBJf9KHej+zdr5ZNAdSvu7WLU2lOUPh81KHdHQs6dEb310LGxcpCc7HVE8IEdO20AbckewDiAN6OCg==", + "license": "MIT", + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/rpc-spec": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/rpc-spec/-/rpc-spec-2.3.0.tgz", + "integrity": "sha512-fA2LMX4BMixCrNB2n6T83AvjZ3oUQTu7qyPLyt8gHQaoEAXs8k6GZmu6iYcr+FboQCjUmRPgMaABbcr9j2J9Sw==", + "license": "MIT", + "dependencies": { + "@solana/errors": "2.3.0", + "@solana/rpc-spec-types": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/rpc-spec-types": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/rpc-spec-types/-/rpc-spec-types-2.3.0.tgz", + "integrity": "sha512-xQsb65lahjr8Wc9dMtP7xa0ZmDS8dOE2ncYjlvfyw/h4mpdXTUdrSMi6RtFwX33/rGuztQ7Hwaid5xLNSLvsFQ==", + "license": "MIT", + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/rpc-spec/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/rpc-spec/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/rpc-subscriptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/rpc-subscriptions/-/rpc-subscriptions-2.3.0.tgz", + "integrity": "sha512-Uyr10nZKGVzvCOqwCZgwYrzuoDyUdwtgQRefh13pXIrdo4wYjVmoLykH49Omt6abwStB0a4UL5gX9V4mFdDJZg==", + "license": "MIT", + "dependencies": { + "@solana/errors": "2.3.0", + "@solana/fast-stable-stringify": "2.3.0", + "@solana/functional": "2.3.0", + "@solana/promises": "2.3.0", + "@solana/rpc-spec-types": "2.3.0", + "@solana/rpc-subscriptions-api": "2.3.0", + "@solana/rpc-subscriptions-channel-websocket": "2.3.0", + "@solana/rpc-subscriptions-spec": "2.3.0", + "@solana/rpc-transformers": "2.3.0", + "@solana/rpc-types": "2.3.0", + "@solana/subscribable": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/rpc-subscriptions-api": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/rpc-subscriptions-api/-/rpc-subscriptions-api-2.3.0.tgz", + "integrity": "sha512-9mCjVbum2Hg9KGX3LKsrI5Xs0KX390lS+Z8qB80bxhar6MJPugqIPH8uRgLhCW9GN3JprAfjRNl7our8CPvsPQ==", + "license": "MIT", + "dependencies": { + "@solana/addresses": "2.3.0", + "@solana/keys": "2.3.0", + "@solana/rpc-subscriptions-spec": "2.3.0", + "@solana/rpc-transformers": "2.3.0", + "@solana/rpc-types": "2.3.0", + "@solana/transaction-messages": "2.3.0", + "@solana/transactions": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/rpc-subscriptions-spec": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/rpc-subscriptions-spec/-/rpc-subscriptions-spec-2.3.0.tgz", + "integrity": "sha512-rdmVcl4PvNKQeA2l8DorIeALCgJEMSu7U8AXJS1PICeb2lQuMeaR+6cs/iowjvIB0lMVjYN2sFf6Q3dJPu6wWg==", + "license": "MIT", + "dependencies": { + "@solana/errors": "2.3.0", + "@solana/promises": "2.3.0", + "@solana/rpc-spec-types": "2.3.0", + "@solana/subscribable": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/rpc-subscriptions-spec/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/rpc-subscriptions-spec/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/rpc-subscriptions/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/rpc-subscriptions/node_modules/@solana/rpc-subscriptions-channel-websocket": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/rpc-subscriptions-channel-websocket/-/rpc-subscriptions-channel-websocket-2.3.0.tgz", + "integrity": "sha512-2oL6ceFwejIgeWzbNiUHI2tZZnaOxNTSerszcin7wYQwijxtpVgUHiuItM/Y70DQmH9sKhmikQp+dqeGalaJxw==", + "license": "MIT", + "dependencies": { + "@solana/errors": "2.3.0", + "@solana/functional": "2.3.0", + "@solana/rpc-subscriptions-spec": "2.3.0", + "@solana/subscribable": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3", + "ws": "^8.18.0" + } + }, + "node_modules/@solana/rpc-subscriptions/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/rpc-subscriptions/node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/@solana/rpc-transformers": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/rpc-transformers/-/rpc-transformers-2.3.0.tgz", + "integrity": "sha512-UuHYK3XEpo9nMXdjyGKkPCOr7WsZsxs7zLYDO1A5ELH3P3JoehvrDegYRAGzBS2VKsfApZ86ZpJToP0K3PhmMA==", + "license": "MIT", + "dependencies": { + "@solana/errors": "2.3.0", + "@solana/functional": "2.3.0", + "@solana/nominal-types": "2.3.0", + "@solana/rpc-spec-types": "2.3.0", + "@solana/rpc-types": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/rpc-transformers/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/rpc-transformers/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/rpc-transport-http": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/rpc-transport-http/-/rpc-transport-http-2.3.0.tgz", + "integrity": "sha512-HFKydmxGw8nAF5N+S0NLnPBDCe5oMDtI2RAmW8DMqP4U3Zxt2XWhvV1SNkAldT5tF0U1vP+is6fHxyhk4xqEvg==", + "license": "MIT", + "dependencies": { + "@solana/errors": "2.3.0", + "@solana/rpc-spec": "2.3.0", + "@solana/rpc-spec-types": "2.3.0", + "undici-types": "^7.11.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/rpc-transport-http/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/rpc-transport-http/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/rpc-transport-http/node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "license": "MIT" + }, + "node_modules/@solana/rpc-types": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/rpc-types/-/rpc-types-2.3.0.tgz", + "integrity": "sha512-O09YX2hED2QUyGxrMOxQ9GzH1LlEwwZWu69QbL4oYmIf6P5dzEEHcqRY6L1LsDVqc/dzAdEs/E1FaPrcIaIIPw==", + "license": "MIT", + "dependencies": { + "@solana/addresses": "2.3.0", + "@solana/codecs-core": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/codecs-strings": "2.3.0", + "@solana/errors": "2.3.0", + "@solana/nominal-types": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/rpc-types/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/rpc-types/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/rpc-types/node_modules/@solana/codecs-strings": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-strings/-/codecs-strings-2.3.0.tgz", + "integrity": "sha512-y5pSBYwzVziXu521hh+VxqUtp0hYGTl1eWGoc1W+8mdvBdC1kTqm/X7aYQw33J42hw03JjryvYOvmGgk3Qz/Ug==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "fastestsmallesttextencoderdecoder": "^1.0.22", + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/rpc-types/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/rpc-types/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/rpc/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/rpc/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/signers": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/signers/-/signers-2.3.0.tgz", + "integrity": "sha512-OSv6fGr/MFRx6J+ZChQMRqKNPGGmdjkqarKkRzkwmv7v8quWsIRnJT5EV8tBy3LI4DLO/A8vKiNSPzvm1TdaiQ==", + "license": "MIT", + "dependencies": { + "@solana/addresses": "2.3.0", + "@solana/codecs-core": "2.3.0", + "@solana/errors": "2.3.0", + "@solana/instructions": "2.3.0", + "@solana/keys": "2.3.0", + "@solana/nominal-types": "2.3.0", + "@solana/transaction-messages": "2.3.0", + "@solana/transactions": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/signers/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/signers/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/signers/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/spl-token": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@solana/spl-token/-/spl-token-0.4.14.tgz", + "integrity": "sha512-u09zr96UBpX4U685MnvQsNzlvw9TiY005hk1vJmJr7gMJldoPG1eYU5/wNEyOA5lkMLiR/gOi9SFD4MefOYEsA==", + "license": "Apache-2.0", + "dependencies": { + "@solana/buffer-layout": "^4.0.0", + "@solana/buffer-layout-utils": "^0.2.0", + "@solana/spl-token-group": "^0.0.7", + "@solana/spl-token-metadata": "^0.1.6", + "buffer": "^6.0.3" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@solana/web3.js": "^1.95.5" + } + }, + "node_modules/@solana/spl-token-group": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@solana/spl-token-group/-/spl-token-group-0.0.7.tgz", + "integrity": "sha512-V1N/iX7Cr7H0uazWUT2uk27TMqlqedpXHRqqAbVO2gvmJyT0E0ummMEAVQeXZ05ZhQ/xF39DLSdBp90XebWEug==", + "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/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/subscribable": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/subscribable/-/subscribable-2.3.0.tgz", + "integrity": "sha512-DkgohEDbMkdTWiKAoatY02Njr56WXx9e/dKKfmne8/Ad6/2llUIrax78nCdlvZW9quXMaXPTxZvdQqo9N669Og==", + "license": "MIT", + "dependencies": { + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/subscribable/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/subscribable/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/sysvars": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/sysvars/-/sysvars-2.3.0.tgz", + "integrity": "sha512-LvjADZrpZ+CnhlHqfI5cmsRzX9Rpyb1Ox2dMHnbsRNzeKAMhu9w4ZBIaeTdO322zsTr509G1B+k2ABD3whvUBA==", + "license": "MIT", + "dependencies": { + "@solana/accounts": "2.3.0", + "@solana/codecs": "2.3.0", + "@solana/errors": "2.3.0", + "@solana/rpc-types": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/sysvars/node_modules/@solana/codecs": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs/-/codecs-2.3.0.tgz", + "integrity": "sha512-JVqGPkzoeyU262hJGdH64kNLH0M+Oew2CIPOa/9tR3++q2pEd4jU2Rxdfye9sd0Ce3XJrR5AIa8ZfbyQXzjh+g==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-data-structures": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/codecs-strings": "2.3.0", + "@solana/options": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/sysvars/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/sysvars/node_modules/@solana/codecs-data-structures": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-data-structures/-/codecs-data-structures-2.3.0.tgz", + "integrity": "sha512-qvU5LE5DqEdYMYgELRHv+HMOx73sSoV1ZZkwIrclwUmwTbTaH8QAJURBj0RhQ/zCne7VuLLOZFFGv6jGigWhSw==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/sysvars/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/sysvars/node_modules/@solana/codecs-strings": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-strings/-/codecs-strings-2.3.0.tgz", + "integrity": "sha512-y5pSBYwzVziXu521hh+VxqUtp0hYGTl1eWGoc1W+8mdvBdC1kTqm/X7aYQw33J42hw03JjryvYOvmGgk3Qz/Ug==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "fastestsmallesttextencoderdecoder": "^1.0.22", + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/sysvars/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/sysvars/node_modules/@solana/options": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/options/-/options-2.3.0.tgz", + "integrity": "sha512-PPnnZBRCWWoZQ11exPxf//DRzN2C6AoFsDI/u2AsQfYih434/7Kp4XLpfOMT/XESi+gdBMFNNfbES5zg3wAIkw==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-data-structures": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/codecs-strings": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/sysvars/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/transaction-confirmation": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/transaction-confirmation/-/transaction-confirmation-2.3.0.tgz", + "integrity": "sha512-UiEuiHCfAAZEKdfne/XljFNJbsKAe701UQHKXEInYzIgBjRbvaeYZlBmkkqtxwcasgBTOmEaEKT44J14N9VZDw==", + "license": "MIT", + "dependencies": { + "@solana/addresses": "2.3.0", + "@solana/codecs-strings": "2.3.0", + "@solana/errors": "2.3.0", + "@solana/keys": "2.3.0", + "@solana/promises": "2.3.0", + "@solana/rpc": "2.3.0", + "@solana/rpc-subscriptions": "2.3.0", + "@solana/rpc-types": "2.3.0", + "@solana/transaction-messages": "2.3.0", + "@solana/transactions": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/transaction-confirmation/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/transaction-confirmation/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/transaction-confirmation/node_modules/@solana/codecs-strings": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-strings/-/codecs-strings-2.3.0.tgz", + "integrity": "sha512-y5pSBYwzVziXu521hh+VxqUtp0hYGTl1eWGoc1W+8mdvBdC1kTqm/X7aYQw33J42hw03JjryvYOvmGgk3Qz/Ug==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "fastestsmallesttextencoderdecoder": "^1.0.22", + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/transaction-confirmation/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/transaction-confirmation/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/transaction-messages": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/transaction-messages/-/transaction-messages-2.3.0.tgz", + "integrity": "sha512-bgqvWuy3MqKS5JdNLH649q+ngiyOu5rGS3DizSnWwYUd76RxZl1kN6CoqHSrrMzFMvis6sck/yPGG3wqrMlAww==", + "license": "MIT", + "dependencies": { + "@solana/addresses": "2.3.0", + "@solana/codecs-core": "2.3.0", + "@solana/codecs-data-structures": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/errors": "2.3.0", + "@solana/functional": "2.3.0", + "@solana/instructions": "2.3.0", + "@solana/nominal-types": "2.3.0", + "@solana/rpc-types": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/transaction-messages/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/transaction-messages/node_modules/@solana/codecs-data-structures": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-data-structures/-/codecs-data-structures-2.3.0.tgz", + "integrity": "sha512-qvU5LE5DqEdYMYgELRHv+HMOx73sSoV1ZZkwIrclwUmwTbTaH8QAJURBj0RhQ/zCne7VuLLOZFFGv6jGigWhSw==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/transaction-messages/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/transaction-messages/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/transaction-messages/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/transactions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/transactions/-/transactions-2.3.0.tgz", + "integrity": "sha512-LnTvdi8QnrQtuEZor5Msje61sDpPstTVwKg4y81tNxDhiyomjuvnSNLAq6QsB9gIxUqbNzPZgOG9IU4I4/Uaug==", + "license": "MIT", + "dependencies": { + "@solana/addresses": "2.3.0", + "@solana/codecs-core": "2.3.0", + "@solana/codecs-data-structures": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/codecs-strings": "2.3.0", + "@solana/errors": "2.3.0", + "@solana/functional": "2.3.0", + "@solana/instructions": "2.3.0", + "@solana/keys": "2.3.0", + "@solana/nominal-types": "2.3.0", + "@solana/rpc-types": "2.3.0", + "@solana/transaction-messages": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/transactions/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/transactions/node_modules/@solana/codecs-data-structures": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-data-structures/-/codecs-data-structures-2.3.0.tgz", + "integrity": "sha512-qvU5LE5DqEdYMYgELRHv+HMOx73sSoV1ZZkwIrclwUmwTbTaH8QAJURBj0RhQ/zCne7VuLLOZFFGv6jGigWhSw==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/transactions/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/transactions/node_modules/@solana/codecs-strings": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-strings/-/codecs-strings-2.3.0.tgz", + "integrity": "sha512-y5pSBYwzVziXu521hh+VxqUtp0hYGTl1eWGoc1W+8mdvBdC1kTqm/X7aYQw33J42hw03JjryvYOvmGgk3Qz/Ug==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "fastestsmallesttextencoderdecoder": "^1.0.22", + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/transactions/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/transactions/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "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/@solana/web3.js/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/web3.js/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/web3.js/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/web3.js/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@swc/helpers": { + "version": "0.5.17", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz", + "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@tanstack/query-core": { + "version": "5.89.0", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.89.0.tgz", + "integrity": "sha512-joFV1MuPhSLsKfTzwjmPDrp8ENfZ9N23ymFu07nLfn3JCkSHy0CFgsyhHTJOmWaumC/WiNIKM0EJyduCF/Ih/Q==", + "license": "MIT", + "peer": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.89.0", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.89.0.tgz", + "integrity": "sha512-SXbtWSTSRXyBOe80mszPxpEbaN4XPRUp/i0EfQK1uyj3KCk/c8FuPJNIRwzOVe/OU3rzxrYtiNabsAmk1l714A==", + "license": "MIT", + "peer": true, + "dependencies": { + "@tanstack/query-core": "5.89.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18 || ^19" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "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/cors": { + "version": "2.8.19", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", + "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.23.tgz", + "integrity": "sha512-Crp6WY9aTYP3qPi2wGDo9iUe/rceX01UMhnF1jmwDcKCFM6cx7YhGP/Mpr3y9AASpfHixIG0E6azCcL5OcDHsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.6", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", + "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==", + "license": "MIT" + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.19.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.17.tgz", + "integrity": "sha512-gfehUI8N1z92kygssiuWvLiwcbOB3IRktR6hTDgJlXMYh5OvkPSRmgfoBUmfZt+vhwJtX7v1Yw4KvvAf7c5QKQ==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "0.17.5", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz", + "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.8", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.8.tgz", + "integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT" + }, + "node_modules/@types/uuid": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", + "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==", + "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/@wagmi/connectors": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/@wagmi/connectors/-/connectors-5.10.0.tgz", + "integrity": "sha512-pG9a9PIOkxfJQF7kSdMUfPjZ52LOPjXboga99LnZHh+VXmXd2J93r7NGYO3kF0lhrt3hdbmYYsZCOgbPkXiHig==", + "license": "MIT", + "dependencies": { + "@base-org/account": "1.1.1", + "@coinbase/wallet-sdk": "4.3.6", + "@gemini-wallet/core": "0.2.0", + "@metamask/sdk": "0.32.0", + "@safe-global/safe-apps-provider": "0.18.6", + "@safe-global/safe-apps-sdk": "9.1.0", + "@walletconnect/ethereum-provider": "2.21.1", + "cbw-sdk": "npm:@coinbase/wallet-sdk@3.9.3" + }, + "funding": { + "url": "https://github.com/sponsors/wevm" + }, + "peerDependencies": { + "@wagmi/core": "2.21.0", + "typescript": ">=5.0.4", + "viem": "2.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@wagmi/core": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@wagmi/core/-/core-2.21.0.tgz", + "integrity": "sha512-ZtQBUvHEyfSM22BCeXZDjwcpby2vZjivjP8mMkQHxuVqRDnunaS5DIlZr2XPJKv01lPdlUajFSoiziNcIZlH5w==", + "license": "MIT", + "dependencies": { + "eventemitter3": "5.0.1", + "mipd": "0.0.7", + "zustand": "5.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/wevm" + }, + "peerDependencies": { + "@tanstack/query-core": ">=5.0.0", + "typescript": ">=5.0.4", + "viem": "2.x" + }, + "peerDependenciesMeta": { + "@tanstack/query-core": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/@wagmi/core/node_modules/zustand": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.0.tgz", + "integrity": "sha512-LE+VcmbartOPM+auOjCCLQOsQ05zUTp8RkgwRzefUk+2jISdMMFnxvyTjA4YNWr5ZGXYbVsEMZosttuxUBkojQ==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=18.0.0", + "immer": ">=9.0.6", + "react": ">=18.0.0", + "use-sync-external-store": ">=1.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + }, + "use-sync-external-store": { + "optional": true + } + } + }, + "node_modules/@walletconnect/core": { + "version": "2.21.1", + "resolved": "https://registry.npmjs.org/@walletconnect/core/-/core-2.21.1.tgz", + "integrity": "sha512-Tp4MHJYcdWD846PH//2r+Mu4wz1/ZU/fr9av1UWFiaYQ2t2TPLDiZxjLw54AAEpMqlEHemwCgiRiAmjR1NDdTQ==", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-provider": "1.0.14", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/jsonrpc-ws-connection": "1.0.16", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "2.1.2", + "@walletconnect/relay-api": "1.0.11", + "@walletconnect/relay-auth": "1.1.0", + "@walletconnect/safe-json": "1.0.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.21.1", + "@walletconnect/utils": "2.21.1", + "@walletconnect/window-getters": "1.0.1", + "es-toolkit": "1.33.0", + "events": "3.3.0", + "uint8arrays": "3.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@walletconnect/environment": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@walletconnect/environment/-/environment-1.0.1.tgz", + "integrity": "sha512-T426LLZtHj8e8rYnKfzsw1aG6+M0BT1ZxayMdv/p8yM0MU+eJDISqNY3/bccxRr4LrF9csq02Rhqt08Ibl0VRg==", + "license": "MIT", + "dependencies": { + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/environment/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, + "node_modules/@walletconnect/ethereum-provider": { + "version": "2.21.1", + "resolved": "https://registry.npmjs.org/@walletconnect/ethereum-provider/-/ethereum-provider-2.21.1.tgz", + "integrity": "sha512-SSlIG6QEVxClgl1s0LMk4xr2wg4eT3Zn/Hb81IocyqNSGfXpjtawWxKxiC5/9Z95f1INyBD6MctJbL/R1oBwIw==", + "license": "Apache-2.0", + "dependencies": { + "@reown/appkit": "1.7.8", + "@walletconnect/jsonrpc-http-connection": "1.0.8", + "@walletconnect/jsonrpc-provider": "1.0.14", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/sign-client": "2.21.1", + "@walletconnect/types": "2.21.1", + "@walletconnect/universal-provider": "2.21.1", + "@walletconnect/utils": "2.21.1", + "events": "3.3.0" + } + }, + "node_modules/@walletconnect/events": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@walletconnect/events/-/events-1.0.1.tgz", + "integrity": "sha512-NPTqaoi0oPBVNuLv7qPaJazmGHs5JGyO8eEAk5VGKmJzDR7AHzD4k6ilox5kxk1iwiOnFopBOOMLs86Oa76HpQ==", + "license": "MIT", + "dependencies": { + "keyvaluestorage-interface": "^1.0.0", + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/events/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, + "node_modules/@walletconnect/heartbeat": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@walletconnect/heartbeat/-/heartbeat-1.2.2.tgz", + "integrity": "sha512-uASiRmC5MwhuRuf05vq4AT48Pq8RMi876zV8rr8cV969uTOzWdB/k+Lj5yI2PBtB1bGQisGen7MM1GcZlQTBXw==", + "license": "MIT", + "dependencies": { + "@walletconnect/events": "^1.0.1", + "@walletconnect/time": "^1.0.2", + "events": "^3.3.0" + } + }, + "node_modules/@walletconnect/jsonrpc-http-connection": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-http-connection/-/jsonrpc-http-connection-1.0.8.tgz", + "integrity": "sha512-+B7cRuaxijLeFDJUq5hAzNyef3e3tBDIxyaCNmFtjwnod5AGis3RToNqzFU33vpVcxFhofkpE7Cx+5MYejbMGw==", + "license": "MIT", + "dependencies": { + "@walletconnect/jsonrpc-utils": "^1.0.6", + "@walletconnect/safe-json": "^1.0.1", + "cross-fetch": "^3.1.4", + "events": "^3.3.0" + } + }, + "node_modules/@walletconnect/jsonrpc-http-connection/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/@walletconnect/jsonrpc-provider": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-provider/-/jsonrpc-provider-1.0.14.tgz", + "integrity": "sha512-rtsNY1XqHvWj0EtITNeuf8PHMvlCLiS3EjQL+WOkxEOA4KPxsohFnBDeyPYiNm4ZvkQdLnece36opYidmtbmow==", + "license": "MIT", + "dependencies": { + "@walletconnect/jsonrpc-utils": "^1.0.8", + "@walletconnect/safe-json": "^1.0.2", + "events": "^3.3.0" + } + }, + "node_modules/@walletconnect/jsonrpc-types": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-types/-/jsonrpc-types-1.0.4.tgz", + "integrity": "sha512-P6679fG/M+wuWg9TY8mh6xFSdYnFyFjwFelxyISxMDrlbXokorEVXYOxiqEbrU3x1BmBoCAJJ+vtEaEoMlpCBQ==", + "license": "MIT", + "dependencies": { + "events": "^3.3.0", + "keyvaluestorage-interface": "^1.0.0" + } + }, + "node_modules/@walletconnect/jsonrpc-utils": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-utils/-/jsonrpc-utils-1.0.8.tgz", + "integrity": "sha512-vdeb03bD8VzJUL6ZtzRYsFMq1eZQcM3EAzT0a3st59dyLfJ0wq+tKMpmGH7HlB7waD858UWgfIcudbPFsbzVdw==", + "license": "MIT", + "dependencies": { + "@walletconnect/environment": "^1.0.1", + "@walletconnect/jsonrpc-types": "^1.0.3", + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/jsonrpc-utils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, + "node_modules/@walletconnect/jsonrpc-ws-connection": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-ws-connection/-/jsonrpc-ws-connection-1.0.16.tgz", + "integrity": "sha512-G81JmsMqh5nJheE1mPst1W0WfVv0SG3N7JggwLLGnI7iuDZJq8cRJvQwLGKHn5H1WTW7DEPCo00zz5w62AbL3Q==", + "license": "MIT", + "dependencies": { + "@walletconnect/jsonrpc-utils": "^1.0.6", + "@walletconnect/safe-json": "^1.0.2", + "events": "^3.3.0", + "ws": "^7.5.1" + } + }, + "node_modules/@walletconnect/keyvaluestorage": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@walletconnect/keyvaluestorage/-/keyvaluestorage-1.1.1.tgz", + "integrity": "sha512-V7ZQq2+mSxAq7MrRqDxanTzu2RcElfK1PfNYiaVnJgJ7Q7G7hTVwF8voIBx92qsRyGHZihrwNPHuZd1aKkd0rA==", + "license": "MIT", + "dependencies": { + "@walletconnect/safe-json": "^1.0.1", + "idb-keyval": "^6.2.1", + "unstorage": "^1.9.0" + }, + "peerDependencies": { + "@react-native-async-storage/async-storage": "1.x" + }, + "peerDependenciesMeta": { + "@react-native-async-storage/async-storage": { + "optional": true + } + } + }, + "node_modules/@walletconnect/logger": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@walletconnect/logger/-/logger-2.1.2.tgz", + "integrity": "sha512-aAb28I3S6pYXZHQm5ESB+V6rDqIYfsnHaQyzFbwUUBFY4H0OXx/YtTl8lvhUNhMMfb9UxbwEBS253TlXUYJWSw==", + "license": "MIT", + "dependencies": { + "@walletconnect/safe-json": "^1.0.2", + "pino": "7.11.0" + } + }, + "node_modules/@walletconnect/relay-api": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@walletconnect/relay-api/-/relay-api-1.0.11.tgz", + "integrity": "sha512-tLPErkze/HmC9aCmdZOhtVmYZq1wKfWTJtygQHoWtgg722Jd4homo54Cs4ak2RUFUZIGO2RsOpIcWipaua5D5Q==", + "license": "MIT", + "dependencies": { + "@walletconnect/jsonrpc-types": "^1.0.2" + } + }, + "node_modules/@walletconnect/relay-auth": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@walletconnect/relay-auth/-/relay-auth-1.1.0.tgz", + "integrity": "sha512-qFw+a9uRz26jRCDgL7Q5TA9qYIgcNY8jpJzI1zAWNZ8i7mQjaijRnWFKsCHAU9CyGjvt6RKrRXyFtFOpWTVmCQ==", + "license": "MIT", + "dependencies": { + "@noble/curves": "1.8.0", + "@noble/hashes": "1.7.0", + "@walletconnect/safe-json": "^1.0.1", + "@walletconnect/time": "^1.0.2", + "uint8arrays": "^3.0.0" + } + }, + "node_modules/@walletconnect/relay-auth/node_modules/@noble/curves": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.0.tgz", + "integrity": "sha512-j84kjAbzEnQHaSIhRPUmB3/eVXu2k3dKPl2LOrR8fSOIL+89U+7lV117EWHtq/GHM3ReGHM46iRBdZfpc4HRUQ==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.7.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@walletconnect/relay-auth/node_modules/@noble/hashes": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.0.tgz", + "integrity": "sha512-HXydb0DgzTpDPwbVeDGCG1gIu7X6+AuU6Zl6av/E/KG8LMsvPntvq+w17CHRpKBmN6Ybdrt1eP3k4cj8DJa78w==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@walletconnect/safe-json": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@walletconnect/safe-json/-/safe-json-1.0.2.tgz", + "integrity": "sha512-Ogb7I27kZ3LPC3ibn8ldyUr5544t3/STow9+lzz7Sfo808YD7SBWk7SAsdBFlYgP2zDRy2hS3sKRcuSRM0OTmA==", + "license": "MIT", + "dependencies": { + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/safe-json/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, + "node_modules/@walletconnect/sign-client": { + "version": "2.21.1", + "resolved": "https://registry.npmjs.org/@walletconnect/sign-client/-/sign-client-2.21.1.tgz", + "integrity": "sha512-QaXzmPsMnKGV6tc4UcdnQVNOz4zyXgarvdIQibJ4L3EmLat73r5ZVl4c0cCOcoaV7rgM9Wbphgu5E/7jNcd3Zg==", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/core": "2.21.1", + "@walletconnect/events": "1.0.1", + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/logger": "2.1.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.21.1", + "@walletconnect/utils": "2.21.1", + "events": "3.3.0" + } + }, + "node_modules/@walletconnect/time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@walletconnect/time/-/time-1.0.2.tgz", + "integrity": "sha512-uzdd9woDcJ1AaBZRhqy5rNC9laqWGErfc4dxA9a87mPdKOgWMD85mcFo9dIYIts/Jwocfwn07EC6EzclKubk/g==", + "license": "MIT", + "dependencies": { + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/time/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, + "node_modules/@walletconnect/types": { + "version": "2.21.1", + "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-2.21.1.tgz", + "integrity": "sha512-UeefNadqP6IyfwWC1Yi7ux+ljbP2R66PLfDrDm8izmvlPmYlqRerJWJvYO4t0Vvr9wrG4Ko7E0c4M7FaPKT/sQ==", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/events": "1.0.1", + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "2.1.2", + "events": "3.3.0" + } + }, + "node_modules/@walletconnect/universal-provider": { + "version": "2.21.1", + "resolved": "https://registry.npmjs.org/@walletconnect/universal-provider/-/universal-provider-2.21.1.tgz", + "integrity": "sha512-Wjx9G8gUHVMnYfxtasC9poGm8QMiPCpXpbbLFT+iPoQskDDly8BwueWnqKs4Mx2SdIAWAwuXeZ5ojk5qQOxJJg==", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/events": "1.0.1", + "@walletconnect/jsonrpc-http-connection": "1.0.8", + "@walletconnect/jsonrpc-provider": "1.0.14", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "2.1.2", + "@walletconnect/sign-client": "2.21.1", + "@walletconnect/types": "2.21.1", + "@walletconnect/utils": "2.21.1", + "es-toolkit": "1.33.0", + "events": "3.3.0" + } + }, + "node_modules/@walletconnect/utils": { + "version": "2.21.1", + "resolved": "https://registry.npmjs.org/@walletconnect/utils/-/utils-2.21.1.tgz", + "integrity": "sha512-VPZvTcrNQCkbGOjFRbC24mm/pzbRMUq2DSQoiHlhh0X1U7ZhuIrzVtAoKsrzu6rqjz0EEtGxCr3K1TGRqDG4NA==", + "license": "Apache-2.0", + "dependencies": { + "@noble/ciphers": "1.2.1", + "@noble/curves": "1.8.1", + "@noble/hashes": "1.7.1", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/relay-api": "1.0.11", + "@walletconnect/relay-auth": "1.1.0", + "@walletconnect/safe-json": "1.0.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.21.1", + "@walletconnect/window-getters": "1.0.1", + "@walletconnect/window-metadata": "1.0.1", + "bs58": "6.0.0", + "detect-browser": "5.3.0", + "query-string": "7.1.3", + "uint8arrays": "3.1.0", + "viem": "2.23.2" + } + }, + "node_modules/@walletconnect/utils/node_modules/@noble/ciphers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.2.1.tgz", + "integrity": "sha512-rONPWMC7PeExE077uLE4oqWrZ1IvAfz3oH9LibVAcVCopJiA9R62uavnbEzdkVmJYI6M6Zgkbeb07+tWjlq2XA==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@walletconnect/utils/node_modules/@noble/curves": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.1.tgz", + "integrity": "sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.7.1" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@walletconnect/utils/node_modules/@noble/hashes": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz", + "integrity": "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@walletconnect/utils/node_modules/@scure/bip32": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.6.2.tgz", + "integrity": "sha512-t96EPDMbtGgtb7onKKqxRLfE5g05k7uHnHRM2xdE6BP/ZmxaLtPek4J4KfVn/90IQNrU1IOAqMgiDtUdtbe3nw==", + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.8.1", + "@noble/hashes": "~1.7.1", + "@scure/base": "~1.2.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@walletconnect/utils/node_modules/@scure/bip39": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.5.4.tgz", + "integrity": "sha512-TFM4ni0vKvCfBpohoh+/lY05i9gRbSwXWngAsF4CABQxoaOHijxuaZ2R6cStDQ5CHtHO9aGJTr4ksVJASRRyMA==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.7.1", + "@scure/base": "~1.2.4" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@walletconnect/utils/node_modules/abitype": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.8.tgz", + "integrity": "sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/wevm" + }, + "peerDependencies": { + "typescript": ">=5.0.4", + "zod": "^3 >=3.22.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, + "node_modules/@walletconnect/utils/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/@walletconnect/utils/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/@walletconnect/utils/node_modules/isows": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.6.tgz", + "integrity": "sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/@walletconnect/utils/node_modules/ox": { + "version": "0.6.7", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.6.7.tgz", + "integrity": "sha512-17Gk/eFsFRAZ80p5eKqv89a57uXjd3NgIf1CaXojATPBuujVc/fQSVhBeAU9JCRB+k7J50WQAyWTxK19T9GgbA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@adraffy/ens-normalize": "^1.10.1", + "@noble/curves": "^1.6.0", + "@noble/hashes": "^1.5.0", + "@scure/bip32": "^1.5.0", + "@scure/bip39": "^1.4.0", + "abitype": "^1.0.6", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@walletconnect/utils/node_modules/viem": { + "version": "2.23.2", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.23.2.tgz", + "integrity": "sha512-NVmW/E0c5crMOtbEAqMF0e3NmvQykFXhLOc/CkLIXOlzHSA6KXVz3CYVmaKqBF8/xtjsjHAGjdJN3Ru1kFJLaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@noble/curves": "1.8.1", + "@noble/hashes": "1.7.1", + "@scure/bip32": "1.6.2", + "@scure/bip39": "1.5.4", + "abitype": "1.0.8", + "isows": "1.0.6", + "ox": "0.6.7", + "ws": "8.18.0" + }, + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@walletconnect/utils/node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "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/@walletconnect/window-getters": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@walletconnect/window-getters/-/window-getters-1.0.1.tgz", + "integrity": "sha512-vHp+HqzGxORPAN8gY03qnbTMnhqIwjeRJNOMOAzePRg4xVEEE2WvYsI9G2NMjOknA8hnuYbU3/hwLcKbjhc8+Q==", + "license": "MIT", + "dependencies": { + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/window-getters/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, + "node_modules/@walletconnect/window-metadata": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@walletconnect/window-metadata/-/window-metadata-1.0.1.tgz", + "integrity": "sha512-9koTqyGrM2cqFRW517BPY/iEtUDx2r1+Pwwu5m7sJ7ka79wi3EyqhqcICk/yDmv6jAS1rjKgTKXlEhanYjijcA==", + "license": "MIT", + "dependencies": { + "@walletconnect/window-getters": "^1.0.1", + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/window-metadata/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, + "node_modules/abitype": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.6.tgz", + "integrity": "sha512-MMSqYh4+C/aVqI2RQaWqbvI4Kxo5cQV40WQ4QFtDnNzCkqChm8MuENhElmynZlO0qUy/ObkEUaXtKqYnx1Kp3A==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/wevm" + }, + "peerDependencies": { + "typescript": ">=5.0.4", + "zod": "^3 >=3.22.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/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/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/async-mutex": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.2.6.tgz", + "integrity": "sha512-Hs4R+4SPgamu6rSGW8C7cV9gaWUKEHykfzCCvIRuaVv636Ju10ZdeUbvb4TBEW0INuq2DHZqXbK4Nd3yG4RaRw==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + } + }, + "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/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/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.12.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz", + "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axios-retry": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-4.5.0.tgz", + "integrity": "sha512-aR99oXhpEDGo0UuAlYcn2iGRds30k366Zfa05XWScR9QaQD4JYiP3/1Qt1u7YlefUOK+cn0CcwoL1oefavQUlQ==", + "license": "Apache-2.0", + "dependencies": { + "is-retry-allowed": "^2.2.0" + }, + "peerDependencies": { + "axios": "0.x || 1.x" + } + }, + "node_modules/base-x": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz", + "integrity": "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/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.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.2.tgz", + "integrity": "sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==", + "license": "MIT" + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "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/bowser": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.12.1.tgz", + "integrity": "sha512-z4rE2Gxh7tvshQ4hluIT7XcFrgLIQaw9X3A+kTTRdovCz5PMukm/0QC/BKSYPj3omF5Qfypn9O/c5kgpmvYUCw==", + "license": "MIT" + }, + "node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "license": "MIT", + "dependencies": { + "base-x": "^3.0.2" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/bufferutil": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.9.tgz", + "integrity": "sha512-WDtdLmJvAuNNPzByAYpRo2rF1Mmradw6gvWsQKf63476DDXmomT9zUiGypLcG4ibIM67vhAj8jJRdbmEws2Aqw==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "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": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cbw-sdk": { + "name": "@coinbase/wallet-sdk", + "version": "3.9.3", + "resolved": "https://registry.npmjs.org/@coinbase/wallet-sdk/-/wallet-sdk-3.9.3.tgz", + "integrity": "sha512-N/A2DRIf0Y3PHc1XAMvbBUu4zisna6qAdqABMZwBMNEfWrXpAwx16pZGkYCLGE+Rvv1edbcB2LYDRnACNcmCiw==", + "license": "Apache-2.0", + "dependencies": { + "bn.js": "^5.2.1", + "buffer": "^6.0.3", + "clsx": "^1.2.1", + "eth-block-tracker": "^7.1.0", + "eth-json-rpc-filters": "^6.0.0", + "eventemitter3": "^5.0.1", + "keccak": "^3.0.3", + "preact": "^10.16.0", + "sha.js": "^2.4.11" + } + }, + "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/charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", + "license": "BSD-3-Clause", + "engines": { + "node": "*" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/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": "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/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-es": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-1.2.2.tgz", + "integrity": "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==", + "license": "MIT" + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "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": "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/crossws": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/crossws/-/crossws-0.3.5.tgz", + "integrity": "sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==", + "license": "MIT", + "dependencies": { + "uncrypto": "^0.1.3" + } + }, + "node_modules/crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", + "license": "BSD-3-Clause", + "engines": { + "node": "*" + } + }, + "node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "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/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "license": "MIT" + }, + "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/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/derive-valtio": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/derive-valtio/-/derive-valtio-0.1.0.tgz", + "integrity": "sha512-OCg2UsLbXK7GmmpzMXhYkdO64vhJ1ROUUGaTFyHjVwEdMEcTTRj7W1TxLbSBxdY8QLBPCcp66MTyaSy0RpO17A==", + "license": "MIT", + "peerDependencies": { + "valtio": "*" + } + }, + "node_modules/destr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", + "license": "MIT" + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-browser": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/detect-browser/-/detect-browser-5.3.0.tgz", + "integrity": "sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w==", + "license": "MIT" + }, + "node_modules/dijkstrajs": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", + "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==", + "license": "MIT" + }, + "node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "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/duplexify": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz", + "integrity": "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.2" + } + }, + "node_modules/eciesjs": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/eciesjs/-/eciesjs-0.4.15.tgz", + "integrity": "sha512-r6kEJXDKecVOCj2nLMuXK/FCPeurW33+3JRpfXVbjLja3XUYFfD9I/JBreH6sUyzcm3G/YQboBjMla6poKeSdA==", + "license": "MIT", + "dependencies": { + "@ecies/ciphers": "^0.2.3", + "@noble/ciphers": "^1.3.0", + "@noble/curves": "^1.9.1", + "@noble/hashes": "^1.8.0" + }, + "engines": { + "bun": ">=1", + "deno": ">=2", + "node": ">=16" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/encode-utf8": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz", + "integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/engine.io-client": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz", + "integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==", + "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.1.1" + } + }, + "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/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/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.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/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/es-toolkit": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.33.0.tgz", + "integrity": "sha512-X13Q/ZSc+vsO1q600bvNK4bxgXMkHcf//RxCmYDaRY5DAcT+eoXjY5hoAPGMdRnWQjvyLEcyauG3b6hz76LNqg==", + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks" + ] + }, + "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.25.10", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.10.tgz", + "integrity": "sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.10", + "@esbuild/android-arm": "0.25.10", + "@esbuild/android-arm64": "0.25.10", + "@esbuild/android-x64": "0.25.10", + "@esbuild/darwin-arm64": "0.25.10", + "@esbuild/darwin-x64": "0.25.10", + "@esbuild/freebsd-arm64": "0.25.10", + "@esbuild/freebsd-x64": "0.25.10", + "@esbuild/linux-arm": "0.25.10", + "@esbuild/linux-arm64": "0.25.10", + "@esbuild/linux-ia32": "0.25.10", + "@esbuild/linux-loong64": "0.25.10", + "@esbuild/linux-mips64el": "0.25.10", + "@esbuild/linux-ppc64": "0.25.10", + "@esbuild/linux-riscv64": "0.25.10", + "@esbuild/linux-s390x": "0.25.10", + "@esbuild/linux-x64": "0.25.10", + "@esbuild/netbsd-arm64": "0.25.10", + "@esbuild/netbsd-x64": "0.25.10", + "@esbuild/openbsd-arm64": "0.25.10", + "@esbuild/openbsd-x64": "0.25.10", + "@esbuild/openharmony-arm64": "0.25.10", + "@esbuild/sunos-x64": "0.25.10", + "@esbuild/win32-arm64": "0.25.10", + "@esbuild/win32-ia32": "0.25.10", + "@esbuild/win32-x64": "0.25.10" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eth-block-tracker": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/eth-block-tracker/-/eth-block-tracker-7.1.0.tgz", + "integrity": "sha512-8YdplnuE1IK4xfqpf4iU7oBxnOYAc35934o083G8ao+8WM8QQtt/mVlAY6yIAdY1eMeLqg4Z//PZjJGmWGPMRg==", + "license": "MIT", + "dependencies": { + "@metamask/eth-json-rpc-provider": "^1.0.0", + "@metamask/safe-event-emitter": "^3.0.0", + "@metamask/utils": "^5.0.1", + "json-rpc-random-id": "^1.0.1", + "pify": "^3.0.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/eth-block-tracker/node_modules/@metamask/utils": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-5.0.2.tgz", + "integrity": "sha512-yfmE79bRQtnMzarnKfX7AEJBwFTxvTyw3nBQlu/5rmGXrjAeAMltoGxO62TFurxrQAFMNa/fEjIHNvungZp0+g==", + "license": "ISC", + "dependencies": { + "@ethereumjs/tx": "^4.1.2", + "@types/debug": "^4.1.7", + "debug": "^4.3.4", + "semver": "^7.3.8", + "superstruct": "^1.0.3" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/eth-block-tracker/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/eth-block-tracker/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/eth-block-tracker/node_modules/superstruct": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-1.0.4.tgz", + "integrity": "sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/eth-json-rpc-filters": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/eth-json-rpc-filters/-/eth-json-rpc-filters-6.0.1.tgz", + "integrity": "sha512-ITJTvqoCw6OVMLs7pI8f4gG92n/St6x80ACtHodeS+IXmO0w+t1T5OOzfSt7KLSMLRkVUoexV7tztLgDxg+iig==", + "license": "ISC", + "dependencies": { + "@metamask/safe-event-emitter": "^3.0.0", + "async-mutex": "^0.2.6", + "eth-query": "^2.1.2", + "json-rpc-engine": "^6.1.0", + "pify": "^5.0.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/eth-json-rpc-filters/node_modules/pify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", + "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eth-query": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/eth-query/-/eth-query-2.1.2.tgz", + "integrity": "sha512-srES0ZcvwkR/wd5OQBRA1bIJMww1skfGS0s8wlwK3/oNP4+wnds60krvu5R1QbpRQjMmpG5OMIWro5s7gvDPsA==", + "license": "ISC", + "dependencies": { + "json-rpc-random-id": "^1.0.0", + "xtend": "^4.0.1" + } + }, + "node_modules/eth-rpc-errors": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eth-rpc-errors/-/eth-rpc-errors-4.0.3.tgz", + "integrity": "sha512-Z3ymjopaoft7JDoxZcEb3pwdGh7yiYMhOwm2doUt6ASXlMavpNlK6Cre0+IMl2VSGyEU9rkiperQhp5iRxn5Pg==", + "license": "MIT", + "dependencies": { + "fast-safe-stringify": "^2.0.6" + } + }, + "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/eventemitter2": { + "version": "6.4.9", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz", + "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==", + "license": "MIT" + }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/express": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.12", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/extension-port-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/extension-port-stream/-/extension-port-stream-3.0.0.tgz", + "integrity": "sha512-an2S5quJMiy5bnZKEf6AkfH/7r8CzHvhchU40gxN+OM6HPhe7Z9T1FUychcf2M9PpPOO0Hf7BAEfJkw2TDIBDw==", + "license": "ISC", + "dependencies": { + "readable-stream": "^3.6.2 || ^4.4.2", + "webextension-polyfill": ">=0.10.0 <1.0" + }, + "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-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-redact": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", + "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "license": "MIT" + }, + "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/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/filter-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", + "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "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.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/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/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "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/get-tsconfig": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", + "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "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/h3": { + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.4.tgz", + "integrity": "sha512-z5cFQWDffyOe4vQ9xIqNfCZdV4p//vy6fBnr8Q1AWnVZ0teurKMG66rLj++TKwKPUP3u7iMUvrvKaEUiQw2QWQ==", + "license": "MIT", + "dependencies": { + "cookie-es": "^1.2.2", + "crossws": "^0.3.5", + "defu": "^6.1.4", + "destr": "^2.0.5", + "iron-webcrypto": "^1.2.1", + "node-mock-http": "^1.0.2", + "radix3": "^1.1.2", + "ufo": "^1.6.1", + "uncrypto": "^0.1.3" + } + }, + "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.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "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/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/idb-keyval": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.1.tgz", + "integrity": "sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==", + "license": "Apache-2.0" + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/iron-webcrypto": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz", + "integrity": "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/brc-dd" + } + }, + "node_modules/is-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-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "license": "MIT" + }, + "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-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", + "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-proto": "^1.0.0", + "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-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": "2.2.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-2.2.0.tgz", + "integrity": "sha512-XVm7LOeLpTW4jV19QSH38vkswxoLud8sQ57YwJVTPWdiaI9I8keEhGFpBlslyVsgdQy4Opg8QOLb8YRgsyZiQg==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "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.2.0", + "resolved": "https://registry.npmjs.org/jayson/-/jayson-4.2.0.tgz", + "integrity": "sha512-VfJ9t1YLwacIubLhONk0KFeosUBwstRWQ0IRT1KDjEjnVnSOVHC3uwugyV7L0c7R9lpVyrUGT2XWiBA1UTtpyg==", + "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/@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/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": "6.1.0", + "resolved": "https://registry.npmjs.org/jose/-/jose-6.1.0.tgz", + "integrity": "sha512-TTQJyoEoKcC1lscpVDCSsVgYzUDg/0Bt3WE//WiTPK6uOCQC2KZS4MpugbMWt/zyjkopgZoXhZuCi00gLudfUA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT", + "peer": true + }, + "node_modules/json-rpc-engine": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/json-rpc-engine/-/json-rpc-engine-6.1.0.tgz", + "integrity": "sha512-NEdLrtrq1jUZyfjkr9OCz9EzCNhnRyWtt1PAnvnhwy6e8XETS0Dtc+ZNCO2gvuAoKsIn2+vCSowXTYE4CkgnAQ==", + "license": "ISC", + "dependencies": { + "@metamask/safe-event-emitter": "^2.0.0", + "eth-rpc-errors": "^4.0.2" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/json-rpc-engine/node_modules/@metamask/safe-event-emitter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@metamask/safe-event-emitter/-/safe-event-emitter-2.0.0.tgz", + "integrity": "sha512-/kSXhY692qiV1MXu6EeOZvg5nECLclxNXcKCxJ3cXQgYuRymRHpdx/t7JXfsK+JLjwA1e1c1/SBrlQYpusC29Q==", + "license": "ISC" + }, + "node_modules/json-rpc-random-id": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz", + "integrity": "sha512-RJ9YYNCkhVDBuP4zN5BBtYAzEl03yq/jIIsyif0JY9qyJuQQZNeDK7anAPKKlyEtLSj2s8h6hNh2F8zO5q7ScA==", + "license": "ISC" + }, + "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/keccak": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz", + "integrity": "sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/keyvaluestorage-interface": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/keyvaluestorage-interface/-/keyvaluestorage-interface-1.0.0.tgz", + "integrity": "sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g==", + "license": "MIT" + }, + "node_modules/lit": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lit/-/lit-3.3.0.tgz", + "integrity": "sha512-DGVsqsOIHBww2DqnuZzW7QsuCdahp50ojuDaBPC7jUDRpYoH0z7kHBBYZewRzer75FwtrkmkKk7iOAwSaWdBmw==", + "license": "BSD-3-Clause", + "dependencies": { + "@lit/reactive-element": "^2.1.0", + "lit-element": "^4.2.0", + "lit-html": "^3.3.0" + } + }, + "node_modules/lit-element": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.2.1.tgz", + "integrity": "sha512-WGAWRGzirAgyphK2urmYOV72tlvnxw7YfyLDgQ+OZnM9vQQBQnumQ7jUJe6unEzwGU3ahFOjuz1iz1jjrpCPuw==", + "license": "BSD-3-Clause", + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.4.0", + "@lit/reactive-element": "^2.1.0", + "lit-html": "^3.3.0" + } + }, + "node_modules/lit-html": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.3.1.tgz", + "integrity": "sha512-S9hbyDu/vs1qNrithiNyeyv64c9yqiW9l+DBgI18fL+MTvOtWoFR0FWiyq1TxaYef5wNlpEmzlXoBlZEO+WjoA==", + "license": "BSD-3-Clause", + "dependencies": { + "@types/trusted-types": "^2.0.2" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "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/md5": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", + "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", + "license": "BSD-3-Clause", + "dependencies": { + "charenc": "0.0.2", + "crypt": "0.0.2", + "is-buffer": "~1.1.6" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micro-ftch": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/micro-ftch/-/micro-ftch-0.3.1.tgz", + "integrity": "sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==", + "license": "MIT" + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mipd": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mipd/-/mipd-0.0.7.tgz", + "integrity": "sha512-aAPZPNDQ3uMTdKbuO2YmAw2TxLHO0moa4YKAyETM/DTj5FloZo+a+8tU+iv4GmW+sOxKLSRwcSFuczk+Cpt6fg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wagmi-dev" + } + ], + "license": "MIT", + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/multiformats": { + "version": "9.9.0", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz", + "integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==", + "license": "(Apache-2.0 AND MIT)" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-addon-api": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", + "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-fetch-native": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", + "license": "MIT" + }, + "node_modules/node-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", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/node-mock-http": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.3.tgz", + "integrity": "sha512-jN8dK25fsfnMrVsEhluUTPkBFY+6ybu7jSB1n+ri/vOGjJxU8J9CZhpSGkHXSkFjtUhbmoncG/YG9ta5Ludqog==", + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/obj-multiplex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/obj-multiplex/-/obj-multiplex-1.0.0.tgz", + "integrity": "sha512-0GNJAOsHoBHeNTvl5Vt6IWnpUEcc3uSRxzBri7EDyIcMgYvnY2JL2qdeV5zTMjWQX5OHcD5amcW2HFfDh0gjIA==", + "license": "ISC", + "dependencies": { + "end-of-stream": "^1.4.0", + "once": "^1.4.0", + "readable-stream": "^2.3.3" + } + }, + "node_modules/obj-multiplex/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/obj-multiplex/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/obj-multiplex/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/obj-multiplex/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ofetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.4.1.tgz", + "integrity": "sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw==", + "license": "MIT", + "dependencies": { + "destr": "^2.0.3", + "node-fetch-native": "^1.6.4", + "ufo": "^1.5.4" + } + }, + "node_modules/on-exit-leak-free": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-0.2.0.tgz", + "integrity": "sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg==", + "license": "MIT" + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/ox": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.9.3.tgz", + "integrity": "sha512-KzyJP+fPV4uhuuqrTZyok4DC7vFzi7HLUFiUNEmpbyh59htKWkOC98IONC1zgXJPbHAhQgqs6B0Z6StCGhmQvg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@adraffy/ens-normalize": "^1.11.0", + "@noble/ciphers": "^1.3.0", + "@noble/curves": "1.9.1", + "@noble/hashes": "^1.8.0", + "@scure/bip32": "^1.7.0", + "@scure/bip39": "^1.6.0", + "abitype": "^1.0.9", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/ox/node_modules/@noble/curves": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.1.tgz", + "integrity": "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ox/node_modules/abitype": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.1.0.tgz", + "integrity": "sha512-6Vh4HcRxNMLA0puzPjM5GBgT4aAcFGKZzSgAXvuZ27shJP6NEpielTuqbBmZILR5/xd0PizkBGy5hReKz9jl5A==", + "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/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/pino": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-7.11.0.tgz", + "integrity": "sha512-dMACeu63HtRLmCG8VKdy4cShCPKaYDR4youZqoSWLxl5Gu99HUw8bw75thbPv9Nip+H+QYX8o3ZJbTdVZZ2TVg==", + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.0.0", + "on-exit-leak-free": "^0.2.0", + "pino-abstract-transport": "v0.5.0", + "pino-std-serializers": "^4.0.0", + "process-warning": "^1.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.1.0", + "safe-stable-stringify": "^2.1.0", + "sonic-boom": "^2.2.1", + "thread-stream": "^0.15.1" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-0.5.0.tgz", + "integrity": "sha512-+KAgmVeqXYbTtU2FScx1XS3kNyfZ5TrXY07V96QnUSFqo2gAqlvmaxH67Lj7SWazqsMabf+58ctdTcBgnOLUOQ==", + "license": "MIT", + "dependencies": { + "duplexify": "^4.1.2", + "split2": "^4.0.0" + } + }, + "node_modules/pino-std-serializers": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-4.0.0.tgz", + "integrity": "sha512-cK0pekc1Kjy5w9V2/n+8MkZwusa6EyyxfeQCB799CQRhRt/CqYKiWs5adeu8Shve2ZNffvfC/7J64A2PJo1W/Q==", + "license": "MIT" + }, + "node_modules/pngjs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", + "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/pony-cause": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/pony-cause/-/pony-cause-2.1.11.tgz", + "integrity": "sha512-M7LhCsdNbNgiLYiP4WjsfLUuFmCfnjdF6jKe2R9NKl4WFN+HZPGHJZ9lnLP7f9ZnKe3U9nuWD0szirmj+migUg==", + "license": "0BSD", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/preact": { + "version": "10.24.2", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.24.2.tgz", + "integrity": "sha512-1cSoF0aCC8uaARATfrlz4VCBqE8LwZwRfLgkxJOQwAlQt6ayTmi0D9OF7nXid1POI5SZidFuG9CnlXbDfLqY/Q==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, + "node_modules/process-warning": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-1.0.0.tgz", + "integrity": "sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==", + "license": "MIT" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-compare": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-2.6.0.tgz", + "integrity": "sha512-8xuCeM3l8yqdmbPoYeLbrAXCBWu19XEYc5/F28f5qOaoAIMyfmBUkl5axiK+x9olUvRlcekvnm98AP9RDngOIw==", + "license": "MIT" + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/qrcode": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.3.tgz", + "integrity": "sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==", + "license": "MIT", + "dependencies": { + "dijkstrajs": "^1.0.1", + "encode-utf8": "^1.0.3", + "pngjs": "^5.0.0", + "yargs": "^15.3.1" + }, + "bin": { + "qrcode": "bin/qrcode" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/query-string": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz", + "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==", + "license": "MIT", + "dependencies": { + "decode-uri-component": "^0.2.2", + "filter-obj": "^1.1.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", + "license": "MIT" + }, + "node_modules/radix3": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.2.tgz", + "integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==", + "license": "MIT" + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/real-require": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.1.0.tgz", + "integrity": "sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg==", + "license": "MIT", + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "license": "ISC" + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/rpc-websockets": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-9.1.3.tgz", + "integrity": "sha512-I+kNjW0udB4Fetr3vvtRuYZJS0PcSPyyvBcH5sDdoV8DFs5E4W2pTr7aiMlKfPxANTClP9RlqCPolj9dd5MsEA==", + "license": "LGPL-3.0-only", + "dependencies": { + "@swc/helpers": "^0.5.11", + "@types/uuid": "^8.3.4", + "@types/ws": "^8.2.2", + "buffer": "^6.0.3", + "eventemitter3": "^5.0.1", + "uuid": "^8.3.2", + "ws": "^8.5.0" + }, + "funding": { + "type": "paypal", + "url": "https://paypal.me/kozjak" + }, + "optionalDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + } + }, + "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/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/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/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC" + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "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/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "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/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/socket.io-client": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz", + "integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.6.1", + "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-client/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/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser/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/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/sonic-boom": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-2.8.0.tgz", + "integrity": "sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg==", + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, + "node_modules/split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "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/stream-shift": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", + "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", + "license": "MIT" + }, + "node_modules/strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/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/thread-stream": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-0.15.2.tgz", + "integrity": "sha512-UkEhKIg2pD+fjkHQKyJO3yoIvAP3N6RlNFt2dUhcS1FGvCD1cQa1M/PGknCLFIyZdtJOWQjejp7bdNqmN7zwdA==", + "license": "MIT", + "dependencies": { + "real-require": "^0.1.0" + } + }, + "node_modules/to-buffer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.1.tgz", + "integrity": "sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==", + "license": "MIT", + "dependencies": { + "isarray": "^2.0.5", + "safe-buffer": "^5.2.1", + "typed-array-buffer": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/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.20.5", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.5.tgz", + "integrity": "sha512-+wKjMNU9w/EaQayHXb7WA7ZaHY6hN8WgfvHNQ3t1PnU91/7O8TcTnIhCDYTZwnt8JsO9IBqZ30Ln1r7pPF52Aw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.25.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/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.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/ufo": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", + "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", + "license": "MIT" + }, + "node_modules/uint8arrays": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.1.0.tgz", + "integrity": "sha512-ei5rfKtoRO8OyOIor2Rz5fhzjThwIHJZ3uyDPnDHTXbP0aMQ1RN/6AI5B5d9dBxJOU+BvOAk7ZQ1xphsX8Lrog==", + "license": "MIT", + "dependencies": { + "multiformats": "^9.4.2" + } + }, + "node_modules/uncrypto": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz", + "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==", + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unstorage": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.1.tgz", + "integrity": "sha512-KKGwRTT0iVBCErKemkJCLs7JdxNVfqTPc/85ae1XES0+bsHbc/sFBfVi5kJp156cc51BHinIH2l3k0EZ24vOBQ==", + "license": "MIT", + "dependencies": { + "anymatch": "^3.1.3", + "chokidar": "^4.0.3", + "destr": "^2.0.5", + "h3": "^1.15.4", + "lru-cache": "^10.4.3", + "node-fetch-native": "^1.6.7", + "ofetch": "^1.4.1", + "ufo": "^1.6.1" + }, + "peerDependencies": { + "@azure/app-configuration": "^1.8.0", + "@azure/cosmos": "^4.2.0", + "@azure/data-tables": "^13.3.0", + "@azure/identity": "^4.6.0", + "@azure/keyvault-secrets": "^4.9.0", + "@azure/storage-blob": "^12.26.0", + "@capacitor/preferences": "^6.0.3 || ^7.0.0", + "@deno/kv": ">=0.9.0", + "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", + "@planetscale/database": "^1.19.0", + "@upstash/redis": "^1.34.3", + "@vercel/blob": ">=0.27.1", + "@vercel/functions": "^2.2.12 || ^3.0.0", + "@vercel/kv": "^1.0.1", + "aws4fetch": "^1.0.20", + "db0": ">=0.2.1", + "idb-keyval": "^6.2.1", + "ioredis": "^5.4.2", + "uploadthing": "^7.4.4" + }, + "peerDependenciesMeta": { + "@azure/app-configuration": { + "optional": true + }, + "@azure/cosmos": { + "optional": true + }, + "@azure/data-tables": { + "optional": true + }, + "@azure/identity": { + "optional": true + }, + "@azure/keyvault-secrets": { + "optional": true + }, + "@azure/storage-blob": { + "optional": true + }, + "@capacitor/preferences": { + "optional": true + }, + "@deno/kv": { + "optional": true + }, + "@netlify/blobs": { + "optional": true + }, + "@planetscale/database": { + "optional": true + }, + "@upstash/redis": { + "optional": true + }, + "@vercel/blob": { + "optional": true + }, + "@vercel/functions": { + "optional": true + }, + "@vercel/kv": { + "optional": true + }, + "aws4fetch": { + "optional": true + }, + "db0": { + "optional": true + }, + "idb-keyval": { + "optional": true + }, + "ioredis": { + "optional": true + }, + "uploadthing": { + "optional": true + } + } + }, + "node_modules/use-sync-external-store": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz", + "integrity": "sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/utf-8-validate": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", + "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, + "node_modules/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/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "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==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/valtio": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/valtio/-/valtio-1.13.2.tgz", + "integrity": "sha512-Qik0o+DSy741TmkqmRfjq+0xpZBXi/Y6+fXZLn0xNF1z/waFMbE3rkivv5Zcf9RrMUp6zswf2J7sbh2KBlba5A==", + "license": "MIT", + "dependencies": { + "derive-valtio": "0.1.0", + "proxy-compare": "2.6.0", + "use-sync-external-store": "1.2.0" + }, + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=16.8", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + } + } + }, + "node_modules/valtio/node_modules/use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/viem": { + "version": "2.37.6", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.37.6.tgz", + "integrity": "sha512-b+1IozQ8TciVQNdQUkOH5xtFR0z7ZxR8pyloENi/a+RA408lv4LoX12ofwoiT3ip0VRhO5ni1em//X0jn/eW0g==", + "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.1.0", + "isows": "1.0.7", + "ox": "0.9.3", + "ws": "8.18.3" + }, + "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/abitype": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.1.0.tgz", + "integrity": "sha512-6Vh4HcRxNMLA0puzPjM5GBgT4aAcFGKZzSgAXvuZ27shJP6NEpielTuqbBmZILR5/xd0PizkBGy5hReKz9jl5A==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/wevm" + }, + "peerDependencies": { + "typescript": ">=5.0.4", + "zod": "^3.22.0 || ^4.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, + "node_modules/viem/node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/wagmi": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/wagmi/-/wagmi-2.17.0.tgz", + "integrity": "sha512-NxdS/oHG3j4l3JzNIAb0zL14p3GXOS9YU4Q3WS+0eTChFIfdqBrurQMImPLNC9P5rXYym6cjC2feeqhHVMJjpg==", + "license": "MIT", + "dependencies": { + "@wagmi/connectors": "5.10.0", + "@wagmi/core": "2.21.0", + "use-sync-external-store": "1.4.0" + }, + "funding": { + "url": "https://github.com/sponsors/wevm" + }, + "peerDependencies": { + "@tanstack/react-query": ">=5.0.0", + "react": ">=18", + "typescript": ">=5.0.4", + "viem": "2.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/webextension-polyfill": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/webextension-polyfill/-/webextension-polyfill-0.10.0.tgz", + "integrity": "sha512-c5s35LgVa5tFaHhrZDnr3FpQpjj1BB+RXhLTYUxGqBVN460HkbM8TBtEqdXWbpTKfzwCcjAZVF7zXCYSKtcp9g==", + "license": "MPL-2.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-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "license": "ISC" + }, + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/x402": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/x402/-/x402-0.6.1.tgz", + "integrity": "sha512-9UmeCSsYzFGav5FdVP70VplKlR3V90P0DZ9fPSrlLVp0ifUVi1S9TztvegkmIHE9xTGZ1GWNi+bkne6N0Ea58w==", + "license": "Apache-2.0", + "dependencies": { + "@scure/base": "^1.2.6", + "@solana-program/compute-budget": "^0.8.0", + "@solana-program/token": "^0.5.1", + "@solana-program/token-2022": "^0.4.2", + "@solana/kit": "^2.1.1", + "@solana/transaction-confirmation": "^2.1.1", + "viem": "^2.21.26", + "wagmi": "^2.15.6", + "zod": "^3.24.2" + } + }, + "node_modules/x402-express": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/x402-express/-/x402-express-0.6.1.tgz", + "integrity": "sha512-J3jDs3+mFfjSQgppYP1Tnn8NXSJFMjj7jcoTIfl9m84evgi54puJrfZKgAhCs8+1FlrP5cEj/NmkYkG3u6zA9Q==", + "license": "Apache-2.0", + "dependencies": { + "@coinbase/cdp-sdk": "^1.22.0", + "@solana/kit": "^2.1.1", + "express": "^4.18.2", + "viem": "^2.21.26", + "x402": "^0.6.1", + "zod": "^3.24.2" + } + }, + "node_modules/xmlhttprequest-ssl": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", + "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "license": "ISC" + }, + "node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "license": "MIT", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/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" + } + }, + "node_modules/zustand": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.3.tgz", + "integrity": "sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=18.0.0", + "immer": ">=9.0.6", + "react": ">=18.0.0", + "use-sync-external-store": ">=1.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + }, + "use-sync-external-store": { + "optional": true + } + } + } + } +} diff --git a/examples/x402-server/package.json b/examples/x402-server/package.json index 0a731f1e..e14c44d4 100644 --- a/examples/x402-server/package.json +++ b/examples/x402-server/package.json @@ -9,19 +9,21 @@ "test-client": "tsx src/test-client.ts" }, "dependencies": { - "@atxp/client": "workspace:*", - "@atxp/common": "workspace:*", + "@atxp/client": "file:../../packages/atxp-client", + "@atxp/common": "file:../../packages/atxp-common", "@coinbase/x402": "^0.3.8", - "express": "^4.18.2", - "cors": "^2.8.5", "bignumber.js": "^9.1.2", - "dotenv": "^16.0.3" + "cors": "^2.8.5", + "dotenv": "^16.0.3", + "express": "^4.18.2", + "x402": "^0.6.1", + "x402-express": "^0.6.1" }, "devDependencies": { - "@types/express": "^4.17.17", "@types/cors": "^2.8.13", + "@types/express": "^4.17.17", "@types/node": "^20.0.0", "tsx": "^4.0.0", "typescript": "^5.0.0" } -} \ No newline at end of file +} diff --git a/examples/x402-server/src/server.ts b/examples/x402-server/src/server.ts index 8d97af0b..fd018431 100644 --- a/examples/x402-server/src/server.ts +++ b/examples/x402-server/src/server.ts @@ -1,52 +1,68 @@ -import express from 'express'; -import cors from 'cors'; -import { paymentMiddleware, createFacilitatorConfig } from '@coinbase/x402'; -import dotenv from 'dotenv'; +import express from "express"; +import { paymentMiddleware } from "x402-express"; +import { facilitator } from "@coinbase/x402"; +import dotenv from "dotenv"; +import path from "path"; +import { fileURLToPath } from 'url'; -dotenv.config(); +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +// Load .env from current directory first, then from repo root +dotenv.config(); // Load local .env if it exists +dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); // Also load from repo root const app = express(); -app.use(cors()); -app.use(express.json()); -// Configure facilitator -const facilitator = process.env.CDP_API_KEY_ID && process.env.CDP_API_KEY_SECRET - ? createFacilitatorConfig(process.env.CDP_API_KEY_ID, process.env.CDP_API_KEY_SECRET) // Production (mainnet) - : { url: 'https://x402.org/facilitator' }; // Public test facilitator (Base Sepolia) +// Your wallet address to receive payments +const recipientAddress = process.env.ATXP_DESTINATION! as `0x${string}`; + +// Determine network based on environment +const isMainnet = process.env.CDP_API_KEY_ID !== undefined; +const network = isMainnet ? "base" : "base-sepolia"; + +// Configure facilitator based on environment +const facilitatorConfig = process.env.CDP_API_KEY_ID && process.env.CDP_API_KEY_SECRET + ? facilitator // Use CDP facilitator for mainnet + : { url: "https://x402.org/facilitator" } ; // Use public test facilitator -// Single line to enable X402 payments on endpoints +// Configure payment middleware app.use(paymentMiddleware( - process.env.RECIPIENT_ADDRESS || '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb8', + recipientAddress, { - '/api/resource': { - price: '$0.01', - network: process.env.NETWORK || 'base-sepolia' // Default to testnet - } + "GET /api/resource": { + price: "$0.01", + network: network, + }, }, - facilitator + facilitatorConfig )); -// Protected endpoint - X402 middleware handles payment automatically -app.get('/api/resource', (req, res) => { +// Protected endpoint - costs $0.01 USDC +app.get("/api/resource", (req, res) => { res.json({ success: true, - data: 'This is protected content that costs $0.01 USDC', + data: "This is protected content that costs $0.01 USDC", timestamp: Date.now() }); }); const PORT = process.env.PORT || 3001; + app.listen(PORT, () => { - const network = process.env.NETWORK || 'base-sepolia'; - const isTestnet = network === 'base-sepolia'; + console.log(`X402 Server (Coinbase SDK) running on http://localhost:${PORT}`); + console.log(`Recipient address: ${recipientAddress}`); + console.log(`Network: ${network} (${isMainnet ? 'MAINNET - real money!' : 'testnet'})`); + console.log(`Facilitator: ${process.env.CDP_API_KEY_ID ? 'CDP (mainnet)' : 'Public test facilitator'}`); + + if (isMainnet) { + console.log("\n⚠️ WARNING: Running on MAINNET - real USDC payments!"); + } - console.log(`X402 Server running on http://localhost:${PORT}`); - console.log(`Network: ${network} (${isTestnet ? 'TESTNET - using test USDC' : 'MAINNET - real money!'})`); - console.log(`Facilitator: ${isTestnet ? 'https://x402.org/facilitator (public)' : 'Coinbase CDP (requires API keys)'}`); - console.log(`Protected endpoint: GET /api/resource ($0.01 USDC)`); + console.log("\nProtected endpoints:"); + console.log(` GET /api/resource - $0.01 USDC`); - if (isTestnet) { - console.log('\n✅ Using public test facilitator - no API keys needed!'); - console.log('Get test USDC from Circle faucet for Base Sepolia to test payments.'); + if (!process.env.ATXP_DESTINATION) { + console.error("\n❌ ERROR: ATXP_DESTINATION environment variable is required!"); + process.exit(1); } }); \ No newline at end of file diff --git a/examples/x402-server/src/test-client.ts b/examples/x402-server/src/test-client.ts index 29610735..89cb1eca 100644 --- a/examples/x402-server/src/test-client.ts +++ b/examples/x402-server/src/test-client.ts @@ -1,19 +1,25 @@ import { wrapWithX402, BaseAccount } from '@atxp/client'; import { ConsoleLogger } from '@atxp/common'; import dotenv from 'dotenv'; +import path from 'path'; +import { fileURLToPath } from 'url'; -dotenv.config(); +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +// Load .env from current directory first, then from repo root +dotenv.config(); // Load local .env if it exists +dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); // Also load from repo root async function testX402Client() { // Check for required environment variables - if (!process.env.BASE_RPC_URL || !process.env.BASE_PRIVATE_KEY) { - console.error('Missing BASE_RPC_URL and BASE_PRIVATE_KEY'); + if (!process.env.BASE_RPC || !process.env.BASE_PRIVATE_KEY) { + console.error('Missing BASE_RPC and/or BASE_PRIVATE_KEY'); process.exit(1); } // Create account const account = new BaseAccount( - process.env.BASE_RPC_URL, + process.env.BASE_RPC, process.env.BASE_PRIVATE_KEY ); From 2eba9a5f9b7601ba496b76c7b36dc4b258496d03 Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 12:40:19 -0700 Subject: [PATCH 19/61] Logging in test-client --- examples/x402-server/src/test-client.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/examples/x402-server/src/test-client.ts b/examples/x402-server/src/test-client.ts index 89cb1eca..a687f2db 100644 --- a/examples/x402-server/src/test-client.ts +++ b/examples/x402-server/src/test-client.ts @@ -24,13 +24,19 @@ async function testX402Client() { ); // Create a logger (optional - defaults to ConsoleLogger if not provided) - const logger = new ConsoleLogger(); + const logger = new ConsoleLogger({ prefix: '[X402 Client]' }); + + // Log account info + console.log('Using RPC:', process.env.BASE_RPC); + console.log('Account address:', account.accountId); // Wrap fetch with X402 support const x402Fetch = wrapWithX402(fetch as any, account, logger); // Make a single request to the protected endpoint const serverUrl = process.env.X402_SERVER_URL || 'http://localhost:3001'; + console.log('Making request to:', `${serverUrl}/api/resource`); + const response = await x402Fetch(`${serverUrl}/api/resource`); if (response.ok) { From dc386575a028d3c94e21146b037d8c7043cdf45a Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 12:49:41 -0700 Subject: [PATCH 20/61] Logging --- examples/x402-server/src/test-client.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/x402-server/src/test-client.ts b/examples/x402-server/src/test-client.ts index a687f2db..8bd3cf17 100644 --- a/examples/x402-server/src/test-client.ts +++ b/examples/x402-server/src/test-client.ts @@ -1,5 +1,5 @@ import { wrapWithX402, BaseAccount } from '@atxp/client'; -import { ConsoleLogger } from '@atxp/common'; +import { ConsoleLogger, LogLevel } from '@atxp/common'; import dotenv from 'dotenv'; import path from 'path'; import { fileURLToPath } from 'url'; @@ -23,8 +23,8 @@ async function testX402Client() { process.env.BASE_PRIVATE_KEY ); - // Create a logger (optional - defaults to ConsoleLogger if not provided) - const logger = new ConsoleLogger({ prefix: '[X402 Client]' }); + // Create a logger with DEBUG level to see all messages + const logger = new ConsoleLogger({ prefix: '[X402 Client]', level: LogLevel.DEBUG }); // Log account info console.log('Using RPC:', process.env.BASE_RPC); From 2f138a754a3ca1c49a668db3174a5f55bed354af Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 13:09:19 -0700 Subject: [PATCH 21/61] Properly handle X402 response formats --- packages/atxp-client/src/x402Wrapper.ts | 47 ++++++++++++++++--------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/packages/atxp-client/src/x402Wrapper.ts b/packages/atxp-client/src/x402Wrapper.ts index 99264d8f..e9be86db 100644 --- a/packages/atxp-client/src/x402Wrapper.ts +++ b/packages/atxp-client/src/x402Wrapper.ts @@ -9,30 +9,43 @@ export function wrapWithX402(fetchFn: FetchLike, account: Account, logger?: Logg // Check if this is an X402 payment challenge if (response.status === 402) { - const paymentHeader = response.headers.get('X-Payment-Required'); - - if (!paymentHeader) { - // Not an X402 response, return as-is - log.debug('Received 402 response without X-Payment-Required header'); - return response; - } - log.info('Received X402 payment challenge'); try { - // Parse the X402 payment requirements - const paymentChallenge = JSON.parse(paymentHeader); - const { network, currency, amount, recipient, memo } = paymentChallenge; + // Parse the X402 payment requirements from response body + const responseBody = await response.text(); + const paymentChallenge = JSON.parse(responseBody); + + // Check if this is a valid X402 response + if (!paymentChallenge.x402Version || !paymentChallenge.accepts || !Array.isArray(paymentChallenge.accepts)) { + log.debug('Received 402 response without valid X402 format'); + return response; + } + + // Find the accept option for base:USDC + const baseUsdcOption = paymentChallenge.accepts.find((option: any) => + option.network === 'base' && option.asset === '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' + ); + + if (!baseUsdcOption) { + log.error('No base:USDC accept option found in payment challenge'); + throw new Error('No base:USDC accept option found in payment challenge'); + } + + const { network, maxAmountRequired, payTo: recipient, asset } = baseUsdcOption; + + // Convert maxAmountRequired from wei to decimal (USDC has 6 decimals) + const amount = new BigNumber(maxAmountRequired).dividedBy(new BigNumber(10).pow(6)).toString(); + const currency = 'USDC'; // Based on the asset address in the response log.debug(`Payment required: ${amount} ${currency} on ${network} to ${recipient}`); - // Find the appropriate payment maker - const paymentMakerKey = `${network}:${currency}`; - const paymentMaker = account.paymentMakers[paymentMakerKey]; + // Find the appropriate payment maker using just the network name + const paymentMaker = account.paymentMakers[network]; if (!paymentMaker) { - log.error(`No payment maker found for ${paymentMakerKey}`); - throw new Error(`No payment maker found for ${paymentMakerKey}`); + log.info(`No payment maker found for ${network}`); + return response; } log.debug(`Creating EIP-3009 payment authorization`); @@ -42,7 +55,7 @@ export function wrapWithX402(fetchFn: FetchLike, account: Account, logger?: Logg new BigNumber(amount), currency, recipient, - memo || '' + '' ); // Wrap the EIP-3009 authorization in X402 protocol format From 0ce5970aa4af344f847c8e6b1054615483fbef3e Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 13:09:41 -0700 Subject: [PATCH 22/61] Fix test mocks --- .../atxp-client/src/atxpClient.events.test.ts | 52 +++++++++++++++++-- packages/atxp-client/src/atxpClient.test.ts | 39 ++++++++++++-- .../atxp-client/src/atxpFetcher.oauth.test.ts | 13 ++++- .../src/atxpFetcher.payment.test.ts | 13 ++++- packages/atxp-client/src/x402Wrapper.test.ts | 25 +++++++-- 5 files changed, 130 insertions(+), 12 deletions(-) diff --git a/packages/atxp-client/src/atxpClient.events.test.ts b/packages/atxp-client/src/atxpClient.events.test.ts index 7e5ac3fe..5b05864c 100644 --- a/packages/atxp-client/src/atxpClient.events.test.ts +++ b/packages/atxp-client/src/atxpClient.events.test.ts @@ -25,7 +25,18 @@ describe('atxpClient events', () => { const onAuthorize = vi.fn(); const paymentMaker = { makePayment: vi.fn(), - generateJWT: vi.fn().mockResolvedValue('testJWT') + generateJWT: vi.fn().mockResolvedValue('testJWT'), + createPaymentAuthorization: vi.fn().mockResolvedValue({ + from: '0x123', + to: '0x456', + value: '1000000', + validAfter: 0, + validBefore: Math.floor(Date.now() / 1000) + 3600, + nonce: '0x789', + v: 27, + r: '0xabc', + s: '0xdef' + }) }; const account = { accountId: 'bdj', @@ -64,7 +75,18 @@ describe('atxpClient events', () => { const onAuthorizeFailure = vi.fn(); const paymentMaker = { makePayment: vi.fn(), - generateJWT: vi.fn().mockResolvedValue('testJWT') + generateJWT: vi.fn().mockResolvedValue('testJWT'), + createPaymentAuthorization: vi.fn().mockResolvedValue({ + from: '0x123', + to: '0x456', + value: '1000000', + validAfter: 0, + validBefore: Math.floor(Date.now() / 1000) + 3600, + nonce: '0x789', + v: 27, + r: '0xabc', + s: '0xdef' + }) }; const account = { accountId: 'bdj', @@ -107,7 +129,18 @@ describe('atxpClient events', () => { const onPayment = vi.fn(); const paymentMaker = { makePayment: vi.fn().mockResolvedValue('test-payment-result-id'), - generateJWT: vi.fn().mockResolvedValue('testJWT') + generateJWT: vi.fn().mockResolvedValue('testJWT'), + createPaymentAuthorization: vi.fn().mockResolvedValue({ + from: '0x123', + to: '0x456', + value: '1000000', + validAfter: 0, + validBefore: Math.floor(Date.now() / 1000) + 3600, + nonce: '0x789', + v: 27, + r: '0xabc', + s: '0xdef' + }) }; const account = { accountId: 'bdj', @@ -151,7 +184,18 @@ describe('atxpClient events', () => { const onPaymentFailure = vi.fn(); const paymentMaker = { makePayment: vi.fn().mockImplementation(() => Promise.reject(new Error('Payment failed'))), - generateJWT: vi.fn().mockResolvedValue('testJWT') + generateJWT: vi.fn().mockResolvedValue('testJWT'), + createPaymentAuthorization: vi.fn().mockResolvedValue({ + from: '0x123', + to: '0x456', + value: '1000000', + validAfter: 0, + validBefore: Math.floor(Date.now() / 1000) + 3600, + nonce: '0x789', + v: 27, + r: '0xabc', + s: '0xdef' + }) }; const account = { accountId: 'bdj', diff --git a/packages/atxp-client/src/atxpClient.test.ts b/packages/atxp-client/src/atxpClient.test.ts index e33ff60a..7357ff81 100644 --- a/packages/atxp-client/src/atxpClient.test.ts +++ b/packages/atxp-client/src/atxpClient.test.ts @@ -24,7 +24,18 @@ describe('atxpClient', () => { const paymentMaker = { makePayment: vi.fn(), - generateJWT: vi.fn().mockResolvedValue('testJWT') + generateJWT: vi.fn().mockResolvedValue('testJWT'), + createPaymentAuthorization: vi.fn().mockResolvedValue({ + from: '0x123', + to: '0x456', + value: '1000000', + validAfter: 0, + validBefore: Math.floor(Date.now() / 1000) + 3600, + nonce: '0x789', + v: 27, + r: '0xabc', + s: '0xdef' + }) }; const account = { accountId: 'bdj', @@ -60,7 +71,18 @@ describe('atxpClient', () => { const paymentMaker = { makePayment: vi.fn().mockResolvedValue('test-payment-result-id'), - generateJWT: vi.fn().mockResolvedValue('testJWT') + generateJWT: vi.fn().mockResolvedValue('testJWT'), + createPaymentAuthorization: vi.fn().mockResolvedValue({ + from: '0x123', + to: '0x456', + value: '1000000', + validAfter: 0, + validBefore: Math.floor(Date.now() / 1000) + 3600, + nonce: '0x789', + v: 27, + r: '0xabc', + s: '0xdef' + }) }; const account = { accountId: 'bdj', @@ -109,7 +131,18 @@ describe('atxpClient', () => { const paymentMaker = { makePayment: vi.fn().mockResolvedValue('test-payment-result-id'), - generateJWT: vi.fn().mockResolvedValue('testJWT') + generateJWT: vi.fn().mockResolvedValue('testJWT'), + createPaymentAuthorization: vi.fn().mockResolvedValue({ + from: '0x123', + to: '0x456', + value: '1000000', + validAfter: 0, + validBefore: Math.floor(Date.now() / 1000) + 3600, + nonce: '0x789', + v: 27, + r: '0xabc', + s: '0xdef' + }) }; const account = { accountId: 'bdj', diff --git a/packages/atxp-client/src/atxpFetcher.oauth.test.ts b/packages/atxp-client/src/atxpFetcher.oauth.test.ts index f7bedfdd..892d510c 100644 --- a/packages/atxp-client/src/atxpFetcher.oauth.test.ts +++ b/packages/atxp-client/src/atxpFetcher.oauth.test.ts @@ -10,7 +10,18 @@ import { PaymentMaker } from './types.js'; function mockPaymentMakers(solanaPaymentMaker?: PaymentMaker) { solanaPaymentMaker = solanaPaymentMaker ?? { makePayment: vi.fn().mockResolvedValue('testPaymentId'), - generateJWT: vi.fn().mockResolvedValue('testJWT') + generateJWT: vi.fn().mockResolvedValue('testJWT'), + createPaymentAuthorization: vi.fn().mockResolvedValue({ + from: '0x123', + to: '0x456', + value: '1000000', + validAfter: 0, + validBefore: Math.floor(Date.now() / 1000) + 3600, + nonce: '0x789', + v: 27, + r: '0xabc', + s: '0xdef' + }) }; return {'solana': solanaPaymentMaker }; } diff --git a/packages/atxp-client/src/atxpFetcher.payment.test.ts b/packages/atxp-client/src/atxpFetcher.payment.test.ts index 6eaf0811..e29cd8f6 100644 --- a/packages/atxp-client/src/atxpFetcher.payment.test.ts +++ b/packages/atxp-client/src/atxpFetcher.payment.test.ts @@ -12,7 +12,18 @@ import BigNumber from 'bignumber.js'; function mockPaymentMakers(solanaPaymentMaker?: PaymentMaker) { solanaPaymentMaker = solanaPaymentMaker ?? { makePayment: vi.fn().mockResolvedValue('testPaymentId'), - generateJWT: vi.fn().mockResolvedValue('testJWT') + generateJWT: vi.fn().mockResolvedValue('testJWT'), + createPaymentAuthorization: vi.fn().mockResolvedValue({ + from: '0x123', + to: '0x456', + value: '1000000', + validAfter: 0, + validBefore: Math.floor(Date.now() / 1000) + 3600, + nonce: '0x789', + v: 27, + r: '0xabc', + s: '0xdef' + }) }; return {'solana': solanaPaymentMaker }; } diff --git a/packages/atxp-client/src/x402Wrapper.test.ts b/packages/atxp-client/src/x402Wrapper.test.ts index 49d47466..1253857b 100644 --- a/packages/atxp-client/src/x402Wrapper.test.ts +++ b/packages/atxp-client/src/x402Wrapper.test.ts @@ -7,6 +7,7 @@ describe('X402 Wrapper', () => { it('should produce valid X402 message structure matching protocol specification', async () => { // Mock account with test payment maker const mockAccount: Account = { + accountId: 'test-account', paymentMakers: { 'base:USDC': { async createPaymentAuthorization( @@ -38,6 +39,9 @@ describe('X402 Wrapper', () => { // First request - return 402 challenge return { status: 402, + ok: false, + json: async () => ({}), + text: async () => '', headers: { get: (name: string) => { if (name === 'X-Payment-Required') { @@ -87,7 +91,11 @@ describe('X402 Wrapper', () => { return { status: 200, ok: true, - json: async () => ({ success: true }) + json: async () => ({ success: true }), + text: async () => JSON.stringify({ success: true }), + headers: { + get: () => null + } }; }); @@ -99,10 +107,15 @@ describe('X402 Wrapper', () => { }); it('should handle non-402 responses without modification', async () => { - const mockAccount: Account = { paymentMakers: {} }; + const mockAccount: Account = { + accountId: 'test-account', + paymentMakers: {} + }; const mockFetch = vi.fn(async () => ({ status: 200, ok: true, + json: async () => ({}), + text: async () => '', headers: { get: () => null } @@ -116,9 +129,15 @@ describe('X402 Wrapper', () => { }); it('should handle 402 responses without X-Payment-Required header', async () => { - const mockAccount: Account = { paymentMakers: {} }; + const mockAccount: Account = { + accountId: 'test-account', + paymentMakers: {} + }; const mockFetch = vi.fn(async () => ({ status: 402, + ok: false, + json: async () => ({}), + text: async () => '', headers: { get: () => null } From 230aea10eaa18b5578ec81a12acd8cb35fc050ef Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 13:10:57 -0700 Subject: [PATCH 23/61] Use ATXPAccount --- examples/x402-server/src/test-client.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/examples/x402-server/src/test-client.ts b/examples/x402-server/src/test-client.ts index 8bd3cf17..79ee5143 100644 --- a/examples/x402-server/src/test-client.ts +++ b/examples/x402-server/src/test-client.ts @@ -1,4 +1,4 @@ -import { wrapWithX402, BaseAccount } from '@atxp/client'; +import { wrapWithX402, ATXPAccount } from '@atxp/client'; import { ConsoleLogger, LogLevel } from '@atxp/common'; import dotenv from 'dotenv'; import path from 'path'; @@ -18,9 +18,8 @@ async function testX402Client() { } // Create account - const account = new BaseAccount( - process.env.BASE_RPC, - process.env.BASE_PRIVATE_KEY + const account = new ATXPAccount( + process.env.ATXP_CONNECTION_STRING! ); // Create a logger with DEBUG level to see all messages From 84eed1e2a99d183872d9c067e5c4aa62a9356737 Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 13:11:22 -0700 Subject: [PATCH 24/61] Revert "Use ATXPAccount" This reverts commit 230aea10eaa18b5578ec81a12acd8cb35fc050ef. --- examples/x402-server/src/test-client.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/x402-server/src/test-client.ts b/examples/x402-server/src/test-client.ts index 79ee5143..8bd3cf17 100644 --- a/examples/x402-server/src/test-client.ts +++ b/examples/x402-server/src/test-client.ts @@ -1,4 +1,4 @@ -import { wrapWithX402, ATXPAccount } from '@atxp/client'; +import { wrapWithX402, BaseAccount } from '@atxp/client'; import { ConsoleLogger, LogLevel } from '@atxp/common'; import dotenv from 'dotenv'; import path from 'path'; @@ -18,8 +18,9 @@ async function testX402Client() { } // Create account - const account = new ATXPAccount( - process.env.ATXP_CONNECTION_STRING! + const account = new BaseAccount( + process.env.BASE_RPC, + process.env.BASE_PRIVATE_KEY ); // Create a logger with DEBUG level to see all messages From 18a6141b892c650c7b315b6b1889a3d36595892f Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 13:12:37 -0700 Subject: [PATCH 25/61] Fix error message --- packages/atxp-client/src/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/atxp-client/src/types.ts b/packages/atxp-client/src/types.ts index 984cff1c..94cf5fb5 100644 --- a/packages/atxp-client/src/types.ts +++ b/packages/atxp-client/src/types.ts @@ -62,7 +62,7 @@ export class InsufficientFundsError extends Error { export class PaymentNetworkError extends Error { constructor(message: string, public readonly originalError?: Error) { - super(`Payment failed due to network error: ${message}. Please check your network connection and try again.`); + super(`Payment failed due to network error: ${message}`); this.name = 'PaymentNetworkError'; } } From fd3e9fd07ed0584fcdca024e89837e9be84cd0cf Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 13:20:49 -0700 Subject: [PATCH 26/61] Temporary: base payemnt maker does X402 for integration testing --- packages/atxp-client/src/basePaymentMaker.ts | 91 +++++++++++++++++++- 1 file changed, 88 insertions(+), 3 deletions(-) diff --git a/packages/atxp-client/src/basePaymentMaker.ts b/packages/atxp-client/src/basePaymentMaker.ts index 9471b4f2..8e024e7d 100644 --- a/packages/atxp-client/src/basePaymentMaker.ts +++ b/packages/atxp-client/src/basePaymentMaker.ts @@ -180,8 +180,93 @@ export class BasePaymentMaker implements PaymentMaker { } } - async createPaymentAuthorization(_amount: BigNumber, _currency: Currency, _receiver: string, _memo: string): Promise { - // BasePaymentMaker doesn't have access to accounts service, so throw not-implemented - throw new PaymentNetworkErrorClass('EIP-3009 payment authorizations are not supported by BasePaymentMaker'); + async createPaymentAuthorization(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { + if (currency.toUpperCase() !== 'USDC') { + throw new PaymentNetworkErrorClass('Only USDC is supported for EIP-3009 authorizations'); + } + + this.logger.info(`Creating EIP-3009 authorization for ${amount} ${currency} to ${receiver}`); + + try { + // Check balance before creating authorization + const balanceRaw = await this.signingClient.readContract({ + address: USDC_CONTRACT_ADDRESS_BASE as Address, + abi: ERC20_ABI, + functionName: 'balanceOf', + args: [this.signingClient.account!.address], + }) as bigint; + + const balance = new BigNumber(balanceRaw.toString()).dividedBy(10 ** USDC_DECIMALS); + + if (balance.lt(amount)) { + this.logger.warn(`Insufficient ${currency} balance for authorization. Required: ${amount}, Available: ${balance}`); + throw new InsufficientFundsErrorClass(currency, amount, balance, 'base'); + } + + // Create EIP-3009 authorization parameters + const validAfter = Math.floor(Date.now() / 1000); // Valid immediately + const validBefore = Math.floor(Date.now() / 1000) + 3600; // Valid for 1 hour + const nonce = '0x' + Array.from(crypto.getRandomValues(new Uint8Array(32)), b => b.toString(16).padStart(2, '0')).join(''); + + // Convert amount to USDC units (6 decimals) + const value = amount.multipliedBy(10 ** USDC_DECIMALS).toFixed(0); + + // Create the EIP-712 typed data for signing + const typedData = { + domain: { + name: 'USD Coin', + version: '2', + chainId: base.id, // Base mainnet chain ID (8453) + verifyingContract: USDC_CONTRACT_ADDRESS_BASE as `0x${string}`, + }, + types: { + TransferWithAuthorization: [ + { name: 'from', type: 'address' }, + { name: 'to', type: 'address' }, + { name: 'value', type: 'uint256' }, + { name: 'validAfter', type: 'uint256' }, + { name: 'validBefore', type: 'uint256' }, + { name: 'nonce', type: 'bytes32' }, + ], + }, + primaryType: 'TransferWithAuthorization' as const, + message: { + from: this.signingClient.account!.address, + to: receiver as Address, + value, + validAfter: validAfter.toString(), + validBefore: validBefore.toString(), + nonce, + }, + }; + + // Sign the typed data + const signature = await this.signingClient.signTypedData({ + account: this.signingClient.account!, + ...typedData, + }); + + this.logger.info(`Created EIP-3009 authorization with signature: ${signature}`); + + // Return EIP-3009 authorization in the expected format + return { + signature, + authorization: { + from: this.signingClient.account!.address, + to: receiver, + value, + validAfter: validAfter.toString(), + validBefore: validBefore.toString(), + nonce, + } + }; + } catch (error) { + if (error instanceof InsufficientFundsErrorClass || error instanceof PaymentNetworkErrorClass) { + throw error; + } + + // Wrap other errors in PaymentNetworkError + throw new PaymentNetworkErrorClass(`Failed to create EIP-3009 authorization: ${(error as Error).message}`, error as Error); + } } } \ No newline at end of file From 0bce04bfdf62e81126047da6e69b437a3930a68e Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 13:33:09 -0700 Subject: [PATCH 27/61] Base64-encode header --- packages/atxp-client/src/x402Wrapper.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/atxp-client/src/x402Wrapper.ts b/packages/atxp-client/src/x402Wrapper.ts index e9be86db..258c189b 100644 --- a/packages/atxp-client/src/x402Wrapper.ts +++ b/packages/atxp-client/src/x402Wrapper.ts @@ -66,12 +66,19 @@ export function wrapWithX402(fetchFn: FetchLike, account: Account, logger?: Logg payload: eip3009Authorization }; + // Base64 encode the X402 message for the X-Payment header + const x402MessageJson = JSON.stringify(x402Message); + log.debug(`X402 message being sent: ${x402MessageJson}`); + const x402MessageBase64 = typeof Buffer !== 'undefined' + ? Buffer.from(x402MessageJson).toString('base64') + : btoa(x402MessageJson); + // Send the X402 message in the X-Payment header const retryInit = { ...init, headers: { ...(init?.headers || {}), - 'X-Payment': JSON.stringify(x402Message) + 'X-Payment': x402MessageBase64 } }; From f627b125440fc8828c0ee0339a38417aeb293c9f Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 15:22:39 -0700 Subject: [PATCH 28/61] WIP --- examples/x402-server/package-lock.json | 14 +- examples/x402-server/package.json | 3 +- examples/x402-server/src/decode-headers.ts | 47 + examples/x402-server/src/test-client.ts | 19 +- examples/x402-server/src/test-compare.ts | 83 + .../x402-server/src/test-debug-wrapper.ts | 72 + examples/x402-server/src/test-hybrid.ts | 65 + examples/x402-server/src/test-new-wrapper.ts | 60 + examples/x402-server/src/test-x402-fetch.ts | 64 + .../src/test-x402fetch-with-base.ts | 79 + package-lock.json | 8424 ++++++++++++++--- packages/atxp-client/package.json | 3 +- packages/atxp-client/src/basePaymentMaker.ts | 13 +- packages/atxp-client/src/index.ts | 13 + packages/atxp-client/src/remoteSigner.ts | 113 + packages/atxp-client/src/x402Wrapper.ts | 4 +- .../atxp-client/src/x402WrapperUsingX402.ts | 100 + packages/atxp-client/src/x402WrapperV2.ts | 125 + 18 files changed, 7843 insertions(+), 1458 deletions(-) create mode 100644 examples/x402-server/src/decode-headers.ts create mode 100644 examples/x402-server/src/test-compare.ts create mode 100644 examples/x402-server/src/test-debug-wrapper.ts create mode 100644 examples/x402-server/src/test-hybrid.ts create mode 100644 examples/x402-server/src/test-new-wrapper.ts create mode 100644 examples/x402-server/src/test-x402-fetch.ts create mode 100644 examples/x402-server/src/test-x402fetch-with-base.ts create mode 100644 packages/atxp-client/src/remoteSigner.ts create mode 100644 packages/atxp-client/src/x402WrapperUsingX402.ts create mode 100644 packages/atxp-client/src/x402WrapperV2.ts diff --git a/examples/x402-server/package-lock.json b/examples/x402-server/package-lock.json index b4548fac..b90cde27 100644 --- a/examples/x402-server/package-lock.json +++ b/examples/x402-server/package-lock.json @@ -16,7 +16,8 @@ "dotenv": "^16.0.3", "express": "^4.18.2", "x402": "^0.6.1", - "x402-express": "^0.6.1" + "x402-express": "^0.6.1", + "x402-fetch": "^0.6.0" }, "devDependencies": { "@types/cors": "^2.8.13", @@ -9342,6 +9343,17 @@ "zod": "^3.24.2" } }, + "node_modules/x402-fetch": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/x402-fetch/-/x402-fetch-0.6.0.tgz", + "integrity": "sha512-c7ZQQOjgBWyX9xbmRCliUguVeG0RCofTlcnPKBrAgNYxEo8p/yuQr2PRvyN9tdQdXVTlGgIsII7GO1wLHJpLhA==", + "license": "Apache-2.0", + "dependencies": { + "viem": "^2.21.26", + "x402": "^0.6.0", + "zod": "^3.24.2" + } + }, "node_modules/xmlhttprequest-ssl": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", diff --git a/examples/x402-server/package.json b/examples/x402-server/package.json index e14c44d4..ef536f9d 100644 --- a/examples/x402-server/package.json +++ b/examples/x402-server/package.json @@ -17,7 +17,8 @@ "dotenv": "^16.0.3", "express": "^4.18.2", "x402": "^0.6.1", - "x402-express": "^0.6.1" + "x402-express": "^0.6.1", + "x402-fetch": "^0.6.0" }, "devDependencies": { "@types/cors": "^2.8.13", diff --git a/examples/x402-server/src/decode-headers.ts b/examples/x402-server/src/decode-headers.ts new file mode 100644 index 00000000..0b58c841 --- /dev/null +++ b/examples/x402-server/src/decode-headers.ts @@ -0,0 +1,47 @@ +// Decode and compare the X-Payment headers from both implementations + +const x402FetchHeader = 'eyJ4NDAyVmVyc2lvbiI6MSwic2NoZW1lIjoiZXhhY3QiLCJuZXR3b3JrIjoiYmFzZSIsInBheWxvYWQiOnsic2lnbmF0dXJlIjoiMHgyNzU5MWY4OTAzODcyY2QyZjEwNzEwN2I0NzM1MDVhYzhjMGQ1ZDI1NmYxY2MxN2I5MWQ3MWQ4NDU1MWEzMTVmNjVjZDZjNGY3YWJhOTJkM2NjYmQ0MDU4N2FiYzQ3OGM5OGIyYzI5MWQ1NTllNzBhOTFkYTEyMGE4OWNhNDhkMjFjIiwiYXV0aG9yaXphdGlvbiI6eyJmcm9tIjoiMHg3RjlEMWE4Nzk3NTAxNjhiOGY0QTU5NzM0QjEyNjJEMTc3OGZEQjVBIiwidG8iOiIweDMyMTQyMThDZEI2QTBFNTk3MDY3N0NkQ2E5ZUI2NTM2NWVmNTg3RkQiLCJ2YWx1ZSI6IjEwMDAwIiwidmFsaWRBZnRlciI6IjE3NTgyMjcxODciLCJ2YWxpZEJlZm9yZSI6IjE3NTgyMjc4NDciLCJub25jZSI6IjB4ZWIzOTgzYTQ3MWEwNGU0Njg2MGIyNzMxNzkzYjNkZThhMDRiN2I2ODQ3NjJkZGRiYjkwMzQ1M2U4MzVjNDAyOCJ9fX0='; + +const customWrapperHeader = 'eyJ4NDAyVmVyc2lvbiI6MSwic2NoZW1lIjoiZXhhY3QiLCJuZXR3b3JrIjoiYmFzZSIsInBheWxvYWQiOnsic2lnbmF0dXJlIjoiMHhlZWY1MWQ2YmJhZjJmMjU2MjBlNWJhZDgyOWZiMTBkMmM4ODFlNjdkNzg5NGQ2MmVkNWIyNDFlMjcxM2ZjZTNjNTJmMTM0Zjg5YWIwNzExNDNkN2JjMzliMmUxM2E1ZjgzN2U0NGEwZjI4YWQ1ZjMwNjkzNDcxNWExMzExNmI5YzFjIiwiYXV0aG9yaXphdGlvbiI6eyJmcm9tIjoiMHg3RjlEMWE4Nzk3NTAxNjhiOGY0QTU5NzM0QjEyNjJEMTc3OGZEQjVBIiwidG8iOiIweDMyMTQyMThDZEI2QTBFNTk3MDY3N0NkQ2E5ZUI2NTM2NWVmNTg3RkQiLCJ2YWx1ZSI6IjEwMDAwIiwidmFsaWRBZnRlciI6IjE3NTgyMjc3OTciLCJ2YWxpZEJlZm9yZSI6IjE3NTgyMzEzOTciLCJub25jZSI6IjB4YTk2YzRjNTcxMWYyNTMyOWE2MjY2Y2RmZjFlZTUyNTZiNzBlZTBmNDNkNWFlZDM5MTI0ZTM1NmQxMTVlNzE4MyJ9fX0='; + +console.log('=== X402-FETCH HEADER ==='); +const x402FetchDecoded = Buffer.from(x402FetchHeader, 'base64').toString('utf-8'); +const x402FetchJson = JSON.parse(x402FetchDecoded); +console.log(JSON.stringify(x402FetchJson, null, 2)); + +console.log('\n=== CUSTOM WRAPPER HEADER ==='); +const customWrapperDecoded = Buffer.from(customWrapperHeader, 'base64').toString('utf-8'); +const customWrapperJson = JSON.parse(customWrapperDecoded); +console.log(JSON.stringify(customWrapperJson, null, 2)); + +console.log('\n=== DIFFERENCES ==='); + +// Compare top-level fields +for (const key in x402FetchJson) { + if (key !== 'payload' && x402FetchJson[key] !== customWrapperJson[key]) { + console.log(`${key}: x402-fetch="${x402FetchJson[key]}" vs custom="${customWrapperJson[key]}"`); + } +} + +// Compare payload.authorization fields (excluding dynamic fields like nonce, validAfter, validBefore, signature) +const x402Auth = x402FetchJson.payload.authorization; +const customAuth = customWrapperJson.payload.authorization; + +console.log('\nStatic fields comparison:'); +console.log(`from: ${x402Auth.from === customAuth.from ? '✅ SAME' : '❌ DIFFERENT'} (${x402Auth.from})`); +console.log(`to: ${x402Auth.to === customAuth.to ? '✅ SAME' : '❌ DIFFERENT'} (${x402Auth.to})`); +console.log(`value: ${x402Auth.value === customAuth.value ? '✅ SAME' : '❌ DIFFERENT'} (${x402Auth.value})`); + +console.log('\nDynamic fields (expected to be different):'); +console.log(`signature: ${x402FetchJson.payload.signature.substring(0, 20)}... vs ${customWrapperJson.payload.signature.substring(0, 20)}...`); +console.log(`nonce: ${x402Auth.nonce.substring(0, 20)}... vs ${customAuth.nonce.substring(0, 20)}...`); +console.log(`validAfter: ${x402Auth.validAfter} vs ${customAuth.validAfter}`); +console.log(`validBefore: ${x402Auth.validBefore} vs ${customAuth.validBefore}`); + +// Check for any extra fields +console.log('\nField presence check:'); +const x402FetchFields = Object.keys(x402FetchJson.payload.authorization).sort(); +const customWrapperFields = Object.keys(customWrapperJson.payload.authorization).sort(); +console.log('x402-fetch fields:', x402FetchFields.join(', ')); +console.log('custom wrapper fields:', customWrapperFields.join(', ')); +console.log('Fields match:', JSON.stringify(x402FetchFields) === JSON.stringify(customWrapperFields) ? '✅ YES' : '❌ NO'); \ No newline at end of file diff --git a/examples/x402-server/src/test-client.ts b/examples/x402-server/src/test-client.ts index 8bd3cf17..93215dd1 100644 --- a/examples/x402-server/src/test-client.ts +++ b/examples/x402-server/src/test-client.ts @@ -17,7 +17,7 @@ async function testX402Client() { process.exit(1); } - // Create account + // Create account to verify we have the right credentials const account = new BaseAccount( process.env.BASE_RPC, process.env.BASE_PRIVATE_KEY @@ -29,9 +29,14 @@ async function testX402Client() { // Log account info console.log('Using RPC:', process.env.BASE_RPC); console.log('Account address:', account.accountId); + console.log('Using wrapWithX402 (our custom implementation)'); - // Wrap fetch with X402 support - const x402Fetch = wrapWithX402(fetch as any, account, logger); + // Wrap fetch with X402 support using our custom implementation + const x402Fetch = wrapWithX402( + fetch as any, + account, + logger + ); // Make a single request to the protected endpoint const serverUrl = process.env.X402_SERVER_URL || 'http://localhost:3001'; @@ -42,6 +47,14 @@ async function testX402Client() { if (response.ok) { const data = await response.json(); console.log('Success:', data); + + // Try to decode payment response if available + const paymentResponseHeader = response.headers.get('x-payment-response'); + if (paymentResponseHeader) { + const paymentResponseJson = Buffer.from(paymentResponseHeader, 'base64').toString('utf-8'); + const paymentResponse = JSON.parse(paymentResponseJson); + console.log('Payment response:', paymentResponse); + } } else { console.error('Failed:', response.status, response.statusText); } diff --git a/examples/x402-server/src/test-compare.ts b/examples/x402-server/src/test-compare.ts new file mode 100644 index 00000000..113ab522 --- /dev/null +++ b/examples/x402-server/src/test-compare.ts @@ -0,0 +1,83 @@ +import { wrapFetchWithPayment, createSigner, type Hex } from 'x402-fetch'; +import { wrapWithX402, BaseAccount } from '@atxp/client'; +import { ConsoleLogger, LogLevel } from '@atxp/common'; +import dotenv from 'dotenv'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +// Load .env +dotenv.config(); +dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); + +async function compareImplementations() { + if (!process.env.BASE_RPC || !process.env.BASE_PRIVATE_KEY) { + console.error('Missing BASE_RPC and/or BASE_PRIVATE_KEY'); + process.exit(1); + } + + const serverUrl = process.env.X402_SERVER_URL || 'http://localhost:3001'; + const endpointPath = '/api/resource'; + const url = `${serverUrl}${endpointPath}`; + + console.log('=== Testing Official x402-fetch Library ==='); + try { + const privateKey = process.env.BASE_PRIVATE_KEY as Hex; + const signer = await createSigner('base', privateKey); + + // Intercept fetch to log headers + const originalFetch = fetch; + const loggingFetch = async (input: any, init?: any) => { + console.log('x402-fetch request headers:', init?.headers); + return originalFetch(input, init); + }; + + const fetchWithPayment = wrapFetchWithPayment(loggingFetch as any, signer, { + maxPaymentValue: 1000000000000000000n + }); + + const response = await fetchWithPayment(url, { method: 'GET' }); + + if (response.ok) { + const data = await response.json(); + console.log('✅ x402-fetch Success:', data); + } else { + console.log('❌ x402-fetch Failed:', response.status); + } + } catch (error) { + console.error('x402-fetch Error:', error); + } + + console.log('\n=== Testing Custom wrapWithX402 Implementation ==='); + try { + const account = new BaseAccount( + process.env.BASE_RPC, + process.env.BASE_PRIVATE_KEY + ); + + const logger = new ConsoleLogger({ prefix: '[Custom]', level: LogLevel.DEBUG }); + + // Intercept fetch to log headers + const originalFetch = fetch; + const loggingFetch = async (input: any, init?: any) => { + console.log('Custom wrapper request headers:', init?.headers); + return originalFetch(input, init); + }; + + const x402Fetch = wrapWithX402(loggingFetch as any, account, logger); + + const response = await x402Fetch(url); + + if (response.ok) { + const data = await response.json(); + console.log('✅ Custom wrapper Success:', data); + } else { + console.log('❌ Custom wrapper Failed:', response.status); + } + } catch (error) { + console.error('Custom wrapper Error:', error); + } +} + +compareImplementations().catch(console.error); \ No newline at end of file diff --git a/examples/x402-server/src/test-debug-wrapper.ts b/examples/x402-server/src/test-debug-wrapper.ts new file mode 100644 index 00000000..8a31360b --- /dev/null +++ b/examples/x402-server/src/test-debug-wrapper.ts @@ -0,0 +1,72 @@ +import { BaseAccount } from '@atxp/client'; +import { ConsoleLogger, LogLevel } from '@atxp/common'; +import { BigNumber } from 'bignumber.js'; +import dotenv from 'dotenv'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +// Load .env +dotenv.config(); +dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); + +async function debugOurImplementation() { + console.log('=== Debugging Our signTypedData Implementation ===\n'); + + if (!process.env.BASE_RPC || !process.env.BASE_PRIVATE_KEY) { + console.error('Missing BASE_RPC and/or BASE_PRIVATE_KEY'); + process.exit(1); + } + + const account = new BaseAccount( + process.env.BASE_RPC, + process.env.BASE_PRIVATE_KEY + ); + + const logger = new ConsoleLogger({ prefix: '[Debug]', level: LogLevel.DEBUG }); + + // Create the exact same authorization parameters that would be created + const recipient = '0x3214218CdB6A0E5970677CdCa9EB65365eF587fD'; + const amount = new BigNumber('0.01'); + const currency = 'USDC'; + + console.log('Creating EIP-3009 authorization with:'); + console.log(' Amount:', amount.toString(), currency); + console.log(' Recipient:', recipient); + console.log(' From:', account.accountId); + + // Get the payment maker to see exactly what it's doing + const paymentMaker = account.paymentMakers['base']; + + try { + // Create the authorization and log the exact parameters + console.log('\nCalling createPaymentAuthorization...'); + const authorization = await paymentMaker.createPaymentAuthorization( + amount, + currency, + recipient, + '' + ); + + console.log('\n=== Authorization Result ==='); + console.log(JSON.stringify(authorization, null, 2)); + + // Now let's also look at what parameters were used for signing + // We'll need to check our BasePaymentMaker implementation + console.log('\nKey parameters from our implementation:'); + console.log('- validAfter: now'); + console.log('- validBefore: now + 660 seconds (11 minutes)'); + console.log('- nonce: random 32 bytes'); + console.log('- value: amount * 10^6 (USDC decimals)'); + console.log('- chainId: 8453 (Base mainnet)'); + console.log('- verifyingContract: 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 (USDC on Base)'); + console.log('- domain.name: "USD Coin"'); + console.log('- domain.version: "2"'); + + } catch (error) { + console.error('Error creating authorization:', error); + } +} + +debugOurImplementation().catch(console.error); \ No newline at end of file diff --git a/examples/x402-server/src/test-hybrid.ts b/examples/x402-server/src/test-hybrid.ts new file mode 100644 index 00000000..d358fdb7 --- /dev/null +++ b/examples/x402-server/src/test-hybrid.ts @@ -0,0 +1,65 @@ +import { wrapFetchWithPayment } from 'x402-fetch'; +import { createRemoteSigner } from '@atxp/client'; +import dotenv from 'dotenv'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +// Load .env from current directory first, then from repo root +dotenv.config(); // Load local .env if it exists +dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); // Also load from repo root + +async function testHybridApproach() { + console.log('=== Testing Hybrid Approach: x402-fetch + Remote Signer ==='); + + // For now, we'll use the local signing since we don't have accounts-x402 running + // But this shows how we'd use the remote signer with x402-fetch + + const accountAddress = '0x7F9D1a879750168b8f4A59734B1262D1778fDB5A'; + const accountsApiUrl = 'https://accounts.atxp.ai'; // Would be the real accounts API + + console.log('Creating remote signer for address:', accountAddress); + console.log('Accounts API URL:', accountsApiUrl); + + // Create a remote signer that delegates to accounts-x402 + const remoteSigner = createRemoteSigner( + accountAddress as `0x${string}`, + accountsApiUrl + ); + + console.log('Remote signer created'); + + // Use x402-fetch's wrapFetchWithPayment with our remote signer + const fetchWithPayment = wrapFetchWithPayment(fetch as any, remoteSigner as any, { + maxPaymentValue: 1000000000000000000n // Maximum payment allowed + }); + + const serverUrl = process.env.X402_SERVER_URL || 'http://localhost:3001'; + const url = `${serverUrl}/api/resource`; + + console.log('Making request to:', url); + console.log('Note: This will fail since we don\'t have accounts-x402 running,'); + console.log('but it demonstrates how to combine x402-fetch with remote signing.'); + + try { + const response = await fetchWithPayment(url, { + method: 'GET' + }); + + if (response.ok) { + const data = await response.json(); + console.log('✅ Success! Response:', data); + } else { + console.log('❌ Request failed:', response.status, response.statusText); + const errorText = await response.text(); + console.log('Error details:', errorText); + } + } catch (error: any) { + console.log('❌ Error:', error.message || error); + console.log('\nThis is expected since we don\'t have the accounts-x402 API running.'); + console.log('In production, the remote signer would call the accounts API to sign.'); + } +} + +testHybridApproach().catch(console.error); \ No newline at end of file diff --git a/examples/x402-server/src/test-new-wrapper.ts b/examples/x402-server/src/test-new-wrapper.ts new file mode 100644 index 00000000..830fc9b0 --- /dev/null +++ b/examples/x402-server/src/test-new-wrapper.ts @@ -0,0 +1,60 @@ +import { wrapWithX402UsingLibrary } from '@atxp/client'; +import { ConsoleLogger, LogLevel } from '@atxp/common'; +import dotenv from 'dotenv'; +import path from 'path'; +import { fileURLToPath } from 'url'; +import type { Hex } from 'viem'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +// Load .env +dotenv.config(); +dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); + +async function testNewWrapper() { + console.log('=== Testing New Wrapper Using x402 Library Functions ==='); + + if (!process.env.BASE_PRIVATE_KEY) { + console.error('Missing BASE_PRIVATE_KEY'); + process.exit(1); + } + + const privateKey = process.env.BASE_PRIVATE_KEY as Hex; + const logger = new ConsoleLogger({ prefix: '[NewWrapper]', level: LogLevel.DEBUG }); + + // Use our new wrapper that uses x402's createPaymentHeader directly + const x402Fetch = wrapWithX402UsingLibrary(fetch as any, privateKey, logger); + + const serverUrl = process.env.X402_SERVER_URL || 'http://localhost:3001'; + const url = `${serverUrl}/api/resource`; + + console.log('Making request to:', url); + console.log('This wrapper uses x402\'s createPaymentHeader directly (same as x402-fetch)\n'); + + try { + const response = await x402Fetch(url); + + if (response.ok) { + const data = await response.json(); + console.log('✅ Success! Response:', data); + + // Try to decode payment response if available + const paymentResponseHeader = response.headers.get('x-payment-response'); + if (paymentResponseHeader) { + const paymentResponseJson = Buffer.from(paymentResponseHeader, 'base64').toString('utf-8'); + const paymentResponse = JSON.parse(paymentResponseJson); + console.log('Payment response:', paymentResponse); + } + + console.log('\n🎉 The new wrapper works! This proves we can use x402\'s functions directly.'); + } else { + console.log('❌ Request failed:', response.status, response.statusText); + const errorText = await response.text(); + console.log('Error details:', errorText); + } + } catch (error: any) { + console.log('❌ Error:', error.message || error); + } +} + +testNewWrapper().catch(console.error); \ No newline at end of file diff --git a/examples/x402-server/src/test-x402-fetch.ts b/examples/x402-server/src/test-x402-fetch.ts new file mode 100644 index 00000000..84909467 --- /dev/null +++ b/examples/x402-server/src/test-x402-fetch.ts @@ -0,0 +1,64 @@ +import { wrapFetchWithPayment, createSigner, decodeXPaymentResponse, type Hex } from 'x402-fetch'; +import dotenv from 'dotenv'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +// Load .env from current directory first, then from repo root +dotenv.config(); // Load local .env if it exists +dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); // Also load from repo root + +async function testX402Fetch() { + // Check for required environment variables + if (!process.env.BASE_PRIVATE_KEY) { + console.error('Missing BASE_PRIVATE_KEY'); + process.exit(1); + } + + const privateKey = process.env.BASE_PRIVATE_KEY as Hex; + const serverUrl = process.env.X402_SERVER_URL || 'http://localhost:3001'; + const endpointPath = '/api/resource'; + const url = `${serverUrl}${endpointPath}`; + + console.log('Using x402-fetch library'); + console.log('Server URL:', url); + + try { + // Create a signer for Base mainnet + const signer = await createSigner('base', privateKey); + console.log('Created signer with private key'); + + // Wrap fetch with payment functionality + const fetchWithPayment = wrapFetchWithPayment(fetch as any, signer, { + maxPaymentValue: 1000000000000000000n // Maximum payment allowed (1 USDC in wei with 6 decimals = 1000000) + }); + + console.log('Making request with x402-fetch...'); + + // Make a request that will trigger payment + const response = await fetchWithPayment(url, { + method: 'GET' + }); + + if (response.ok) { + const data = await response.json(); + console.log('Success! Response:', data); + + // Try to decode payment response if available + const paymentResponseHeader = response.headers.get('x-payment-response'); + if (paymentResponseHeader) { + const paymentResponse = decodeXPaymentResponse(paymentResponseHeader); + console.log('Payment response:', paymentResponse); + } + } else { + console.error('Request failed:', response.status, response.statusText); + const errorText = await response.text(); + console.error('Error details:', errorText); + } + } catch (error) { + console.error('Error:', error); + } +} + +testX402Fetch().catch(console.error); \ No newline at end of file diff --git a/examples/x402-server/src/test-x402fetch-with-base.ts b/examples/x402-server/src/test-x402fetch-with-base.ts new file mode 100644 index 00000000..dd7c1f30 --- /dev/null +++ b/examples/x402-server/src/test-x402fetch-with-base.ts @@ -0,0 +1,79 @@ +import { wrapFetchWithPayment, createSigner } from 'x402-fetch'; +import { BaseAccount } from '@atxp/client'; +import { ConsoleLogger, LogLevel } from '@atxp/common'; +import dotenv from 'dotenv'; +import path from 'path'; +import { fileURLToPath } from 'url'; +import type { Hex } from 'viem'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +// Load .env +dotenv.config(); +dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); + +async function testX402FetchWithBaseAccount() { + console.log('=== Using x402-fetch with BaseAccount\'s Private Key ==='); + + if (!process.env.BASE_RPC || !process.env.BASE_PRIVATE_KEY) { + console.error('Missing BASE_RPC and/or BASE_PRIVATE_KEY'); + process.exit(1); + } + + // Create BaseAccount to verify we have the right credentials + const account = new BaseAccount( + process.env.BASE_RPC, + process.env.BASE_PRIVATE_KEY + ); + + console.log('BaseAccount created with address:', account.accountId); + + // Now use x402-fetch's createSigner with the same private key + const signer = await createSigner('base', process.env.BASE_PRIVATE_KEY as Hex); + console.log('x402-fetch signer created'); + + // Create logger + const logger = new ConsoleLogger({ prefix: '[X402-Fetch]', level: LogLevel.DEBUG }); + + // Wrap fetch with x402-fetch's payment handling + const fetchWithPayment = wrapFetchWithPayment(fetch as any, signer, { + maxPaymentValue: 1000000000000000000n // Maximum payment allowed + }); + + const serverUrl = process.env.X402_SERVER_URL || 'http://localhost:3001'; + const url = `${serverUrl}/api/resource`; + + console.log('Making request to:', url); + console.log('Using x402-fetch library with BaseAccount\'s credentials...\n'); + + try { + const response = await fetchWithPayment(url, { + method: 'GET' + }); + + if (response.ok) { + const data = await response.json(); + console.log('✅ Success! Response:', data); + + // Try to decode payment response if available + const paymentResponseHeader = response.headers.get('x-payment-response'); + if (paymentResponseHeader) { + // Decode base64 + const paymentResponseJson = Buffer.from(paymentResponseHeader, 'base64').toString('utf-8'); + const paymentResponse = JSON.parse(paymentResponseJson); + console.log('Payment response:', paymentResponse); + } + + console.log('\n✨ This proves x402-fetch works correctly with our Base credentials!'); + console.log('The issue with our custom wrapper must be in how we\'re creating/signing the authorization.'); + } else { + console.log('❌ Request failed:', response.status, response.statusText); + const errorText = await response.text(); + console.log('Error details:', errorText); + } + } catch (error: any) { + console.log('❌ Error:', error.message || error); + } +} + +testX402FetchWithBaseAccount().catch(console.error); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 9fb3196b..c61a23f3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1643,6 +1643,75 @@ "integrity": "sha512-mqTyfBPYUrUfHwnmLOnBTBrtEiuO45MIVxvbJ1blivIZC+0YMFskQnrcPn1txQM2S4LKnwmFv1XMgjt0qMma1Q==", "license": "MIT OR Apache-2.0" }, + "node_modules/@coinbase/wallet-sdk": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/@coinbase/wallet-sdk/-/wallet-sdk-4.3.6.tgz", + "integrity": "sha512-4q8BNG1ViL4mSAAvPAtpwlOs1gpC+67eQtgIwNvT3xyeyFFd+guwkc8bcX5rTmQhXpqnhzC4f0obACbP9CqMSA==", + "license": "Apache-2.0", + "dependencies": { + "@noble/hashes": "1.4.0", + "clsx": "1.2.1", + "eventemitter3": "5.0.1", + "idb-keyval": "6.2.1", + "ox": "0.6.9", + "preact": "10.24.2", + "viem": "^2.27.2", + "zustand": "5.0.3" + } + }, + "node_modules/@coinbase/wallet-sdk/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/@coinbase/wallet-sdk/node_modules/ox": { + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.6.9.tgz", + "integrity": "sha512-wi5ShvzE4eOcTwQVsIPdFr+8ycyX+5le/96iAJutaZAvCes1J0+RvpEPg5QDPDiaR0XQQAvZVl7AwqQcINuUug==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@adraffy/ens-normalize": "^1.10.1", + "@noble/curves": "^1.6.0", + "@noble/hashes": "^1.5.0", + "@scure/bip32": "^1.5.0", + "@scure/bip39": "^1.4.0", + "abitype": "^1.0.6", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@coinbase/wallet-sdk/node_modules/ox/node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@csstools/color-helpers": { "version": "5.0.2", "dev": true, @@ -1748,6 +1817,20 @@ "node": ">=18" } }, + "node_modules/@ecies/ciphers": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@ecies/ciphers/-/ciphers-0.2.4.tgz", + "integrity": "sha512-t+iX+Wf5nRKyNzk8dviW3Ikb/280+aEJAnw9YXvCp2tYGPSkMki+NRY+8aNLmVFv3eNtMdvViPNOPxS8SZNP+w==", + "license": "MIT", + "engines": { + "bun": ">=1", + "deno": ">=2", + "node": ">=16" + }, + "peerDependencies": { + "@noble/ciphers": "^1.0.0" + } + }, "node_modules/@esbuild/darwin-arm64": { "version": "0.25.4", "cpu": [ @@ -1942,6 +2025,57 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@ethereumjs/common": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-3.2.0.tgz", + "integrity": "sha512-pksvzI0VyLgmuEF2FA/JR/4/y6hcPq8OUail3/AvycBaW1d5VSauOZzqGvJ3RTmR4MU35lWE8KseKOsEhrFRBA==", + "license": "MIT", + "dependencies": { + "@ethereumjs/util": "^8.1.0", + "crc-32": "^1.2.0" + } + }, + "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/@ethereumjs/tx": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-4.2.0.tgz", + "integrity": "sha512-1nc6VO4jtFd172BbSnTnDQVr9IYBFl1y4xPzZdtkrkKIncBCkdbgfdRV+MiTkJYAtTxvV12GRZLqBFT1PNK6Yw==", + "license": "MPL-2.0", + "dependencies": { + "@ethereumjs/common": "^3.2.0", + "@ethereumjs/rlp": "^4.0.1", + "@ethereumjs/util": "^8.1.0", + "ethereum-cryptography": "^2.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@ethereumjs/util": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/util/-/util-8.1.0.tgz", + "integrity": "sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==", + "license": "MPL-2.0", + "dependencies": { + "@ethereumjs/rlp": "^4.0.1", + "ethereum-cryptography": "^2.0.0", + "micro-ftch": "^0.3.1" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/@expo/cli": { "version": "0.24.13", "license": "MIT", @@ -3309,6 +3443,19 @@ "node": ">=8" } }, + "node_modules/@gemini-wallet/core": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@gemini-wallet/core/-/core-0.2.0.tgz", + "integrity": "sha512-vv9aozWnKrrPWQ3vIFcWk7yta4hQW1Ie0fsNNPeXnjAxkbXr2hqMagEptLuMxpEP2W3mnRu05VDNKzcvAuuZDw==", + "license": "MIT", + "dependencies": { + "@metamask/rpc-errors": "7.0.2", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "viem": ">=2.0.0" + } + }, "node_modules/@humanfs/core": { "version": "0.19.1", "dev": true, @@ -3716,1970 +3863,6012 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@modelcontextprotocol/sdk": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.18.1.tgz", - "integrity": "sha512-d//GE8/Yh7aC3e7p+kZG8JqqEAwwDUmAfvH1quogtbk+ksS6E0RR6toKKESPYYZVre0meqkJb27zb+dhqE9Sgw==", - "license": "MIT", + "node_modules/@lit-labs/ssr-dom-shim": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.4.0.tgz", + "integrity": "sha512-ficsEARKnmmW5njugNYKipTm4SFnbik7CXtoencDZzmzo/dQ+2Q0bgkzJuoJP20Aj0F+izzJjOqsnkd6F/o1bw==", + "license": "BSD-3-Clause" + }, + "node_modules/@lit/reactive-element": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.1.1.tgz", + "integrity": "sha512-N+dm5PAYdQ8e6UlywyyrgI2t++wFGXfHx+dSJ1oBrg6FAxUj40jId++EaRm80MKX5JnlH1sBsyZ5h0bcZKemCg==", + "license": "BSD-3-Clause", "dependencies": { - "ajv": "^6.12.6", - "content-type": "^1.0.5", - "cors": "^2.8.5", - "cross-spawn": "^7.0.5", - "eventsource": "^3.0.2", - "eventsource-parser": "^3.0.0", - "express": "^5.0.1", - "express-rate-limit": "^7.5.0", - "pkce-challenge": "^5.0.0", - "raw-body": "^3.0.0", - "zod": "^3.23.8", - "zod-to-json-schema": "^3.24.1" - }, - "engines": { - "node": ">=18" + "@lit-labs/ssr-dom-shim": "^1.4.0" } }, - "node_modules/@noble/ciphers": { - "version": "1.3.0", - "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" + "node_modules/@metamask/eth-json-rpc-provider": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@metamask/eth-json-rpc-provider/-/eth-json-rpc-provider-1.0.1.tgz", + "integrity": "sha512-whiUMPlAOrVGmX8aKYVPvlKyG4CpQXiNNyt74vE1xb5sPvmx5oA7B/kOi/JdBvhGQq97U1/AVdXEdk2zkP8qyA==", + "dependencies": { + "@metamask/json-rpc-engine": "^7.0.0", + "@metamask/safe-event-emitter": "^3.0.0", + "@metamask/utils": "^5.0.1" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@noble/curves": { - "version": "1.9.6", - "license": "MIT", + "node_modules/@metamask/eth-json-rpc-provider/node_modules/@metamask/json-rpc-engine": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@metamask/json-rpc-engine/-/json-rpc-engine-7.3.3.tgz", + "integrity": "sha512-dwZPq8wx9yV3IX2caLi9q9xZBw2XeIoYqdyihDDDpuHVCEiqadJLwqM3zy+uwf6F1QYQ65A8aOMQg1Uw7LMLNg==", + "license": "ISC", "dependencies": { - "@noble/hashes": "1.8.0" + "@metamask/rpc-errors": "^6.2.1", + "@metamask/safe-event-emitter": "^3.0.0", + "@metamask/utils": "^8.3.0" }, "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "node": ">=16.0.0" } }, - "node_modules/@noble/hashes": { - "version": "1.8.0", - "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" + "node_modules/@metamask/eth-json-rpc-provider/node_modules/@metamask/json-rpc-engine/node_modules/@metamask/utils": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-8.5.0.tgz", + "integrity": "sha512-I6bkduevXb72TIM9q2LRO63JSsF9EXduh3sBr9oybNX2hNNpr/j1tEjXrsG0Uabm4MJ1xkGAQEMwifvKZIkyxQ==", + "license": "ISC", + "dependencies": { + "@ethereumjs/tx": "^4.2.0", + "@metamask/superstruct": "^3.0.0", + "@noble/hashes": "^1.3.1", + "@scure/base": "^1.1.3", + "@types/debug": "^4.1.7", + "debug": "^4.3.4", + "pony-cause": "^2.1.10", + "semver": "^7.5.4", + "uuid": "^9.0.1" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "dev": true, + "node_modules/@metamask/eth-json-rpc-provider/node_modules/@metamask/rpc-errors": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@metamask/rpc-errors/-/rpc-errors-6.4.0.tgz", + "integrity": "sha512-1ugFO1UoirU2esS3juZanS/Fo8C8XYocCuBpfZI5N7ECtoG+zu0wF+uWZASik6CkO6w9n/Iebt4iI4pT0vptpg==", "license": "MIT", "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "@metamask/utils": "^9.0.0", + "fast-safe-stringify": "^2.0.6" }, "engines": { - "node": ">= 8" + "node": ">=16.0.0" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "dev": true, - "license": "MIT", + "node_modules/@metamask/eth-json-rpc-provider/node_modules/@metamask/rpc-errors/node_modules/@metamask/utils": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-9.3.0.tgz", + "integrity": "sha512-w8CVbdkDrVXFJbfBSlDfafDR6BAkpDmv1bC1UJVCoVny5tW2RKAdn9i68Xf7asYT4TnUhl/hN4zfUiKQq9II4g==", + "license": "ISC", + "dependencies": { + "@ethereumjs/tx": "^4.2.0", + "@metamask/superstruct": "^3.1.0", + "@noble/hashes": "^1.3.1", + "@scure/base": "^1.1.3", + "@types/debug": "^4.1.7", + "debug": "^4.3.4", + "pony-cause": "^2.1.10", + "semver": "^7.5.4", + "uuid": "^9.0.1" + }, "engines": { - "node": ">= 8" + "node": ">=16.0.0" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "dev": true, - "license": "MIT", + "node_modules/@metamask/eth-json-rpc-provider/node_modules/@metamask/utils": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-5.0.2.tgz", + "integrity": "sha512-yfmE79bRQtnMzarnKfX7AEJBwFTxvTyw3nBQlu/5rmGXrjAeAMltoGxO62TFurxrQAFMNa/fEjIHNvungZp0+g==", + "license": "ISC", "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "@ethereumjs/tx": "^4.1.2", + "@types/debug": "^4.1.7", + "debug": "^4.3.4", + "semver": "^7.3.8", + "superstruct": "^1.0.3" }, "engines": { - "node": ">= 8" + "node": ">=14.0.0" } }, - "node_modules/@opentelemetry/api": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", - "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", - "license": "Apache-2.0", - "peer": true, + "node_modules/@metamask/eth-json-rpc-provider/node_modules/superstruct": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-1.0.4.tgz", + "integrity": "sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ==", + "license": "MIT", "engines": { - "node": ">=8.0.0" + "node": ">=14.0.0" } }, - "node_modules/@paralleldrive/cuid2": { - "version": "2.2.2", - "dev": true, + "node_modules/@metamask/eth-json-rpc-provider/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "license": "MIT", - "dependencies": { - "@noble/hashes": "^1.1.5" + "bin": { + "uuid": "dist/bin/uuid" } }, - "node_modules/@react-native/assets-registry": { - "version": "0.79.3", - "license": "MIT", - "peer": true, + "node_modules/@metamask/json-rpc-engine": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@metamask/json-rpc-engine/-/json-rpc-engine-8.0.2.tgz", + "integrity": "sha512-IoQPmql8q7ABLruW7i4EYVHWUbF74yrp63bRuXV5Zf9BQwcn5H9Ww1eLtROYvI1bUXwOiHZ6qT5CWTrDc/t/AA==", + "license": "ISC", + "dependencies": { + "@metamask/rpc-errors": "^6.2.1", + "@metamask/safe-event-emitter": "^3.0.0", + "@metamask/utils": "^8.3.0" + }, "engines": { - "node": ">=18" + "node": ">=16.0.0" } }, - "node_modules/@react-native/babel-plugin-codegen": { - "version": "0.79.2", + "node_modules/@metamask/json-rpc-engine/node_modules/@metamask/rpc-errors": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@metamask/rpc-errors/-/rpc-errors-6.4.0.tgz", + "integrity": "sha512-1ugFO1UoirU2esS3juZanS/Fo8C8XYocCuBpfZI5N7ECtoG+zu0wF+uWZASik6CkO6w9n/Iebt4iI4pT0vptpg==", "license": "MIT", - "peer": true, "dependencies": { - "@babel/traverse": "^7.25.3", - "@react-native/codegen": "0.79.2" + "@metamask/utils": "^9.0.0", + "fast-safe-stringify": "^2.0.6" }, "engines": { - "node": ">=18" + "node": ">=16.0.0" } }, - "node_modules/@react-native/babel-plugin-codegen/node_modules/@react-native/codegen": { - "version": "0.79.2", - "license": "MIT", - "peer": true, + "node_modules/@metamask/json-rpc-engine/node_modules/@metamask/rpc-errors/node_modules/@metamask/utils": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-9.3.0.tgz", + "integrity": "sha512-w8CVbdkDrVXFJbfBSlDfafDR6BAkpDmv1bC1UJVCoVny5tW2RKAdn9i68Xf7asYT4TnUhl/hN4zfUiKQq9II4g==", + "license": "ISC", "dependencies": { - "glob": "^7.1.1", - "hermes-parser": "0.25.1", - "invariant": "^2.2.4", - "nullthrows": "^1.1.1", - "yargs": "^17.6.2" + "@ethereumjs/tx": "^4.2.0", + "@metamask/superstruct": "^3.1.0", + "@noble/hashes": "^1.3.1", + "@scure/base": "^1.1.3", + "@types/debug": "^4.1.7", + "debug": "^4.3.4", + "pony-cause": "^2.1.10", + "semver": "^7.5.4", + "uuid": "^9.0.1" }, "engines": { - "node": ">=18" + "node": ">=16.0.0" + } + }, + "node_modules/@metamask/json-rpc-engine/node_modules/@metamask/utils": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-8.5.0.tgz", + "integrity": "sha512-I6bkduevXb72TIM9q2LRO63JSsF9EXduh3sBr9oybNX2hNNpr/j1tEjXrsG0Uabm4MJ1xkGAQEMwifvKZIkyxQ==", + "license": "ISC", + "dependencies": { + "@ethereumjs/tx": "^4.2.0", + "@metamask/superstruct": "^3.0.0", + "@noble/hashes": "^1.3.1", + "@scure/base": "^1.1.3", + "@types/debug": "^4.1.7", + "debug": "^4.3.4", + "pony-cause": "^2.1.10", + "semver": "^7.5.4", + "uuid": "^9.0.1" }, - "peerDependencies": { - "@babel/core": "*" + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@react-native/babel-preset": { - "version": "0.79.2", + "node_modules/@metamask/json-rpc-engine/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "license": "MIT", - "peer": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@metamask/json-rpc-middleware-stream": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@metamask/json-rpc-middleware-stream/-/json-rpc-middleware-stream-7.0.2.tgz", + "integrity": "sha512-yUdzsJK04Ev98Ck4D7lmRNQ8FPioXYhEUZOMS01LXW8qTvPGiRVXmVltj2p4wrLkh0vW7u6nv0mNl5xzC5Qmfg==", + "license": "ISC", "dependencies": { - "@babel/core": "^7.25.2", - "@babel/plugin-proposal-export-default-from": "^7.24.7", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-default-from": "^7.24.7", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-transform-arrow-functions": "^7.24.7", - "@babel/plugin-transform-async-generator-functions": "^7.25.4", - "@babel/plugin-transform-async-to-generator": "^7.24.7", - "@babel/plugin-transform-block-scoping": "^7.25.0", - "@babel/plugin-transform-class-properties": "^7.25.4", - "@babel/plugin-transform-classes": "^7.25.4", - "@babel/plugin-transform-computed-properties": "^7.24.7", - "@babel/plugin-transform-destructuring": "^7.24.8", - "@babel/plugin-transform-flow-strip-types": "^7.25.2", - "@babel/plugin-transform-for-of": "^7.24.7", - "@babel/plugin-transform-function-name": "^7.25.1", - "@babel/plugin-transform-literals": "^7.25.2", - "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", - "@babel/plugin-transform-modules-commonjs": "^7.24.8", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", - "@babel/plugin-transform-numeric-separator": "^7.24.7", - "@babel/plugin-transform-object-rest-spread": "^7.24.7", - "@babel/plugin-transform-optional-catch-binding": "^7.24.7", - "@babel/plugin-transform-optional-chaining": "^7.24.8", - "@babel/plugin-transform-parameters": "^7.24.7", - "@babel/plugin-transform-private-methods": "^7.24.7", - "@babel/plugin-transform-private-property-in-object": "^7.24.7", - "@babel/plugin-transform-react-display-name": "^7.24.7", - "@babel/plugin-transform-react-jsx": "^7.25.2", - "@babel/plugin-transform-react-jsx-self": "^7.24.7", - "@babel/plugin-transform-react-jsx-source": "^7.24.7", - "@babel/plugin-transform-regenerator": "^7.24.7", - "@babel/plugin-transform-runtime": "^7.24.7", - "@babel/plugin-transform-shorthand-properties": "^7.24.7", - "@babel/plugin-transform-spread": "^7.24.7", - "@babel/plugin-transform-sticky-regex": "^7.24.7", - "@babel/plugin-transform-typescript": "^7.25.2", - "@babel/plugin-transform-unicode-regex": "^7.24.7", - "@babel/template": "^7.25.0", - "@react-native/babel-plugin-codegen": "0.79.2", - "babel-plugin-syntax-hermes-parser": "0.25.1", - "babel-plugin-transform-flow-enums": "^0.0.2", - "react-refresh": "^0.14.0" + "@metamask/json-rpc-engine": "^8.0.2", + "@metamask/safe-event-emitter": "^3.0.0", + "@metamask/utils": "^8.3.0", + "readable-stream": "^3.6.2" }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@babel/core": "*" + "node": ">=16.0.0" } }, - "node_modules/@react-native/codegen": { - "version": "0.79.3", - "license": "MIT", - "peer": true, + "node_modules/@metamask/json-rpc-middleware-stream/node_modules/@metamask/utils": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-8.5.0.tgz", + "integrity": "sha512-I6bkduevXb72TIM9q2LRO63JSsF9EXduh3sBr9oybNX2hNNpr/j1tEjXrsG0Uabm4MJ1xkGAQEMwifvKZIkyxQ==", + "license": "ISC", "dependencies": { - "glob": "^7.1.1", - "hermes-parser": "0.25.1", - "invariant": "^2.2.4", - "nullthrows": "^1.1.1", - "yargs": "^17.6.2" + "@ethereumjs/tx": "^4.2.0", + "@metamask/superstruct": "^3.0.0", + "@noble/hashes": "^1.3.1", + "@scure/base": "^1.1.3", + "@types/debug": "^4.1.7", + "debug": "^4.3.4", + "pony-cause": "^2.1.10", + "semver": "^7.5.4", + "uuid": "^9.0.1" }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@babel/core": "*" + "node": ">=16.0.0" } }, - "node_modules/@react-native/community-cli-plugin": { - "version": "0.79.3", + "node_modules/@metamask/json-rpc-middleware-stream/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "license": "MIT", - "peer": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@metamask/object-multiplex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@metamask/object-multiplex/-/object-multiplex-2.1.0.tgz", + "integrity": "sha512-4vKIiv0DQxljcXwfpnbsXcfa5glMj5Zg9mqn4xpIWqkv6uJ2ma5/GtUfLFSxhlxnR8asRMv8dDmWya1Tc1sDFA==", + "license": "ISC", "dependencies": { - "@react-native/dev-middleware": "0.79.3", - "chalk": "^4.0.0", - "debug": "^2.2.0", - "invariant": "^2.2.4", - "metro": "^0.82.0", - "metro-config": "^0.82.0", - "metro-core": "^0.82.0", - "semver": "^7.1.3" + "once": "^1.4.0", + "readable-stream": "^3.6.2" }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@react-native-community/cli": "*" - }, - "peerDependenciesMeta": { - "@react-native-community/cli": { - "optional": true - } + "node": "^16.20 || ^18.16 || >=20" } }, - "node_modules/@react-native/community-cli-plugin/node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/@metamask/onboarding": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@metamask/onboarding/-/onboarding-1.0.1.tgz", + "integrity": "sha512-FqHhAsCI+Vacx2qa5mAFcWNSrTcVGMNjzxVgaX8ECSny/BJ9/vgXP9V7WF/8vb9DltPeQkxr+Fnfmm6GHfmdTQ==", "license": "MIT", - "peer": true, "dependencies": { - "color-convert": "^2.0.1" + "bowser": "^2.9.0" + } + }, + "node_modules/@metamask/providers": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@metamask/providers/-/providers-16.1.0.tgz", + "integrity": "sha512-znVCvux30+3SaUwcUGaSf+pUckzT5ukPRpcBmy+muBLC0yaWnBcvDqGfcsw6CBIenUdFrVoAFa8B6jsuCY/a+g==", + "license": "MIT", + "dependencies": { + "@metamask/json-rpc-engine": "^8.0.1", + "@metamask/json-rpc-middleware-stream": "^7.0.1", + "@metamask/object-multiplex": "^2.0.0", + "@metamask/rpc-errors": "^6.2.1", + "@metamask/safe-event-emitter": "^3.1.1", + "@metamask/utils": "^8.3.0", + "detect-browser": "^5.2.0", + "extension-port-stream": "^3.0.0", + "fast-deep-equal": "^3.1.3", + "is-stream": "^2.0.0", + "readable-stream": "^3.6.2", + "webextension-polyfill": "^0.10.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": "^18.18 || >=20" } }, - "node_modules/@react-native/community-cli-plugin/node_modules/chalk": { - "version": "4.1.2", + "node_modules/@metamask/providers/node_modules/@metamask/rpc-errors": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@metamask/rpc-errors/-/rpc-errors-6.4.0.tgz", + "integrity": "sha512-1ugFO1UoirU2esS3juZanS/Fo8C8XYocCuBpfZI5N7ECtoG+zu0wF+uWZASik6CkO6w9n/Iebt4iI4pT0vptpg==", "license": "MIT", - "peer": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "@metamask/utils": "^9.0.0", + "fast-safe-stringify": "^2.0.6" }, "engines": { - "node": ">=10" + "node": ">=16.0.0" + } + }, + "node_modules/@metamask/providers/node_modules/@metamask/rpc-errors/node_modules/@metamask/utils": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-9.3.0.tgz", + "integrity": "sha512-w8CVbdkDrVXFJbfBSlDfafDR6BAkpDmv1bC1UJVCoVny5tW2RKAdn9i68Xf7asYT4TnUhl/hN4zfUiKQq9II4g==", + "license": "ISC", + "dependencies": { + "@ethereumjs/tx": "^4.2.0", + "@metamask/superstruct": "^3.1.0", + "@noble/hashes": "^1.3.1", + "@scure/base": "^1.1.3", + "@types/debug": "^4.1.7", + "debug": "^4.3.4", + "pony-cause": "^2.1.10", + "semver": "^7.5.4", + "uuid": "^9.0.1" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@react-native/community-cli-plugin/node_modules/debug": { - "version": "2.6.9", - "license": "MIT", - "peer": true, + "node_modules/@metamask/providers/node_modules/@metamask/utils": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-8.5.0.tgz", + "integrity": "sha512-I6bkduevXb72TIM9q2LRO63JSsF9EXduh3sBr9oybNX2hNNpr/j1tEjXrsG0Uabm4MJ1xkGAQEMwifvKZIkyxQ==", + "license": "ISC", "dependencies": { - "ms": "2.0.0" + "@ethereumjs/tx": "^4.2.0", + "@metamask/superstruct": "^3.0.0", + "@noble/hashes": "^1.3.1", + "@scure/base": "^1.1.3", + "@types/debug": "^4.1.7", + "debug": "^4.3.4", + "pony-cause": "^2.1.10", + "semver": "^7.5.4", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@react-native/community-cli-plugin/node_modules/ms": { - "version": "2.0.0", + "node_modules/@metamask/providers/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "license": "MIT", - "peer": true + "bin": { + "uuid": "dist/bin/uuid" + } }, - "node_modules/@react-native/community-cli-plugin/node_modules/supports-color": { - "version": "7.2.0", + "node_modules/@metamask/rpc-errors": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@metamask/rpc-errors/-/rpc-errors-7.0.2.tgz", + "integrity": "sha512-YYYHsVYd46XwY2QZzpGeU4PSdRhHdxnzkB8piWGvJW2xbikZ3R+epAYEL4q/K8bh9JPTucsUdwRFnACor1aOYw==", "license": "MIT", - "peer": true, "dependencies": { - "has-flag": "^4.0.0" + "@metamask/utils": "^11.0.1", + "fast-safe-stringify": "^2.0.6" }, "engines": { - "node": ">=8" + "node": "^18.20 || ^20.17 || >=22" } }, - "node_modules/@react-native/debugger-frontend": { - "version": "0.79.3", - "license": "BSD-3-Clause", - "peer": true, + "node_modules/@metamask/safe-event-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@metamask/safe-event-emitter/-/safe-event-emitter-3.1.2.tgz", + "integrity": "sha512-5yb2gMI1BDm0JybZezeoX/3XhPDOtTbcFvpTXM9kxsoZjPZFh4XciqRbpD6N86HYZqWDhEaKUDuOyR0sQHEjMA==", + "license": "ISC", "engines": { - "node": ">=18" + "node": ">=12.0.0" } }, - "node_modules/@react-native/dev-middleware": { - "version": "0.79.3", - "license": "MIT", - "peer": true, + "node_modules/@metamask/sdk": { + "version": "0.32.0", + "resolved": "https://registry.npmjs.org/@metamask/sdk/-/sdk-0.32.0.tgz", + "integrity": "sha512-WmGAlP1oBuD9hk4CsdlG1WJFuPtYJY+dnTHJMeCyohTWD2GgkcLMUUuvu9lO1/NVzuOoSi1OrnjbuY1O/1NZ1g==", "dependencies": { - "@isaacs/ttlcache": "^1.4.1", - "@react-native/debugger-frontend": "0.79.3", - "chrome-launcher": "^0.15.2", - "chromium-edge-launcher": "^0.2.0", - "connect": "^3.6.5", - "debug": "^2.2.0", - "invariant": "^2.2.4", - "nullthrows": "^1.1.1", - "open": "^7.0.3", - "serve-static": "^1.16.2", - "ws": "^6.2.3" - }, - "engines": { - "node": ">=18" + "@babel/runtime": "^7.26.0", + "@metamask/onboarding": "^1.0.1", + "@metamask/providers": "16.1.0", + "@metamask/sdk-communication-layer": "0.32.0", + "@metamask/sdk-install-modal-web": "0.32.0", + "@paulmillr/qr": "^0.2.1", + "bowser": "^2.9.0", + "cross-fetch": "^4.0.0", + "debug": "^4.3.4", + "eciesjs": "^0.4.11", + "eth-rpc-errors": "^4.0.3", + "eventemitter2": "^6.4.9", + "obj-multiplex": "^1.0.0", + "pump": "^3.0.0", + "readable-stream": "^3.6.2", + "socket.io-client": "^4.5.1", + "tslib": "^2.6.0", + "util": "^0.12.4", + "uuid": "^8.3.2" } }, - "node_modules/@react-native/dev-middleware/node_modules/debug": { - "version": "2.6.9", - "license": "MIT", - "peer": true, + "node_modules/@metamask/sdk-install-modal-web": { + "version": "0.32.0", + "resolved": "https://registry.npmjs.org/@metamask/sdk-install-modal-web/-/sdk-install-modal-web-0.32.0.tgz", + "integrity": "sha512-TFoktj0JgfWnQaL3yFkApqNwcaqJ+dw4xcnrJueMP3aXkSNev2Ido+WVNOg4IIMxnmOrfAC9t0UJ0u/dC9MjOQ==", "dependencies": { - "ms": "2.0.0" + "@paulmillr/qr": "^0.2.1" } }, - "node_modules/@react-native/dev-middleware/node_modules/fresh": { - "version": "0.5.2", - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.6" + "node_modules/@metamask/sdk/node_modules/@metamask/sdk-communication-layer": { + "version": "0.32.0", + "resolved": "https://registry.npmjs.org/@metamask/sdk-communication-layer/-/sdk-communication-layer-0.32.0.tgz", + "integrity": "sha512-dmj/KFjMi1fsdZGIOtbhxdg3amxhKL/A5BqSU4uh/SyDKPub/OT+x5pX8bGjpTL1WPWY/Q0OIlvFyX3VWnT06Q==", + "dependencies": { + "bufferutil": "^4.0.8", + "date-fns": "^2.29.3", + "debug": "^4.3.4", + "utf-8-validate": "^5.0.2", + "uuid": "^8.3.2" + }, + "peerDependencies": { + "cross-fetch": "^4.0.0", + "eciesjs": "*", + "eventemitter2": "^6.4.9", + "readable-stream": "^3.6.2", + "socket.io-client": "^4.5.1" } }, - "node_modules/@react-native/dev-middleware/node_modules/ms": { - "version": "2.0.0", - "license": "MIT", - "peer": true - }, - "node_modules/@react-native/dev-middleware/node_modules/send": { - "version": "0.19.0", + "node_modules/@metamask/sdk/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", - "peer": true, "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" + "node-fetch": "^2.7.0" } }, - "node_modules/@react-native/dev-middleware/node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", + "node_modules/@metamask/superstruct": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@metamask/superstruct/-/superstruct-3.2.1.tgz", + "integrity": "sha512-fLgJnDOXFmuVlB38rUN5SmU7hAFQcCjrg3Vrxz67KTY7YHFnSNEKvX4avmEBdOI0yTCxZjwMCFEqsC8k2+Wd3g==", "license": "MIT", - "peer": true, "engines": { - "node": ">= 0.8" + "node": ">=16.0.0" } }, - "node_modules/@react-native/dev-middleware/node_modules/send/node_modules/ms": { - "version": "2.1.3", - "license": "MIT", - "peer": true - }, - "node_modules/@react-native/dev-middleware/node_modules/serve-static": { - "version": "1.16.2", - "license": "MIT", - "peer": true, + "node_modules/@metamask/utils": { + "version": "11.8.0", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-11.8.0.tgz", + "integrity": "sha512-EJqiuvVBAjV1vd1kBhmVmRtGfadrBfY3ImcAMjl+8MSSByTB3VNwvlIBLQdp+TwdAomUdenJCx2BvOSQykm8Hg==", + "license": "ISC", "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" + "@ethereumjs/tx": "^4.2.0", + "@metamask/superstruct": "^3.1.0", + "@noble/hashes": "^1.3.1", + "@scure/base": "^1.1.3", + "@types/debug": "^4.1.7", + "@types/lodash": "^4.17.20", + "debug": "^4.3.4", + "lodash": "^4.17.21", + "pony-cause": "^2.1.10", + "semver": "^7.5.4", + "uuid": "^9.0.1" }, "engines": { - "node": ">= 0.8.0" + "node": "^18.18 || ^20.14 || >=22" } }, - "node_modules/@react-native/dev-middleware/node_modules/ws": { - "version": "6.2.3", + "node_modules/@metamask/utils/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "license": "MIT", - "peer": true, - "dependencies": { - "async-limiter": "~1.0.0" + "bin": { + "uuid": "dist/bin/uuid" } }, - "node_modules/@react-native/gradle-plugin": { - "version": "0.79.3", + "node_modules/@modelcontextprotocol/sdk": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.18.1.tgz", + "integrity": "sha512-d//GE8/Yh7aC3e7p+kZG8JqqEAwwDUmAfvH1quogtbk+ksS6E0RR6toKKESPYYZVre0meqkJb27zb+dhqE9Sgw==", "license": "MIT", - "peer": true, + "dependencies": { + "ajv": "^6.12.6", + "content-type": "^1.0.5", + "cors": "^2.8.5", + "cross-spawn": "^7.0.5", + "eventsource": "^3.0.2", + "eventsource-parser": "^3.0.0", + "express": "^5.0.1", + "express-rate-limit": "^7.5.0", + "pkce-challenge": "^5.0.0", + "raw-body": "^3.0.0", + "zod": "^3.23.8", + "zod-to-json-schema": "^3.24.1" + }, "engines": { "node": ">=18" } }, - "node_modules/@react-native/js-polyfills": { - "version": "0.79.3", + "node_modules/@noble/ciphers": { + "version": "1.3.0", "license": "MIT", - "peer": true, "engines": { - "node": ">=18" + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@react-native/normalize-colors": { - "version": "0.79.3", - "license": "MIT", - "peer": true - }, - "node_modules/@react-native/virtualized-lists": { - "version": "0.79.3", + "node_modules/@noble/curves": { + "version": "1.9.6", "license": "MIT", - "peer": true, "dependencies": { - "invariant": "^2.2.4", - "nullthrows": "^1.1.1" + "@noble/hashes": "1.8.0" }, "engines": { - "node": ">=18" + "node": "^14.21.3 || >=16" }, - "peerDependencies": { - "@types/react": "^19.0.0", - "react": "*", - "react-native": "*" + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.8.0", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@rollup/plugin-commonjs": { - "version": "28.0.6", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.6.tgz", - "integrity": "sha512-XSQB1K7FUU5QP+3lOQmVCE3I0FcbbNvmNT4VJSj93iUjayaARrTQeoRdiYQoftAJBLrR9t2agwAd3ekaTgHNlw==", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", "dev": true, "license": "MIT", "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "commondir": "^1.0.1", - "estree-walker": "^2.0.2", - "fdir": "^6.2.0", - "is-reference": "1.2.1", - "magic-string": "^0.30.3", - "picomatch": "^4.0.2" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, "engines": { - "node": ">=16.0.0 || 14 >= 14.17" - }, - "peerDependencies": { - "rollup": "^2.68.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } + "node": ">= 8" } }, - "node_modules/@rollup/plugin-commonjs/node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">= 8" + } }, - "node_modules/@rollup/plugin-json": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.1.0.tgz", - "integrity": "sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", "dev": true, "license": "MIT", "dependencies": { - "@rollup/pluginutils": "^5.1.0" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } + "node": ">= 8" } }, - "node_modules/@rollup/plugin-node-resolve": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-16.0.1.tgz", - "integrity": "sha512-tk5YCxJWIG81umIvNkSod2qK5KyQW19qcBF/B78n1bjtOON6gzKoVeSzAE8yHCZEDmqkHKkxplExA8KzdJLJpA==", + "node_modules/@opentelemetry/api": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@paralleldrive/cuid2": { + "version": "2.2.2", "dev": true, "license": "MIT", "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "@types/resolve": "1.20.2", - "deepmerge": "^4.2.2", - "is-module": "^1.0.0", - "resolve": "^1.22.1" - }, + "@noble/hashes": "^1.1.5" + } + }, + "node_modules/@paulmillr/qr": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@paulmillr/qr/-/qr-0.2.1.tgz", + "integrity": "sha512-IHnV6A+zxU7XwmKFinmYjUcwlyK9+xkG3/s9KcQhI9BjQKycrJ1JRO+FbNYPwZiPKW3je/DR0k7w8/gLa5eaxQ==", + "deprecated": "The package is now available as \"qr\": npm install qr", + "license": "(MIT OR Apache-2.0)", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@react-native/assets-registry": { + "version": "0.79.3", + "license": "MIT", + "peer": true, "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^2.78.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } + "node": ">=18" } }, - "node_modules/@rollup/plugin-typescript": { - "version": "12.1.4", - "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-12.1.4.tgz", - "integrity": "sha512-s5Hx+EtN60LMlDBvl5f04bEiFZmAepk27Q+mr85L/00zPDn1jtzlTV6FWn81MaIwqfWzKxmOJrBWHU6vtQyedQ==", - "dev": true, + "node_modules/@react-native/babel-plugin-codegen": { + "version": "0.79.2", "license": "MIT", + "peer": true, "dependencies": { - "@rollup/pluginutils": "^5.1.0", - "resolve": "^1.22.1" + "@babel/traverse": "^7.25.3", + "@react-native/codegen": "0.79.2" }, "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^2.14.0||^3.0.0||^4.0.0", - "tslib": "*", - "typescript": ">=3.7.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - }, - "tslib": { - "optional": true - } + "node": ">=18" } }, - "node_modules/@rollup/pluginutils": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", - "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", - "dev": true, + "node_modules/@react-native/babel-plugin-codegen/node_modules/@react-native/codegen": { + "version": "0.79.2", "license": "MIT", + "peer": true, "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^4.0.2" + "glob": "^7.1.1", + "hermes-parser": "0.25.1", + "invariant": "^2.2.4", + "nullthrows": "^1.1.1", + "yargs": "^17.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=18" }, "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } + "@babel/core": "*" } }, - "node_modules/@rollup/pluginutils/node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.50.2.tgz", - "integrity": "sha512-uLN8NAiFVIRKX9ZQha8wy6UUs06UNSZ32xj6giK/rmMXAgKahwExvK6SsmgU5/brh4w/nSgj8e0k3c1HBQpa0A==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.50.2.tgz", - "integrity": "sha512-oEouqQk2/zxxj22PNcGSskya+3kV0ZKH+nQxuCCOGJ4oTXBdNTbv+f/E3c74cNLeMO1S5wVWacSws10TTSB77g==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/@react-native/babel-preset": { + "version": "0.79.2", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/core": "^7.25.2", + "@babel/plugin-proposal-export-default-from": "^7.24.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-default-from": "^7.24.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-transform-arrow-functions": "^7.24.7", + "@babel/plugin-transform-async-generator-functions": "^7.25.4", + "@babel/plugin-transform-async-to-generator": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.25.0", + "@babel/plugin-transform-class-properties": "^7.25.4", + "@babel/plugin-transform-classes": "^7.25.4", + "@babel/plugin-transform-computed-properties": "^7.24.7", + "@babel/plugin-transform-destructuring": "^7.24.8", + "@babel/plugin-transform-flow-strip-types": "^7.25.2", + "@babel/plugin-transform-for-of": "^7.24.7", + "@babel/plugin-transform-function-name": "^7.25.1", + "@babel/plugin-transform-literals": "^7.25.2", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.8", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-numeric-separator": "^7.24.7", + "@babel/plugin-transform-object-rest-spread": "^7.24.7", + "@babel/plugin-transform-optional-catch-binding": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.8", + "@babel/plugin-transform-parameters": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.24.7", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", + "@babel/plugin-transform-react-display-name": "^7.24.7", + "@babel/plugin-transform-react-jsx": "^7.25.2", + "@babel/plugin-transform-react-jsx-self": "^7.24.7", + "@babel/plugin-transform-react-jsx-source": "^7.24.7", + "@babel/plugin-transform-regenerator": "^7.24.7", + "@babel/plugin-transform-runtime": "^7.24.7", + "@babel/plugin-transform-shorthand-properties": "^7.24.7", + "@babel/plugin-transform-spread": "^7.24.7", + "@babel/plugin-transform-sticky-regex": "^7.24.7", + "@babel/plugin-transform-typescript": "^7.25.2", + "@babel/plugin-transform-unicode-regex": "^7.24.7", + "@babel/template": "^7.25.0", + "@react-native/babel-plugin-codegen": "0.79.2", + "babel-plugin-syntax-hermes-parser": "0.25.1", + "babel-plugin-transform-flow-enums": "^0.0.2", + "react-refresh": "^0.14.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@babel/core": "*" + } + }, + "node_modules/@react-native/codegen": { + "version": "0.79.3", + "license": "MIT", + "peer": true, + "dependencies": { + "glob": "^7.1.1", + "hermes-parser": "0.25.1", + "invariant": "^2.2.4", + "nullthrows": "^1.1.1", + "yargs": "^17.6.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@babel/core": "*" + } + }, + "node_modules/@react-native/community-cli-plugin": { + "version": "0.79.3", + "license": "MIT", + "peer": true, + "dependencies": { + "@react-native/dev-middleware": "0.79.3", + "chalk": "^4.0.0", + "debug": "^2.2.0", + "invariant": "^2.2.4", + "metro": "^0.82.0", + "metro-config": "^0.82.0", + "metro-core": "^0.82.0", + "semver": "^7.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@react-native-community/cli": "*" + }, + "peerDependenciesMeta": { + "@react-native-community/cli": { + "optional": true + } + } + }, + "node_modules/@react-native/community-cli-plugin/node_modules/ansi-styles": { + "version": "4.3.0", + "license": "MIT", + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@react-native/community-cli-plugin/node_modules/chalk": { + "version": "4.1.2", + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@react-native/community-cli-plugin/node_modules/debug": { + "version": "2.6.9", + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/@react-native/community-cli-plugin/node_modules/ms": { + "version": "2.0.0", + "license": "MIT", + "peer": true + }, + "node_modules/@react-native/community-cli-plugin/node_modules/supports-color": { + "version": "7.2.0", + "license": "MIT", + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native/debugger-frontend": { + "version": "0.79.3", + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/dev-middleware": { + "version": "0.79.3", + "license": "MIT", + "peer": true, + "dependencies": { + "@isaacs/ttlcache": "^1.4.1", + "@react-native/debugger-frontend": "0.79.3", + "chrome-launcher": "^0.15.2", + "chromium-edge-launcher": "^0.2.0", + "connect": "^3.6.5", + "debug": "^2.2.0", + "invariant": "^2.2.4", + "nullthrows": "^1.1.1", + "open": "^7.0.3", + "serve-static": "^1.16.2", + "ws": "^6.2.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/debug": { + "version": "2.6.9", + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/fresh": { + "version": "0.5.2", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/ms": { + "version": "2.0.0", + "license": "MIT", + "peer": true + }, + "node_modules/@react-native/dev-middleware/node_modules/send": { + "version": "0.19.0", + "license": "MIT", + "peer": true, + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/send/node_modules/ms": { + "version": "2.1.3", + "license": "MIT", + "peer": true + }, + "node_modules/@react-native/dev-middleware/node_modules/serve-static": { + "version": "1.16.2", + "license": "MIT", + "peer": true, + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/ws": { + "version": "6.2.3", + "license": "MIT", + "peer": true, + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/@react-native/gradle-plugin": { + "version": "0.79.3", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/js-polyfills": { + "version": "0.79.3", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/normalize-colors": { + "version": "0.79.3", + "license": "MIT", + "peer": true + }, + "node_modules/@react-native/virtualized-lists": { + "version": "0.79.3", + "license": "MIT", + "peer": true, + "dependencies": { + "invariant": "^2.2.4", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/react": "^19.0.0", + "react": "*", + "react-native": "*" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@reown/appkit": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@reown/appkit/-/appkit-1.7.8.tgz", + "integrity": "sha512-51kTleozhA618T1UvMghkhKfaPcc9JlKwLJ5uV+riHyvSoWPKPRIa5A6M1Wano5puNyW0s3fwywhyqTHSilkaA==", + "license": "Apache-2.0", + "dependencies": { + "@reown/appkit-common": "1.7.8", + "@reown/appkit-controllers": "1.7.8", + "@reown/appkit-pay": "1.7.8", + "@reown/appkit-polyfills": "1.7.8", + "@reown/appkit-scaffold-ui": "1.7.8", + "@reown/appkit-ui": "1.7.8", + "@reown/appkit-utils": "1.7.8", + "@reown/appkit-wallet": "1.7.8", + "@walletconnect/types": "2.21.0", + "@walletconnect/universal-provider": "2.21.0", + "bs58": "6.0.0", + "valtio": "1.13.2", + "viem": ">=2.29.0" + } + }, + "node_modules/@reown/appkit-common": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@reown/appkit-common/-/appkit-common-1.7.8.tgz", + "integrity": "sha512-ridIhc/x6JOp7KbDdwGKY4zwf8/iK8EYBl+HtWrruutSLwZyVi5P8WaZa+8iajL6LcDcDF7LoyLwMTym7SRuwQ==", + "license": "Apache-2.0", + "dependencies": { + "big.js": "6.2.2", + "dayjs": "1.11.13", + "viem": ">=2.29.0" + } + }, + "node_modules/@reown/appkit-controllers": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@reown/appkit-controllers/-/appkit-controllers-1.7.8.tgz", + "integrity": "sha512-IdXlJlivrlj6m63VsGLsjtPHHsTWvKGVzWIP1fXZHVqmK+rZCBDjCi9j267Rb9/nYRGHWBtlFQhO8dK35WfeDA==", + "license": "Apache-2.0", + "dependencies": { + "@reown/appkit-common": "1.7.8", + "@reown/appkit-wallet": "1.7.8", + "@walletconnect/universal-provider": "2.21.0", + "valtio": "1.13.2", + "viem": ">=2.29.0" + } + }, + "node_modules/@reown/appkit-controllers/node_modules/@noble/ciphers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.2.1.tgz", + "integrity": "sha512-rONPWMC7PeExE077uLE4oqWrZ1IvAfz3oH9LibVAcVCopJiA9R62uavnbEzdkVmJYI6M6Zgkbeb07+tWjlq2XA==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit-controllers/node_modules/@noble/curves": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.1.tgz", + "integrity": "sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.7.1" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit-controllers/node_modules/@noble/hashes": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz", + "integrity": "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit-controllers/node_modules/@scure/bip32": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.6.2.tgz", + "integrity": "sha512-t96EPDMbtGgtb7onKKqxRLfE5g05k7uHnHRM2xdE6BP/ZmxaLtPek4J4KfVn/90IQNrU1IOAqMgiDtUdtbe3nw==", + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.8.1", + "@noble/hashes": "~1.7.1", + "@scure/base": "~1.2.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit-controllers/node_modules/@scure/bip39": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.5.4.tgz", + "integrity": "sha512-TFM4ni0vKvCfBpohoh+/lY05i9gRbSwXWngAsF4CABQxoaOHijxuaZ2R6cStDQ5CHtHO9aGJTr4ksVJASRRyMA==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.7.1", + "@scure/base": "~1.2.4" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit-controllers/node_modules/@walletconnect/core": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@walletconnect/core/-/core-2.21.0.tgz", + "integrity": "sha512-o6R7Ua4myxR8aRUAJ1z3gT9nM+jd2B2mfamu6arzy1Cc6vi10fIwFWb6vg3bC8xJ6o9H3n/cN5TOW3aA9Y1XVw==", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-provider": "1.0.14", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/jsonrpc-ws-connection": "1.0.16", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "2.1.2", + "@walletconnect/relay-api": "1.0.11", + "@walletconnect/relay-auth": "1.1.0", + "@walletconnect/safe-json": "1.0.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.21.0", + "@walletconnect/utils": "2.21.0", + "@walletconnect/window-getters": "1.0.1", + "es-toolkit": "1.33.0", + "events": "3.3.0", + "uint8arrays": "3.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@reown/appkit-controllers/node_modules/@walletconnect/sign-client": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@walletconnect/sign-client/-/sign-client-2.21.0.tgz", + "integrity": "sha512-z7h+PeLa5Au2R591d/8ZlziE0stJvdzP9jNFzFolf2RG/OiXulgFKum8PrIyXy+Rg2q95U9nRVUF9fWcn78yBA==", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/core": "2.21.0", + "@walletconnect/events": "1.0.1", + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/logger": "2.1.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.21.0", + "@walletconnect/utils": "2.21.0", + "events": "3.3.0" + } + }, + "node_modules/@reown/appkit-controllers/node_modules/@walletconnect/types": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-2.21.0.tgz", + "integrity": "sha512-ll+9upzqt95ZBWcfkOszXZkfnpbJJ2CmxMfGgE5GmhdxxxCcO5bGhXkI+x8OpiS555RJ/v/sXJYMSOLkmu4fFw==", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/events": "1.0.1", + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "2.1.2", + "events": "3.3.0" + } + }, + "node_modules/@reown/appkit-controllers/node_modules/@walletconnect/universal-provider": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@walletconnect/universal-provider/-/universal-provider-2.21.0.tgz", + "integrity": "sha512-mtUQvewt+X0VBQay/xOJBvxsB3Xsm1lTwFjZ6WUwSOTR1X+FNb71hSApnV5kbsdDIpYPXeQUbGt2se1n5E5UBg==", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/events": "1.0.1", + "@walletconnect/jsonrpc-http-connection": "1.0.8", + "@walletconnect/jsonrpc-provider": "1.0.14", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "2.1.2", + "@walletconnect/sign-client": "2.21.0", + "@walletconnect/types": "2.21.0", + "@walletconnect/utils": "2.21.0", + "es-toolkit": "1.33.0", + "events": "3.3.0" + } + }, + "node_modules/@reown/appkit-controllers/node_modules/@walletconnect/utils": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@walletconnect/utils/-/utils-2.21.0.tgz", + "integrity": "sha512-zfHLiUoBrQ8rP57HTPXW7rQMnYxYI4gT9yTACxVW6LhIFROTF6/ytm5SKNoIvi4a5nX5dfXG4D9XwQUCu8Ilig==", + "license": "Apache-2.0", + "dependencies": { + "@noble/ciphers": "1.2.1", + "@noble/curves": "1.8.1", + "@noble/hashes": "1.7.1", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/relay-api": "1.0.11", + "@walletconnect/relay-auth": "1.1.0", + "@walletconnect/safe-json": "1.0.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.21.0", + "@walletconnect/window-getters": "1.0.1", + "@walletconnect/window-metadata": "1.0.1", + "bs58": "6.0.0", + "detect-browser": "5.3.0", + "query-string": "7.1.3", + "uint8arrays": "3.1.0", + "viem": "2.23.2" + } + }, + "node_modules/@reown/appkit-controllers/node_modules/@walletconnect/utils/node_modules/viem": { + "version": "2.23.2", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.23.2.tgz", + "integrity": "sha512-NVmW/E0c5crMOtbEAqMF0e3NmvQykFXhLOc/CkLIXOlzHSA6KXVz3CYVmaKqBF8/xtjsjHAGjdJN3Ru1kFJLaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@noble/curves": "1.8.1", + "@noble/hashes": "1.7.1", + "@scure/bip32": "1.6.2", + "@scure/bip39": "1.5.4", + "abitype": "1.0.8", + "isows": "1.0.6", + "ox": "0.6.7", + "ws": "8.18.0" + }, + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@reown/appkit-controllers/node_modules/isows": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.6.tgz", + "integrity": "sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/@reown/appkit-controllers/node_modules/ox": { + "version": "0.6.7", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.6.7.tgz", + "integrity": "sha512-17Gk/eFsFRAZ80p5eKqv89a57uXjd3NgIf1CaXojATPBuujVc/fQSVhBeAU9JCRB+k7J50WQAyWTxK19T9GgbA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@adraffy/ens-normalize": "^1.10.1", + "@noble/curves": "^1.6.0", + "@noble/hashes": "^1.5.0", + "@scure/bip32": "^1.5.0", + "@scure/bip39": "^1.4.0", + "abitype": "^1.0.6", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@reown/appkit-controllers/node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "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/@reown/appkit-pay": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@reown/appkit-pay/-/appkit-pay-1.7.8.tgz", + "integrity": "sha512-OSGQ+QJkXx0FEEjlpQqIhT8zGJKOoHzVnyy/0QFrl3WrQTjCzg0L6+i91Ad5Iy1zb6V5JjqtfIFpRVRWN4M3pw==", + "license": "Apache-2.0", + "dependencies": { + "@reown/appkit-common": "1.7.8", + "@reown/appkit-controllers": "1.7.8", + "@reown/appkit-ui": "1.7.8", + "@reown/appkit-utils": "1.7.8", + "lit": "3.3.0", + "valtio": "1.13.2" + } + }, + "node_modules/@reown/appkit-polyfills": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@reown/appkit-polyfills/-/appkit-polyfills-1.7.8.tgz", + "integrity": "sha512-W/kq786dcHHAuJ3IV2prRLEgD/2iOey4ueMHf1sIFjhhCGMynMkhsOhQMUH0tzodPqUgAC494z4bpIDYjwWXaA==", + "license": "Apache-2.0", + "dependencies": { + "buffer": "6.0.3" + } + }, + "node_modules/@reown/appkit-scaffold-ui": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@reown/appkit-scaffold-ui/-/appkit-scaffold-ui-1.7.8.tgz", + "integrity": "sha512-RCeHhAwOrIgcvHwYlNWMcIDibdI91waaoEYBGw71inE0kDB8uZbE7tE6DAXJmDkvl0qPh+DqlC4QbJLF1FVYdQ==", + "license": "Apache-2.0", + "dependencies": { + "@reown/appkit-common": "1.7.8", + "@reown/appkit-controllers": "1.7.8", + "@reown/appkit-ui": "1.7.8", + "@reown/appkit-utils": "1.7.8", + "@reown/appkit-wallet": "1.7.8", + "lit": "3.3.0" + } + }, + "node_modules/@reown/appkit-ui": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@reown/appkit-ui/-/appkit-ui-1.7.8.tgz", + "integrity": "sha512-1hjCKjf6FLMFzrulhl0Y9Vb9Fu4royE+SXCPSWh4VhZhWqlzUFc7kutnZKx8XZFVQH4pbBvY62SpRC93gqoHow==", + "license": "Apache-2.0", + "dependencies": { + "@reown/appkit-common": "1.7.8", + "@reown/appkit-controllers": "1.7.8", + "@reown/appkit-wallet": "1.7.8", + "lit": "3.3.0", + "qrcode": "1.5.3" + } + }, + "node_modules/@reown/appkit-utils": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@reown/appkit-utils/-/appkit-utils-1.7.8.tgz", + "integrity": "sha512-8X7UvmE8GiaoitCwNoB86pttHgQtzy4ryHZM9kQpvjQ0ULpiER44t1qpVLXNM4X35O0v18W0Dk60DnYRMH2WRw==", + "license": "Apache-2.0", + "dependencies": { + "@reown/appkit-common": "1.7.8", + "@reown/appkit-controllers": "1.7.8", + "@reown/appkit-polyfills": "1.7.8", + "@reown/appkit-wallet": "1.7.8", + "@walletconnect/logger": "2.1.2", + "@walletconnect/universal-provider": "2.21.0", + "valtio": "1.13.2", + "viem": ">=2.29.0" + }, + "peerDependencies": { + "valtio": "1.13.2" + } + }, + "node_modules/@reown/appkit-utils/node_modules/@noble/ciphers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.2.1.tgz", + "integrity": "sha512-rONPWMC7PeExE077uLE4oqWrZ1IvAfz3oH9LibVAcVCopJiA9R62uavnbEzdkVmJYI6M6Zgkbeb07+tWjlq2XA==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit-utils/node_modules/@noble/curves": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.1.tgz", + "integrity": "sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.7.1" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit-utils/node_modules/@noble/hashes": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz", + "integrity": "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit-utils/node_modules/@scure/bip32": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.6.2.tgz", + "integrity": "sha512-t96EPDMbtGgtb7onKKqxRLfE5g05k7uHnHRM2xdE6BP/ZmxaLtPek4J4KfVn/90IQNrU1IOAqMgiDtUdtbe3nw==", + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.8.1", + "@noble/hashes": "~1.7.1", + "@scure/base": "~1.2.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit-utils/node_modules/@scure/bip39": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.5.4.tgz", + "integrity": "sha512-TFM4ni0vKvCfBpohoh+/lY05i9gRbSwXWngAsF4CABQxoaOHijxuaZ2R6cStDQ5CHtHO9aGJTr4ksVJASRRyMA==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.7.1", + "@scure/base": "~1.2.4" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit-utils/node_modules/@walletconnect/core": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@walletconnect/core/-/core-2.21.0.tgz", + "integrity": "sha512-o6R7Ua4myxR8aRUAJ1z3gT9nM+jd2B2mfamu6arzy1Cc6vi10fIwFWb6vg3bC8xJ6o9H3n/cN5TOW3aA9Y1XVw==", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-provider": "1.0.14", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/jsonrpc-ws-connection": "1.0.16", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "2.1.2", + "@walletconnect/relay-api": "1.0.11", + "@walletconnect/relay-auth": "1.1.0", + "@walletconnect/safe-json": "1.0.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.21.0", + "@walletconnect/utils": "2.21.0", + "@walletconnect/window-getters": "1.0.1", + "es-toolkit": "1.33.0", + "events": "3.3.0", + "uint8arrays": "3.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@reown/appkit-utils/node_modules/@walletconnect/sign-client": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@walletconnect/sign-client/-/sign-client-2.21.0.tgz", + "integrity": "sha512-z7h+PeLa5Au2R591d/8ZlziE0stJvdzP9jNFzFolf2RG/OiXulgFKum8PrIyXy+Rg2q95U9nRVUF9fWcn78yBA==", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/core": "2.21.0", + "@walletconnect/events": "1.0.1", + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/logger": "2.1.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.21.0", + "@walletconnect/utils": "2.21.0", + "events": "3.3.0" + } + }, + "node_modules/@reown/appkit-utils/node_modules/@walletconnect/types": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-2.21.0.tgz", + "integrity": "sha512-ll+9upzqt95ZBWcfkOszXZkfnpbJJ2CmxMfGgE5GmhdxxxCcO5bGhXkI+x8OpiS555RJ/v/sXJYMSOLkmu4fFw==", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/events": "1.0.1", + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "2.1.2", + "events": "3.3.0" + } + }, + "node_modules/@reown/appkit-utils/node_modules/@walletconnect/universal-provider": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@walletconnect/universal-provider/-/universal-provider-2.21.0.tgz", + "integrity": "sha512-mtUQvewt+X0VBQay/xOJBvxsB3Xsm1lTwFjZ6WUwSOTR1X+FNb71hSApnV5kbsdDIpYPXeQUbGt2se1n5E5UBg==", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/events": "1.0.1", + "@walletconnect/jsonrpc-http-connection": "1.0.8", + "@walletconnect/jsonrpc-provider": "1.0.14", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "2.1.2", + "@walletconnect/sign-client": "2.21.0", + "@walletconnect/types": "2.21.0", + "@walletconnect/utils": "2.21.0", + "es-toolkit": "1.33.0", + "events": "3.3.0" + } + }, + "node_modules/@reown/appkit-utils/node_modules/@walletconnect/utils": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@walletconnect/utils/-/utils-2.21.0.tgz", + "integrity": "sha512-zfHLiUoBrQ8rP57HTPXW7rQMnYxYI4gT9yTACxVW6LhIFROTF6/ytm5SKNoIvi4a5nX5dfXG4D9XwQUCu8Ilig==", + "license": "Apache-2.0", + "dependencies": { + "@noble/ciphers": "1.2.1", + "@noble/curves": "1.8.1", + "@noble/hashes": "1.7.1", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/relay-api": "1.0.11", + "@walletconnect/relay-auth": "1.1.0", + "@walletconnect/safe-json": "1.0.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.21.0", + "@walletconnect/window-getters": "1.0.1", + "@walletconnect/window-metadata": "1.0.1", + "bs58": "6.0.0", + "detect-browser": "5.3.0", + "query-string": "7.1.3", + "uint8arrays": "3.1.0", + "viem": "2.23.2" + } + }, + "node_modules/@reown/appkit-utils/node_modules/@walletconnect/utils/node_modules/viem": { + "version": "2.23.2", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.23.2.tgz", + "integrity": "sha512-NVmW/E0c5crMOtbEAqMF0e3NmvQykFXhLOc/CkLIXOlzHSA6KXVz3CYVmaKqBF8/xtjsjHAGjdJN3Ru1kFJLaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@noble/curves": "1.8.1", + "@noble/hashes": "1.7.1", + "@scure/bip32": "1.6.2", + "@scure/bip39": "1.5.4", + "abitype": "1.0.8", + "isows": "1.0.6", + "ox": "0.6.7", + "ws": "8.18.0" + }, + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@reown/appkit-utils/node_modules/isows": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.6.tgz", + "integrity": "sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/@reown/appkit-utils/node_modules/ox": { + "version": "0.6.7", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.6.7.tgz", + "integrity": "sha512-17Gk/eFsFRAZ80p5eKqv89a57uXjd3NgIf1CaXojATPBuujVc/fQSVhBeAU9JCRB+k7J50WQAyWTxK19T9GgbA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@adraffy/ens-normalize": "^1.10.1", + "@noble/curves": "^1.6.0", + "@noble/hashes": "^1.5.0", + "@scure/bip32": "^1.5.0", + "@scure/bip39": "^1.4.0", + "abitype": "^1.0.6", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@reown/appkit-utils/node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "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/@reown/appkit-wallet": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@reown/appkit-wallet/-/appkit-wallet-1.7.8.tgz", + "integrity": "sha512-kspz32EwHIOT/eg/ZQbFPxgXq0B/olDOj3YMu7gvLEFz4xyOFd/wgzxxAXkp5LbG4Cp++s/elh79rVNmVFdB9A==", + "license": "Apache-2.0", + "dependencies": { + "@reown/appkit-common": "1.7.8", + "@reown/appkit-polyfills": "1.7.8", + "@walletconnect/logger": "2.1.2", + "zod": "3.22.4" + } + }, + "node_modules/@reown/appkit-wallet/node_modules/zod": { + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", + "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@reown/appkit/node_modules/@noble/ciphers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.2.1.tgz", + "integrity": "sha512-rONPWMC7PeExE077uLE4oqWrZ1IvAfz3oH9LibVAcVCopJiA9R62uavnbEzdkVmJYI6M6Zgkbeb07+tWjlq2XA==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit/node_modules/@noble/curves": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.1.tgz", + "integrity": "sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.7.1" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit/node_modules/@noble/hashes": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz", + "integrity": "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit/node_modules/@scure/bip32": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.6.2.tgz", + "integrity": "sha512-t96EPDMbtGgtb7onKKqxRLfE5g05k7uHnHRM2xdE6BP/ZmxaLtPek4J4KfVn/90IQNrU1IOAqMgiDtUdtbe3nw==", + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.8.1", + "@noble/hashes": "~1.7.1", + "@scure/base": "~1.2.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit/node_modules/@scure/bip39": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.5.4.tgz", + "integrity": "sha512-TFM4ni0vKvCfBpohoh+/lY05i9gRbSwXWngAsF4CABQxoaOHijxuaZ2R6cStDQ5CHtHO9aGJTr4ksVJASRRyMA==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.7.1", + "@scure/base": "~1.2.4" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@reown/appkit/node_modules/@walletconnect/core": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@walletconnect/core/-/core-2.21.0.tgz", + "integrity": "sha512-o6R7Ua4myxR8aRUAJ1z3gT9nM+jd2B2mfamu6arzy1Cc6vi10fIwFWb6vg3bC8xJ6o9H3n/cN5TOW3aA9Y1XVw==", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-provider": "1.0.14", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/jsonrpc-ws-connection": "1.0.16", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "2.1.2", + "@walletconnect/relay-api": "1.0.11", + "@walletconnect/relay-auth": "1.1.0", + "@walletconnect/safe-json": "1.0.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.21.0", + "@walletconnect/utils": "2.21.0", + "@walletconnect/window-getters": "1.0.1", + "es-toolkit": "1.33.0", + "events": "3.3.0", + "uint8arrays": "3.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@reown/appkit/node_modules/@walletconnect/sign-client": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@walletconnect/sign-client/-/sign-client-2.21.0.tgz", + "integrity": "sha512-z7h+PeLa5Au2R591d/8ZlziE0stJvdzP9jNFzFolf2RG/OiXulgFKum8PrIyXy+Rg2q95U9nRVUF9fWcn78yBA==", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/core": "2.21.0", + "@walletconnect/events": "1.0.1", + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/logger": "2.1.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.21.0", + "@walletconnect/utils": "2.21.0", + "events": "3.3.0" + } + }, + "node_modules/@reown/appkit/node_modules/@walletconnect/types": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-2.21.0.tgz", + "integrity": "sha512-ll+9upzqt95ZBWcfkOszXZkfnpbJJ2CmxMfGgE5GmhdxxxCcO5bGhXkI+x8OpiS555RJ/v/sXJYMSOLkmu4fFw==", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/events": "1.0.1", + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "2.1.2", + "events": "3.3.0" + } + }, + "node_modules/@reown/appkit/node_modules/@walletconnect/universal-provider": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@walletconnect/universal-provider/-/universal-provider-2.21.0.tgz", + "integrity": "sha512-mtUQvewt+X0VBQay/xOJBvxsB3Xsm1lTwFjZ6WUwSOTR1X+FNb71hSApnV5kbsdDIpYPXeQUbGt2se1n5E5UBg==", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/events": "1.0.1", + "@walletconnect/jsonrpc-http-connection": "1.0.8", + "@walletconnect/jsonrpc-provider": "1.0.14", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "2.1.2", + "@walletconnect/sign-client": "2.21.0", + "@walletconnect/types": "2.21.0", + "@walletconnect/utils": "2.21.0", + "es-toolkit": "1.33.0", + "events": "3.3.0" + } + }, + "node_modules/@reown/appkit/node_modules/@walletconnect/utils": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@walletconnect/utils/-/utils-2.21.0.tgz", + "integrity": "sha512-zfHLiUoBrQ8rP57HTPXW7rQMnYxYI4gT9yTACxVW6LhIFROTF6/ytm5SKNoIvi4a5nX5dfXG4D9XwQUCu8Ilig==", + "license": "Apache-2.0", + "dependencies": { + "@noble/ciphers": "1.2.1", + "@noble/curves": "1.8.1", + "@noble/hashes": "1.7.1", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/relay-api": "1.0.11", + "@walletconnect/relay-auth": "1.1.0", + "@walletconnect/safe-json": "1.0.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.21.0", + "@walletconnect/window-getters": "1.0.1", + "@walletconnect/window-metadata": "1.0.1", + "bs58": "6.0.0", + "detect-browser": "5.3.0", + "query-string": "7.1.3", + "uint8arrays": "3.1.0", + "viem": "2.23.2" + } + }, + "node_modules/@reown/appkit/node_modules/@walletconnect/utils/node_modules/viem": { + "version": "2.23.2", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.23.2.tgz", + "integrity": "sha512-NVmW/E0c5crMOtbEAqMF0e3NmvQykFXhLOc/CkLIXOlzHSA6KXVz3CYVmaKqBF8/xtjsjHAGjdJN3Ru1kFJLaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@noble/curves": "1.8.1", + "@noble/hashes": "1.7.1", + "@scure/bip32": "1.6.2", + "@scure/bip39": "1.5.4", + "abitype": "1.0.8", + "isows": "1.0.6", + "ox": "0.6.7", + "ws": "8.18.0" + }, + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@reown/appkit/node_modules/isows": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.6.tgz", + "integrity": "sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/@reown/appkit/node_modules/ox": { + "version": "0.6.7", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.6.7.tgz", + "integrity": "sha512-17Gk/eFsFRAZ80p5eKqv89a57uXjd3NgIf1CaXojATPBuujVc/fQSVhBeAU9JCRB+k7J50WQAyWTxK19T9GgbA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@adraffy/ens-normalize": "^1.10.1", + "@noble/curves": "^1.6.0", + "@noble/hashes": "^1.5.0", + "@scure/bip32": "^1.5.0", + "@scure/bip39": "^1.4.0", + "abitype": "^1.0.6", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@reown/appkit/node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "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/@rollup/plugin-commonjs": { + "version": "28.0.6", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.6.tgz", + "integrity": "sha512-XSQB1K7FUU5QP+3lOQmVCE3I0FcbbNvmNT4VJSj93iUjayaARrTQeoRdiYQoftAJBLrR9t2agwAd3ekaTgHNlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "commondir": "^1.0.1", + "estree-walker": "^2.0.2", + "fdir": "^6.2.0", + "is-reference": "1.2.1", + "magic-string": "^0.30.3", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=16.0.0 || 14 >= 14.17" + }, + "peerDependencies": { + "rollup": "^2.68.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-commonjs/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/plugin-json": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.1.0.tgz", + "integrity": "sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.1.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-16.0.1.tgz", + "integrity": "sha512-tk5YCxJWIG81umIvNkSod2qK5KyQW19qcBF/B78n1bjtOON6gzKoVeSzAE8yHCZEDmqkHKkxplExA8KzdJLJpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.78.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-typescript": { + "version": "12.1.4", + "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-12.1.4.tgz", + "integrity": "sha512-s5Hx+EtN60LMlDBvl5f04bEiFZmAepk27Q+mr85L/00zPDn1jtzlTV6FWn81MaIwqfWzKxmOJrBWHU6vtQyedQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.1.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.14.0||^3.0.0||^4.0.0", + "tslib": "*", + "typescript": ">=3.7.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + }, + "tslib": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", + "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.50.2.tgz", + "integrity": "sha512-uLN8NAiFVIRKX9ZQha8wy6UUs06UNSZ32xj6giK/rmMXAgKahwExvK6SsmgU5/brh4w/nSgj8e0k3c1HBQpa0A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.50.2.tgz", + "integrity": "sha512-oEouqQk2/zxxj22PNcGSskya+3kV0ZKH+nQxuCCOGJ4oTXBdNTbv+f/E3c74cNLeMO1S5wVWacSws10TTSB77g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.40.2", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.2.tgz", + "integrity": "sha512-47N4hxa01a4x6XnJoskMKTS8XZ0CZMd8YTbINbi+w03A2w4j1RTlnGHOz/P0+Bg1LaVL6ufZyNprSg+fW5nYQQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.50.2.tgz", + "integrity": "sha512-QkzxvH3kYN9J1w7D1A+yIMdI1pPekD+pWx7G5rXgnIlQ1TVYVC6hLl7SOV9pi5q9uIDF9AuIGkuzcbF7+fAhow==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.50.2.tgz", + "integrity": "sha512-dkYXB0c2XAS3a3jmyDkX4Jk0m7gWLFzq1C3qUnJJ38AyxIF5G/dyS4N9B30nvFseCfgtCEdbYFhk0ChoCGxPog==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.50.2.tgz", + "integrity": "sha512-9VlPY/BN3AgbukfVHAB8zNFWB/lKEuvzRo1NKev0Po8sYFKx0i+AQlCYftgEjcL43F2h9Ui1ZSdVBc4En/sP2w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.50.2.tgz", + "integrity": "sha512-+GdKWOvsifaYNlIVf07QYan1J5F141+vGm5/Y8b9uCZnG/nxoGqgCmR24mv0koIWWuqvFYnbURRqw1lv7IBINw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.2.tgz", + "integrity": "sha512-KlE8IC0HFOC33taNt1zR8qNlBYHj31qGT1UqWqtvR/+NuCVhfufAq9fxO8BMFC22Wu0rxOwGVWxtCMvZVLmhQg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.2.tgz", + "integrity": "sha512-j8CgxvfM0kbnhu4XgjnCWJQyyBOeBI1Zq91Z850aUddUmPeQvuAy6OiMdPS46gNFgy8gN1xkYyLgwLYZG3rBOg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.50.2.tgz", + "integrity": "sha512-OL6KaNvBopLlj5fTa5D5bau4W82f+1TyTZRr2BdnfsrnQnmdxh4okMxR2DcDkJuh4KeoQZVuvHvzuD/lyLn2Kw==", + "cpu": [ + "loong64" + ], + "dev": true, "license": "MIT", "optional": true, "os": [ - "android" + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.50.2.tgz", + "integrity": "sha512-I21VJl1w6z/K5OTRl6aS9DDsqezEZ/yKpbqlvfHbW0CEF5IL8ATBMuUx6/mp683rKTK8thjs/0BaNrZLXetLag==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.50.2.tgz", + "integrity": "sha512-Hq6aQJT/qFFHrYMjS20nV+9SKrXL2lvFBENZoKfoTH2kKDOJqff5OSJr4x72ZaG/uUn+XmBnGhfr4lwMRrmqCQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.50.2.tgz", + "integrity": "sha512-82rBSEXRv5qtKyr0xZ/YMF531oj2AIpLZkeNYxmKNN6I2sVE9PGegN99tYDLK2fYHJITL1P2Lgb4ZXnv0PjQvw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.50.2.tgz", + "integrity": "sha512-4Q3S3Hy7pC6uaRo9gtXUTJ+EKo9AKs3BXKc2jYypEcMQ49gDPFU2P1ariX9SEtBzE5egIX6fSUmbmGazwBVF9w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.2.tgz", + "integrity": "sha512-lG7Xa+BmBNwpjmVUbmyKxdQJ3Q6whHjMjzQplOs5Z+Gj7mxPtWakGHqzMqNER68G67kmCX9qX57aRsW5V0VOng==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.2.tgz", + "integrity": "sha512-tD46wKHd+KJvsmije4bUskNuvWKFcTOIM9tZ/RrmIvcXnbi0YK/cKS9FzFtAm7Oxi2EhV5N2OpfFB348vSQRXA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.50.2.tgz", + "integrity": "sha512-nMKvq6FRHSzYfKLHZ+cChowlEkR2lj/V0jYj9JnGUVPL2/mIeFGmVM2mLaFeNa5Jev7W7TovXqXIG2d39y1KYA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.50.2.tgz", + "integrity": "sha512-eFUvvnTYEKeTyHEijQKz81bLrUQOXKZqECeiWH6tb8eXXbZk+CXSG2aFrig2BQ/pjiVRj36zysjgILkqarS2YA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.50.2.tgz", + "integrity": "sha512-cBaWmXqyfRhH8zmUxK3d3sAhEWLrtMjWBRwdMMHJIXSjvjLKvv49adxiEz+FJ8AP90apSDDBx2Tyd/WylV6ikA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.2.tgz", + "integrity": "sha512-bwspbWB04XJpeElvsp+DCylKfF4trJDa2Y9Go8O6A7YLX2LIKGcNK/CYImJN6ZP4DcuOHB4Utl3iCbnR62DudA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" ] }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.40.2", - "cpu": [ - "arm64" - ], + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@safe-global/safe-apps-provider": { + "version": "0.18.6", + "resolved": "https://registry.npmjs.org/@safe-global/safe-apps-provider/-/safe-apps-provider-0.18.6.tgz", + "integrity": "sha512-4LhMmjPWlIO8TTDC2AwLk44XKXaK6hfBTWyljDm0HQ6TWlOEijVWNrt2s3OCVMSxlXAcEzYfqyu1daHZooTC2Q==", + "license": "MIT", + "dependencies": { + "@safe-global/safe-apps-sdk": "^9.1.0", + "events": "^3.3.0" + } + }, + "node_modules/@safe-global/safe-apps-sdk": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@safe-global/safe-apps-sdk/-/safe-apps-sdk-9.1.0.tgz", + "integrity": "sha512-N5p/ulfnnA2Pi2M3YeWjULeWbjo7ei22JwU/IXnhoHzKq3pYCN6ynL9mJBOlvDVv892EgLPCWCOwQk/uBT2v0Q==", + "license": "MIT", + "dependencies": { + "@safe-global/safe-gateway-typescript-sdk": "^3.5.3", + "viem": "^2.1.1" + } + }, + "node_modules/@safe-global/safe-gateway-typescript-sdk": { + "version": "3.23.1", + "resolved": "https://registry.npmjs.org/@safe-global/safe-gateway-typescript-sdk/-/safe-gateway-typescript-sdk-3.23.1.tgz", + "integrity": "sha512-6ORQfwtEJYpalCeVO21L4XXGSdbEMfyp2hEv6cP82afKXSwvse6d3sdelgaPWUxHIsFRkWvHDdzh8IyyKHZKxw==", + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/@scure/base": { + "version": "1.2.6", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32": { + "version": "1.7.0", + "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", + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.8.0", + "@scure/base": "~1.2.5" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "license": "MIT", + "peer": true + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "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-program/compute-budget": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@solana-program/compute-budget/-/compute-budget-0.8.0.tgz", + "integrity": "sha512-qPKxdxaEsFxebZ4K5RPuy7VQIm/tfJLa1+Nlt3KNA8EYQkz9Xm8htdoEaXVrer9kpgzzp9R3I3Bh6omwCM06tQ==", + "license": "Apache-2.0", + "peerDependencies": { + "@solana/kit": "^2.1.0" + } + }, + "node_modules/@solana-program/token": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@solana-program/token/-/token-0.5.1.tgz", + "integrity": "sha512-bJvynW5q9SFuVOZ5vqGVkmaPGA0MCC+m9jgJj1nk5m20I389/ms69ASnhWGoOPNcie7S9OwBX0gTj2fiyWpfag==", + "license": "Apache-2.0", + "peerDependencies": { + "@solana/kit": "^2.1.0" + } + }, + "node_modules/@solana-program/token-2022": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@solana-program/token-2022/-/token-2022-0.4.2.tgz", + "integrity": "sha512-zIpR5t4s9qEU3hZKupzIBxJ6nUV5/UVyIT400tu9vT1HMs5JHxaTTsb5GUhYjiiTvNwU0MQavbwc4Dl29L0Xvw==", + "license": "Apache-2.0", + "peerDependencies": { + "@solana/kit": "^2.1.0", + "@solana/sysvars": "^2.1.0" + } + }, + "node_modules/@solana/accounts": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/accounts/-/accounts-2.3.0.tgz", + "integrity": "sha512-QgQTj404Z6PXNOyzaOpSzjgMOuGwG8vC66jSDB+3zHaRcEPRVRd2sVSrd1U6sHtnV3aiaS6YyDuPQMheg4K2jw==", + "license": "MIT", + "dependencies": { + "@solana/addresses": "2.3.0", + "@solana/codecs-core": "2.3.0", + "@solana/codecs-strings": "2.3.0", + "@solana/errors": "2.3.0", + "@solana/rpc-spec": "2.3.0", + "@solana/rpc-types": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/accounts/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/accounts/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/accounts/node_modules/@solana/codecs-strings": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-strings/-/codecs-strings-2.3.0.tgz", + "integrity": "sha512-y5pSBYwzVziXu521hh+VxqUtp0hYGTl1eWGoc1W+8mdvBdC1kTqm/X7aYQw33J42hw03JjryvYOvmGgk3Qz/Ug==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "fastestsmallesttextencoderdecoder": "^1.0.22", + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/accounts/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/accounts/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/addresses": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/addresses/-/addresses-2.3.0.tgz", + "integrity": "sha512-ypTNkY2ZaRFpHLnHAgaW8a83N0/WoqdFvCqf4CQmnMdFsZSdC7qOwcbd7YzdaQn9dy+P2hybewzB+KP7LutxGA==", + "license": "MIT", + "dependencies": { + "@solana/assertions": "2.3.0", + "@solana/codecs-core": "2.3.0", + "@solana/codecs-strings": "2.3.0", + "@solana/errors": "2.3.0", + "@solana/nominal-types": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/addresses/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/addresses/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/addresses/node_modules/@solana/codecs-strings": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-strings/-/codecs-strings-2.3.0.tgz", + "integrity": "sha512-y5pSBYwzVziXu521hh+VxqUtp0hYGTl1eWGoc1W+8mdvBdC1kTqm/X7aYQw33J42hw03JjryvYOvmGgk3Qz/Ug==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "fastestsmallesttextencoderdecoder": "^1.0.22", + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/addresses/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/addresses/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/assertions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/assertions/-/assertions-2.3.0.tgz", + "integrity": "sha512-Ekoet3khNg3XFLN7MIz8W31wPQISpKUGDGTylLptI+JjCDWx3PIa88xjEMqFo02WJ8sBj2NLV64Xg1sBcsHjZQ==", + "license": "MIT", + "dependencies": { + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/assertions/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/assertions/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/buffer-layout": { + "version": "4.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "~6.0.3" + }, + "engines": { + "node": ">=5.10" + } + }, + "node_modules/@solana/buffer-layout-utils": { + "version": "0.2.0", + "dev": true, + "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", + "dev": true, + "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.0.0-rc.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@solana/errors": "2.0.0-rc.1" + }, + "peerDependencies": { + "typescript": ">=5" + } + }, + "node_modules/@solana/codecs-data-structures": { + "version": "2.0.0-rc.1", + "dev": true, + "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-numbers": { + "version": "2.0.0-rc.1", + "dev": true, + "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": { + "version": "2.0.0-rc.1", + "dev": true, + "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/errors": { + "version": "2.0.0-rc.1", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "commander": "^12.1.0" + }, + "bin": { + "errors": "bin/cli.mjs" + }, + "peerDependencies": { + "typescript": ">=5" + } + }, + "node_modules/@solana/fast-stable-stringify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/fast-stable-stringify/-/fast-stable-stringify-2.3.0.tgz", + "integrity": "sha512-KfJPrMEieUg6D3hfQACoPy0ukrAV8Kio883llt/8chPEG3FVTX9z/Zuf4O01a15xZmBbmQ7toil2Dp0sxMJSxw==", + "license": "MIT", + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/functional": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/functional/-/functional-2.3.0.tgz", + "integrity": "sha512-AgsPh3W3tE+nK3eEw/W9qiSfTGwLYEvl0rWaxHht/lRcuDVwfKRzeSa5G79eioWFFqr+pTtoCr3D3OLkwKz02Q==", + "license": "MIT", + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/instructions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/instructions/-/instructions-2.3.0.tgz", + "integrity": "sha512-PLMsmaIKu7hEAzyElrk2T7JJx4D+9eRwebhFZpy2PXziNSmFF929eRHKUsKqBFM3cYR1Yy3m6roBZfA+bGE/oQ==", + "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/instructions/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/instructions/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/instructions/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/keys": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/keys/-/keys-2.3.0.tgz", + "integrity": "sha512-ZVVdga79pNH+2pVcm6fr2sWz9HTwfopDVhYb0Lh3dh+WBmJjwkabXEIHey2rUES7NjFa/G7sV8lrUn/v8LDCCQ==", + "license": "MIT", + "dependencies": { + "@solana/assertions": "2.3.0", + "@solana/codecs-core": "2.3.0", + "@solana/codecs-strings": "2.3.0", + "@solana/errors": "2.3.0", + "@solana/nominal-types": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/keys/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/keys/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/keys/node_modules/@solana/codecs-strings": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-strings/-/codecs-strings-2.3.0.tgz", + "integrity": "sha512-y5pSBYwzVziXu521hh+VxqUtp0hYGTl1eWGoc1W+8mdvBdC1kTqm/X7aYQw33J42hw03JjryvYOvmGgk3Qz/Ug==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "fastestsmallesttextencoderdecoder": "^1.0.22", + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/keys/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/keys/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/kit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/kit/-/kit-2.3.0.tgz", + "integrity": "sha512-sb6PgwoW2LjE5oTFu4lhlS/cGt/NB3YrShEyx7JgWFWysfgLdJnhwWThgwy/4HjNsmtMrQGWVls0yVBHcMvlMQ==", + "license": "MIT", + "dependencies": { + "@solana/accounts": "2.3.0", + "@solana/addresses": "2.3.0", + "@solana/codecs": "2.3.0", + "@solana/errors": "2.3.0", + "@solana/functional": "2.3.0", + "@solana/instructions": "2.3.0", + "@solana/keys": "2.3.0", + "@solana/programs": "2.3.0", + "@solana/rpc": "2.3.0", + "@solana/rpc-parsed-types": "2.3.0", + "@solana/rpc-spec-types": "2.3.0", + "@solana/rpc-subscriptions": "2.3.0", + "@solana/rpc-types": "2.3.0", + "@solana/signers": "2.3.0", + "@solana/sysvars": "2.3.0", + "@solana/transaction-confirmation": "2.3.0", + "@solana/transaction-messages": "2.3.0", + "@solana/transactions": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/kit/node_modules/@solana/codecs": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs/-/codecs-2.3.0.tgz", + "integrity": "sha512-JVqGPkzoeyU262hJGdH64kNLH0M+Oew2CIPOa/9tR3++q2pEd4jU2Rxdfye9sd0Ce3XJrR5AIa8ZfbyQXzjh+g==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-data-structures": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/codecs-strings": "2.3.0", + "@solana/options": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/kit/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/kit/node_modules/@solana/codecs-data-structures": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-data-structures/-/codecs-data-structures-2.3.0.tgz", + "integrity": "sha512-qvU5LE5DqEdYMYgELRHv+HMOx73sSoV1ZZkwIrclwUmwTbTaH8QAJURBj0RhQ/zCne7VuLLOZFFGv6jGigWhSw==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/kit/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/kit/node_modules/@solana/codecs-strings": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-strings/-/codecs-strings-2.3.0.tgz", + "integrity": "sha512-y5pSBYwzVziXu521hh+VxqUtp0hYGTl1eWGoc1W+8mdvBdC1kTqm/X7aYQw33J42hw03JjryvYOvmGgk3Qz/Ug==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "fastestsmallesttextencoderdecoder": "^1.0.22", + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/kit/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/kit/node_modules/@solana/options": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/options/-/options-2.3.0.tgz", + "integrity": "sha512-PPnnZBRCWWoZQ11exPxf//DRzN2C6AoFsDI/u2AsQfYih434/7Kp4XLpfOMT/XESi+gdBMFNNfbES5zg3wAIkw==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-data-structures": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/codecs-strings": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/kit/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/nominal-types": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/nominal-types/-/nominal-types-2.3.0.tgz", + "integrity": "sha512-uKlMnlP4PWW5UTXlhKM8lcgIaNj8dvd8xO4Y9l+FVvh9RvW2TO0GwUO6JCo7JBzCB0PSqRJdWWaQ8pu1Ti/OkA==", + "license": "MIT", + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/options": { + "version": "2.0.0-rc.1", + "dev": true, + "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/pay": { + "version": "0.2.6", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@solana/qr-code-styling": "^1.6.0", + "@solana/spl-token": "^0.4.13", + "@solana/web3.js": "^1.98.2", + "bignumber.js": "^9.1.0", + "cross-fetch": "^3.1.5", + "js-base64": "^3.7.2", + "tweetnacl": "^1.0.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@solana/programs": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/programs/-/programs-2.3.0.tgz", + "integrity": "sha512-UXKujV71VCI5uPs+cFdwxybtHZAIZyQkqDiDnmK+DawtOO9mBn4Nimdb/6RjR2CXT78mzO9ZCZ3qfyX+ydcB7w==", + "license": "MIT", + "dependencies": { + "@solana/addresses": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/programs/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/programs/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/promises": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/promises/-/promises-2.3.0.tgz", + "integrity": "sha512-GjVgutZKXVuojd9rWy1PuLnfcRfqsaCm7InCiZc8bqmJpoghlyluweNc7ml9Y5yQn1P2IOyzh9+p/77vIyNybQ==", + "license": "MIT", + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/qr-code-styling": { + "version": "1.6.0", + "dev": true, + "license": "MIT", + "dependencies": { + "qrcode-generator": "^1.4.3" + } + }, + "node_modules/@solana/rpc": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/rpc/-/rpc-2.3.0.tgz", + "integrity": "sha512-ZWN76iNQAOCpYC7yKfb3UNLIMZf603JckLKOOLTHuy9MZnTN8XV6uwvDFhf42XvhglgUjGCEnbUqWtxQ9pa/pQ==", + "license": "MIT", + "dependencies": { + "@solana/errors": "2.3.0", + "@solana/fast-stable-stringify": "2.3.0", + "@solana/functional": "2.3.0", + "@solana/rpc-api": "2.3.0", + "@solana/rpc-spec": "2.3.0", + "@solana/rpc-spec-types": "2.3.0", + "@solana/rpc-transformers": "2.3.0", + "@solana/rpc-transport-http": "2.3.0", + "@solana/rpc-types": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/rpc-api": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/rpc-api/-/rpc-api-2.3.0.tgz", + "integrity": "sha512-UUdiRfWoyYhJL9PPvFeJr4aJ554ob2jXcpn4vKmRVn9ire0sCbpQKYx6K8eEKHZWXKrDW8IDspgTl0gT/aJWVg==", + "license": "MIT", + "dependencies": { + "@solana/addresses": "2.3.0", + "@solana/codecs-core": "2.3.0", + "@solana/codecs-strings": "2.3.0", + "@solana/errors": "2.3.0", + "@solana/keys": "2.3.0", + "@solana/rpc-parsed-types": "2.3.0", + "@solana/rpc-spec": "2.3.0", + "@solana/rpc-transformers": "2.3.0", + "@solana/rpc-types": "2.3.0", + "@solana/transaction-messages": "2.3.0", + "@solana/transactions": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/rpc-api/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/rpc-api/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/rpc-api/node_modules/@solana/codecs-strings": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-strings/-/codecs-strings-2.3.0.tgz", + "integrity": "sha512-y5pSBYwzVziXu521hh+VxqUtp0hYGTl1eWGoc1W+8mdvBdC1kTqm/X7aYQw33J42hw03JjryvYOvmGgk3Qz/Ug==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "fastestsmallesttextencoderdecoder": "^1.0.22", + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/rpc-api/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/rpc-api/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/rpc-parsed-types": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/rpc-parsed-types/-/rpc-parsed-types-2.3.0.tgz", + "integrity": "sha512-B5pHzyEIbBJf9KHej+zdr5ZNAdSvu7WLU2lOUPh81KHdHQs6dEb310LGxcpCc7HVE8IEdO20AbckewDiAN6OCg==", + "license": "MIT", + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/rpc-spec": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/rpc-spec/-/rpc-spec-2.3.0.tgz", + "integrity": "sha512-fA2LMX4BMixCrNB2n6T83AvjZ3oUQTu7qyPLyt8gHQaoEAXs8k6GZmu6iYcr+FboQCjUmRPgMaABbcr9j2J9Sw==", + "license": "MIT", + "dependencies": { + "@solana/errors": "2.3.0", + "@solana/rpc-spec-types": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/rpc-spec-types": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/rpc-spec-types/-/rpc-spec-types-2.3.0.tgz", + "integrity": "sha512-xQsb65lahjr8Wc9dMtP7xa0ZmDS8dOE2ncYjlvfyw/h4mpdXTUdrSMi6RtFwX33/rGuztQ7Hwaid5xLNSLvsFQ==", + "license": "MIT", + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/rpc-spec/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/rpc-spec/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/rpc-subscriptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/rpc-subscriptions/-/rpc-subscriptions-2.3.0.tgz", + "integrity": "sha512-Uyr10nZKGVzvCOqwCZgwYrzuoDyUdwtgQRefh13pXIrdo4wYjVmoLykH49Omt6abwStB0a4UL5gX9V4mFdDJZg==", + "license": "MIT", + "dependencies": { + "@solana/errors": "2.3.0", + "@solana/fast-stable-stringify": "2.3.0", + "@solana/functional": "2.3.0", + "@solana/promises": "2.3.0", + "@solana/rpc-spec-types": "2.3.0", + "@solana/rpc-subscriptions-api": "2.3.0", + "@solana/rpc-subscriptions-channel-websocket": "2.3.0", + "@solana/rpc-subscriptions-spec": "2.3.0", + "@solana/rpc-transformers": "2.3.0", + "@solana/rpc-types": "2.3.0", + "@solana/subscribable": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/rpc-subscriptions-api": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/rpc-subscriptions-api/-/rpc-subscriptions-api-2.3.0.tgz", + "integrity": "sha512-9mCjVbum2Hg9KGX3LKsrI5Xs0KX390lS+Z8qB80bxhar6MJPugqIPH8uRgLhCW9GN3JprAfjRNl7our8CPvsPQ==", + "license": "MIT", + "dependencies": { + "@solana/addresses": "2.3.0", + "@solana/keys": "2.3.0", + "@solana/rpc-subscriptions-spec": "2.3.0", + "@solana/rpc-transformers": "2.3.0", + "@solana/rpc-types": "2.3.0", + "@solana/transaction-messages": "2.3.0", + "@solana/transactions": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/rpc-subscriptions-spec": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/rpc-subscriptions-spec/-/rpc-subscriptions-spec-2.3.0.tgz", + "integrity": "sha512-rdmVcl4PvNKQeA2l8DorIeALCgJEMSu7U8AXJS1PICeb2lQuMeaR+6cs/iowjvIB0lMVjYN2sFf6Q3dJPu6wWg==", + "license": "MIT", + "dependencies": { + "@solana/errors": "2.3.0", + "@solana/promises": "2.3.0", + "@solana/rpc-spec-types": "2.3.0", + "@solana/subscribable": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/rpc-subscriptions-spec/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/rpc-subscriptions-spec/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/rpc-subscriptions/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/rpc-subscriptions/node_modules/@solana/rpc-subscriptions-channel-websocket": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/rpc-subscriptions-channel-websocket/-/rpc-subscriptions-channel-websocket-2.3.0.tgz", + "integrity": "sha512-2oL6ceFwejIgeWzbNiUHI2tZZnaOxNTSerszcin7wYQwijxtpVgUHiuItM/Y70DQmH9sKhmikQp+dqeGalaJxw==", + "license": "MIT", + "dependencies": { + "@solana/errors": "2.3.0", + "@solana/functional": "2.3.0", + "@solana/rpc-subscriptions-spec": "2.3.0", + "@solana/subscribable": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3", + "ws": "^8.18.0" + } + }, + "node_modules/@solana/rpc-subscriptions/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/rpc-subscriptions/node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/@solana/rpc-transformers": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/rpc-transformers/-/rpc-transformers-2.3.0.tgz", + "integrity": "sha512-UuHYK3XEpo9nMXdjyGKkPCOr7WsZsxs7zLYDO1A5ELH3P3JoehvrDegYRAGzBS2VKsfApZ86ZpJToP0K3PhmMA==", + "license": "MIT", + "dependencies": { + "@solana/errors": "2.3.0", + "@solana/functional": "2.3.0", + "@solana/nominal-types": "2.3.0", + "@solana/rpc-spec-types": "2.3.0", + "@solana/rpc-types": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/rpc-transformers/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/rpc-transformers/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/rpc-transport-http": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/rpc-transport-http/-/rpc-transport-http-2.3.0.tgz", + "integrity": "sha512-HFKydmxGw8nAF5N+S0NLnPBDCe5oMDtI2RAmW8DMqP4U3Zxt2XWhvV1SNkAldT5tF0U1vP+is6fHxyhk4xqEvg==", + "license": "MIT", + "dependencies": { + "@solana/errors": "2.3.0", + "@solana/rpc-spec": "2.3.0", + "@solana/rpc-spec-types": "2.3.0", + "undici-types": "^7.11.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/rpc-transport-http/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/rpc-transport-http/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/rpc-transport-http/node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "license": "MIT" + }, + "node_modules/@solana/rpc-types": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/rpc-types/-/rpc-types-2.3.0.tgz", + "integrity": "sha512-O09YX2hED2QUyGxrMOxQ9GzH1LlEwwZWu69QbL4oYmIf6P5dzEEHcqRY6L1LsDVqc/dzAdEs/E1FaPrcIaIIPw==", + "license": "MIT", + "dependencies": { + "@solana/addresses": "2.3.0", + "@solana/codecs-core": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/codecs-strings": "2.3.0", + "@solana/errors": "2.3.0", + "@solana/nominal-types": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/rpc-types/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/rpc-types/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/rpc-types/node_modules/@solana/codecs-strings": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-strings/-/codecs-strings-2.3.0.tgz", + "integrity": "sha512-y5pSBYwzVziXu521hh+VxqUtp0hYGTl1eWGoc1W+8mdvBdC1kTqm/X7aYQw33J42hw03JjryvYOvmGgk3Qz/Ug==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "fastestsmallesttextencoderdecoder": "^1.0.22", + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/rpc-types/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/rpc-types/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/rpc/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/rpc/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/signers": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/signers/-/signers-2.3.0.tgz", + "integrity": "sha512-OSv6fGr/MFRx6J+ZChQMRqKNPGGmdjkqarKkRzkwmv7v8quWsIRnJT5EV8tBy3LI4DLO/A8vKiNSPzvm1TdaiQ==", + "license": "MIT", + "dependencies": { + "@solana/addresses": "2.3.0", + "@solana/codecs-core": "2.3.0", + "@solana/errors": "2.3.0", + "@solana/instructions": "2.3.0", + "@solana/keys": "2.3.0", + "@solana/nominal-types": "2.3.0", + "@solana/transaction-messages": "2.3.0", + "@solana/transactions": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/signers/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/signers/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/signers/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/spl-token": { + "version": "0.4.13", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@solana/buffer-layout": "^4.0.0", + "@solana/buffer-layout-utils": "^0.2.0", + "@solana/spl-token-group": "^0.0.7", + "@solana/spl-token-metadata": "^0.1.6", + "buffer": "^6.0.3" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@solana/web3.js": "^1.95.5" + } + }, + "node_modules/@solana/spl-token-group": { + "version": "0.0.7", + "dev": true, + "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/spl-token-metadata": { + "version": "0.1.6", + "dev": true, + "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/subscribable": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/subscribable/-/subscribable-2.3.0.tgz", + "integrity": "sha512-DkgohEDbMkdTWiKAoatY02Njr56WXx9e/dKKfmne8/Ad6/2llUIrax78nCdlvZW9quXMaXPTxZvdQqo9N669Og==", + "license": "MIT", + "dependencies": { + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/subscribable/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/subscribable/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/sysvars": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/sysvars/-/sysvars-2.3.0.tgz", + "integrity": "sha512-LvjADZrpZ+CnhlHqfI5cmsRzX9Rpyb1Ox2dMHnbsRNzeKAMhu9w4ZBIaeTdO322zsTr509G1B+k2ABD3whvUBA==", + "license": "MIT", + "dependencies": { + "@solana/accounts": "2.3.0", + "@solana/codecs": "2.3.0", + "@solana/errors": "2.3.0", + "@solana/rpc-types": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/sysvars/node_modules/@solana/codecs": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs/-/codecs-2.3.0.tgz", + "integrity": "sha512-JVqGPkzoeyU262hJGdH64kNLH0M+Oew2CIPOa/9tR3++q2pEd4jU2Rxdfye9sd0Ce3XJrR5AIa8ZfbyQXzjh+g==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-data-structures": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/codecs-strings": "2.3.0", + "@solana/options": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/sysvars/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/sysvars/node_modules/@solana/codecs-data-structures": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-data-structures/-/codecs-data-structures-2.3.0.tgz", + "integrity": "sha512-qvU5LE5DqEdYMYgELRHv+HMOx73sSoV1ZZkwIrclwUmwTbTaH8QAJURBj0RhQ/zCne7VuLLOZFFGv6jGigWhSw==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/sysvars/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/sysvars/node_modules/@solana/codecs-strings": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-strings/-/codecs-strings-2.3.0.tgz", + "integrity": "sha512-y5pSBYwzVziXu521hh+VxqUtp0hYGTl1eWGoc1W+8mdvBdC1kTqm/X7aYQw33J42hw03JjryvYOvmGgk3Qz/Ug==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "fastestsmallesttextencoderdecoder": "^1.0.22", + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/sysvars/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/sysvars/node_modules/@solana/options": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/options/-/options-2.3.0.tgz", + "integrity": "sha512-PPnnZBRCWWoZQ11exPxf//DRzN2C6AoFsDI/u2AsQfYih434/7Kp4XLpfOMT/XESi+gdBMFNNfbES5zg3wAIkw==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-data-structures": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/codecs-strings": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/sysvars/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] + "engines": { + "node": ">=20" + } }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.2.tgz", - "integrity": "sha512-47N4hxa01a4x6XnJoskMKTS8XZ0CZMd8YTbINbi+w03A2w4j1RTlnGHOz/P0+Bg1LaVL6ufZyNprSg+fW5nYQQ==", - "cpu": [ - "x64" - ], + "node_modules/@solana/transaction-confirmation": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/transaction-confirmation/-/transaction-confirmation-2.3.0.tgz", + "integrity": "sha512-UiEuiHCfAAZEKdfne/XljFNJbsKAe701UQHKXEInYzIgBjRbvaeYZlBmkkqtxwcasgBTOmEaEKT44J14N9VZDw==", "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] + "dependencies": { + "@solana/addresses": "2.3.0", + "@solana/codecs-strings": "2.3.0", + "@solana/errors": "2.3.0", + "@solana/keys": "2.3.0", + "@solana/promises": "2.3.0", + "@solana/rpc": "2.3.0", + "@solana/rpc-subscriptions": "2.3.0", + "@solana/rpc-types": "2.3.0", + "@solana/transaction-messages": "2.3.0", + "@solana/transactions": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.50.2.tgz", - "integrity": "sha512-QkzxvH3kYN9J1w7D1A+yIMdI1pPekD+pWx7G5rXgnIlQ1TVYVC6hLl7SOV9pi5q9uIDF9AuIGkuzcbF7+fAhow==", - "cpu": [ - "arm64" - ], + "node_modules/@solana/transaction-confirmation/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/transaction-confirmation/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/transaction-confirmation/node_modules/@solana/codecs-strings": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-strings/-/codecs-strings-2.3.0.tgz", + "integrity": "sha512-y5pSBYwzVziXu521hh+VxqUtp0hYGTl1eWGoc1W+8mdvBdC1kTqm/X7aYQw33J42hw03JjryvYOvmGgk3Qz/Ug==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "fastestsmallesttextencoderdecoder": "^1.0.22", + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/transaction-confirmation/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/transaction-confirmation/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/transaction-messages": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/transaction-messages/-/transaction-messages-2.3.0.tgz", + "integrity": "sha512-bgqvWuy3MqKS5JdNLH649q+ngiyOu5rGS3DizSnWwYUd76RxZl1kN6CoqHSrrMzFMvis6sck/yPGG3wqrMlAww==", + "license": "MIT", + "dependencies": { + "@solana/addresses": "2.3.0", + "@solana/codecs-core": "2.3.0", + "@solana/codecs-data-structures": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/errors": "2.3.0", + "@solana/functional": "2.3.0", + "@solana/instructions": "2.3.0", + "@solana/nominal-types": "2.3.0", + "@solana/rpc-types": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/transaction-messages/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/transaction-messages/node_modules/@solana/codecs-data-structures": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-data-structures/-/codecs-data-structures-2.3.0.tgz", + "integrity": "sha512-qvU5LE5DqEdYMYgELRHv+HMOx73sSoV1ZZkwIrclwUmwTbTaH8QAJURBj0RhQ/zCne7VuLLOZFFGv6jGigWhSw==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/transaction-messages/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/transaction-messages/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/transaction-messages/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/transactions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/transactions/-/transactions-2.3.0.tgz", + "integrity": "sha512-LnTvdi8QnrQtuEZor5Msje61sDpPstTVwKg4y81tNxDhiyomjuvnSNLAq6QsB9gIxUqbNzPZgOG9IU4I4/Uaug==", + "license": "MIT", + "dependencies": { + "@solana/addresses": "2.3.0", + "@solana/codecs-core": "2.3.0", + "@solana/codecs-data-structures": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/codecs-strings": "2.3.0", + "@solana/errors": "2.3.0", + "@solana/functional": "2.3.0", + "@solana/instructions": "2.3.0", + "@solana/keys": "2.3.0", + "@solana/nominal-types": "2.3.0", + "@solana/rpc-types": "2.3.0", + "@solana/transaction-messages": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/transactions/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/transactions/node_modules/@solana/codecs-data-structures": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-data-structures/-/codecs-data-structures-2.3.0.tgz", + "integrity": "sha512-qvU5LE5DqEdYMYgELRHv+HMOx73sSoV1ZZkwIrclwUmwTbTaH8QAJURBj0RhQ/zCne7VuLLOZFFGv6jGigWhSw==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/transactions/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/transactions/node_modules/@solana/codecs-strings": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-strings/-/codecs-strings-2.3.0.tgz", + "integrity": "sha512-y5pSBYwzVziXu521hh+VxqUtp0hYGTl1eWGoc1W+8mdvBdC1kTqm/X7aYQw33J42hw03JjryvYOvmGgk3Qz/Ug==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/codecs-numbers": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "fastestsmallesttextencoderdecoder": "^1.0.22", + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/transactions/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/transactions/node_modules/commander": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@solana/web3.js": { + "version": "1.98.2", + "dev": true, + "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/@solana/web3.js/node_modules/@solana/codecs-core": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@solana/errors": "2.1.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5" + } + }, + "node_modules/@solana/web3.js/node_modules/@solana/codecs-numbers": { + "version": "2.1.0", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] + "dependencies": { + "@solana/codecs-core": "2.1.0", + "@solana/errors": "2.1.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5" + } }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.50.2.tgz", - "integrity": "sha512-dkYXB0c2XAS3a3jmyDkX4Jk0m7gWLFzq1C3qUnJJ38AyxIF5G/dyS4N9B30nvFseCfgtCEdbYFhk0ChoCGxPog==", - "cpu": [ - "x64" - ], + "node_modules/@solana/web3.js/node_modules/@solana/errors": { + "version": "2.1.0", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] + "dependencies": { + "chalk": "^5.3.0", + "commander": "^13.1.0" + }, + "bin": { + "errors": "bin/cli.mjs" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5" + } }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.50.2.tgz", - "integrity": "sha512-9VlPY/BN3AgbukfVHAB8zNFWB/lKEuvzRo1NKev0Po8sYFKx0i+AQlCYftgEjcL43F2h9Ui1ZSdVBc4En/sP2w==", - "cpu": [ - "arm" - ], + "node_modules/@solana/web3.js/node_modules/base-x": { + "version": "3.0.11", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "safe-buffer": "^5.0.1" + } }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.50.2.tgz", - "integrity": "sha512-+GdKWOvsifaYNlIVf07QYan1J5F141+vGm5/Y8b9uCZnG/nxoGqgCmR24mv0koIWWuqvFYnbURRqw1lv7IBINw==", - "cpu": [ - "arm" - ], + "node_modules/@solana/web3.js/node_modules/bs58": { + "version": "4.0.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "base-x": "^3.0.2" + } }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.2.tgz", - "integrity": "sha512-KlE8IC0HFOC33taNt1zR8qNlBYHj31qGT1UqWqtvR/+NuCVhfufAq9fxO8BMFC22Wu0rxOwGVWxtCMvZVLmhQg==", - "cpu": [ - "arm64" - ], + "node_modules/@solana/web3.js/node_modules/commander": { + "version": "13.1.0", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": ">=18" + } }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.2.tgz", - "integrity": "sha512-j8CgxvfM0kbnhu4XgjnCWJQyyBOeBI1Zq91Z850aUddUmPeQvuAy6OiMdPS46gNFgy8gN1xkYyLgwLYZG3rBOg==", - "cpu": [ - "arm64" - ], + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "peer": true }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.50.2.tgz", - "integrity": "sha512-OL6KaNvBopLlj5fTa5D5bau4W82f+1TyTZRr2BdnfsrnQnmdxh4okMxR2DcDkJuh4KeoQZVuvHvzuD/lyLn2Kw==", - "cpu": [ - "loong64" - ], + "node_modules/@swc/helpers": { + "version": "0.5.17", "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@tanstack/query-core": { + "version": "5.89.0", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.89.0.tgz", + "integrity": "sha512-joFV1MuPhSLsKfTzwjmPDrp8ENfZ9N23ymFu07nLfn3JCkSHy0CFgsyhHTJOmWaumC/WiNIKM0EJyduCF/Ih/Q==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "peer": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.50.2.tgz", - "integrity": "sha512-I21VJl1w6z/K5OTRl6aS9DDsqezEZ/yKpbqlvfHbW0CEF5IL8ATBMuUx6/mp683rKTK8thjs/0BaNrZLXetLag==", - "cpu": [ - "ppc64" - ], - "dev": true, + "node_modules/@tanstack/react-query": { + "version": "5.89.0", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.89.0.tgz", + "integrity": "sha512-SXbtWSTSRXyBOe80mszPxpEbaN4XPRUp/i0EfQK1uyj3KCk/c8FuPJNIRwzOVe/OU3rzxrYtiNabsAmk1l714A==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "peer": true, + "dependencies": { + "@tanstack/query-core": "5.89.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18 || ^19" + } }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.50.2.tgz", - "integrity": "sha512-Hq6aQJT/qFFHrYMjS20nV+9SKrXL2lvFBENZoKfoTH2kKDOJqff5OSJr4x72ZaG/uUn+XmBnGhfr4lwMRrmqCQ==", - "cpu": [ - "riscv64" - ], - "dev": true, + "node_modules/@types/babel__core": { + "version": "7.20.5", "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "peer": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.50.2.tgz", - "integrity": "sha512-82rBSEXRv5qtKyr0xZ/YMF531oj2AIpLZkeNYxmKNN6I2sVE9PGegN99tYDLK2fYHJITL1P2Lgb4ZXnv0PjQvw==", - "cpu": [ - "riscv64" - ], - "dev": true, + "node_modules/@types/babel__generator": { + "version": "7.27.0", "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "peer": true, + "dependencies": { + "@babel/types": "^7.0.0" + } }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.50.2.tgz", - "integrity": "sha512-4Q3S3Hy7pC6uaRo9gtXUTJ+EKo9AKs3BXKc2jYypEcMQ49gDPFU2P1ariX9SEtBzE5egIX6fSUmbmGazwBVF9w==", - "cpu": [ - "s390x" - ], - "dev": true, + "node_modules/@types/babel__template": { + "version": "7.4.4", "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "peer": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.2.tgz", - "integrity": "sha512-lG7Xa+BmBNwpjmVUbmyKxdQJ3Q6whHjMjzQplOs5Z+Gj7mxPtWakGHqzMqNER68G67kmCX9qX57aRsW5V0VOng==", - "cpu": [ - "x64" - ], + "node_modules/@types/babel__traverse": { + "version": "7.20.7", "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "peer": true, + "dependencies": { + "@babel/types": "^7.20.7" + } }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.2.tgz", - "integrity": "sha512-tD46wKHd+KJvsmije4bUskNuvWKFcTOIM9tZ/RrmIvcXnbi0YK/cKS9FzFtAm7Oxi2EhV5N2OpfFB348vSQRXA==", - "cpu": [ - "x64" - ], + "node_modules/@types/better-sqlite3": { + "version": "7.6.13", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "@types/node": "*" + } }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.50.2.tgz", - "integrity": "sha512-nMKvq6FRHSzYfKLHZ+cChowlEkR2lj/V0jYj9JnGUVPL2/mIeFGmVM2mLaFeNa5Jev7W7TovXqXIG2d39y1KYA==", - "cpu": [ - "arm64" - ], + "node_modules/@types/body-parser": { + "version": "1.19.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/chai": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.2.tgz", + "integrity": "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] + "dependencies": { + "@types/deep-eql": "*" + } }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.50.2.tgz", - "integrity": "sha512-eFUvvnTYEKeTyHEijQKz81bLrUQOXKZqECeiWH6tb8eXXbZk+CXSG2aFrig2BQ/pjiVRj36zysjgILkqarS2YA==", - "cpu": [ - "arm64" - ], + "node_modules/@types/connect": { + "version": "3.4.38", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "dependencies": { + "@types/node": "*" + } }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.50.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.50.2.tgz", - "integrity": "sha512-cBaWmXqyfRhH8zmUxK3d3sAhEWLrtMjWBRwdMMHJIXSjvjLKvv49adxiEz+FJ8AP90apSDDBx2Tyd/WylV6ikA==", - "cpu": [ - "ia32" - ], + "node_modules/@types/content-type": { + "version": "1.1.9", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "license": "MIT" }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.40.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.2.tgz", - "integrity": "sha512-bwspbWB04XJpeElvsp+DCylKfF4trJDa2Y9Go8O6A7YLX2LIKGcNK/CYImJN6ZP4DcuOHB4Utl3iCbnR62DudA==", - "cpu": [ - "x64" - ], + "node_modules/@types/cookiejar": { + "version": "2.1.5", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "dependencies": { + "@types/ms": "*" + } }, - "node_modules/@rtsao/scc": { - "version": "1.1.0", + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", "dev": true, "license": "MIT" }, - "node_modules/@scure/base": { - "version": "1.2.6", + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/express": { + "version": "5.0.1", + "dev": true, "license": "MIT", - "funding": { - "url": "https://paulmillr.com/funding/" + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^5.0.0", + "@types/serve-static": "*" } }, - "node_modules/@scure/bip32": { - "version": "1.7.0", + "node_modules/@types/express-serve-static-core": { + "version": "5.0.6", + "dev": true, "license": "MIT", "dependencies": { - "@noble/curves": "~1.9.0", - "@noble/hashes": "~1.8.0", - "@scure/base": "~1.2.5" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" } }, - "node_modules/@scure/bip39": { - "version": "1.6.0", + "node_modules/@types/glob-to-regexp": { + "version": "0.4.4", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", "license": "MIT", + "peer": true, "dependencies": { - "@noble/hashes": "~1.8.0", - "@scure/base": "~1.2.5" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "@types/node": "*" } }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", + "node_modules/@types/http-errors": { + "version": "2.0.4", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", "license": "MIT", "peer": true }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "license": "BSD-3-Clause", + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "license": "MIT", "peer": true, "dependencies": { - "type-detect": "4.0.8" + "@types/istanbul-lib-coverage": "*" } }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "license": "BSD-3-Clause", + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "license": "MIT", "peer": true, "dependencies": { - "@sinonjs/commons": "^3.0.0" + "@types/istanbul-lib-report": "*" } }, - "node_modules/@solana/buffer-layout": { - "version": "4.0.1", + "node_modules/@types/json-schema": { + "version": "7.0.15", "dev": true, - "license": "MIT", - "dependencies": { - "buffer": "~6.0.3" - }, - "engines": { - "node": ">=5.10" - } + "license": "MIT" }, - "node_modules/@solana/buffer-layout-utils": { - "version": "0.2.0", + "node_modules/@types/json5": { + "version": "0.0.29", "dev": true, - "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" - } + "license": "MIT" }, - "node_modules/@solana/codecs": { - "version": "2.0.0-rc.1", + "node_modules/@types/lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==", + "license": "MIT" + }, + "node_modules/@types/methods": { + "version": "1.1.4", "dev": true, - "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" - } + "license": "MIT" }, - "node_modules/@solana/codecs-core": { - "version": "2.0.0-rc.1", + "node_modules/@types/mime": { + "version": "1.3.5", "dev": true, + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.15.14", "license": "MIT", "dependencies": { - "@solana/errors": "2.0.0-rc.1" - }, - "peerDependencies": { - "typescript": ">=5" + "undici-types": "~6.21.0" } }, - "node_modules/@solana/codecs-data-structures": { - "version": "2.0.0-rc.1", + "node_modules/@types/qs": { + "version": "6.9.18", "dev": true, - "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" - } + "license": "MIT" }, - "node_modules/@solana/codecs-numbers": { - "version": "2.0.0-rc.1", + "node_modules/@types/range-parser": { + "version": "1.2.7", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/resolve": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", + "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "0.17.4", "dev": true, "license": "MIT", "dependencies": { - "@solana/codecs-core": "2.0.0-rc.1", - "@solana/errors": "2.0.0-rc.1" - }, - "peerDependencies": { - "typescript": ">=5" + "@types/mime": "^1", + "@types/node": "*" } }, - "node_modules/@solana/codecs-strings": { - "version": "2.0.0-rc.1", + "node_modules/@types/serve-static": { + "version": "1.15.7", "dev": true, "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" + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" } }, - "node_modules/@solana/errors": { - "version": "2.0.0-rc.1", + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "license": "MIT", + "peer": true + }, + "node_modules/@types/superagent": { + "version": "8.1.9", "dev": true, "license": "MIT", "dependencies": { - "chalk": "^5.3.0", - "commander": "^12.1.0" - }, - "bin": { - "errors": "bin/cli.mjs" - }, - "peerDependencies": { - "typescript": ">=5" + "@types/cookiejar": "^2.1.5", + "@types/methods": "^1.1.4", + "@types/node": "*", + "form-data": "^4.0.0" } }, - "node_modules/@solana/options": { - "version": "2.0.0-rc.1", + "node_modules/@types/supertest": { + "version": "6.0.3", "dev": true, "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" + "@types/methods": "^1.1.4", + "@types/superagent": "^8.1.0" } }, - "node_modules/@solana/pay": { - "version": "0.2.6", + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT" + }, + "node_modules/@types/uuid": { + "version": "8.3.4", "dev": true, - "license": "Apache-2.0", + "license": "MIT" + }, + "node_modules/@types/ws": { + "version": "7.4.7", + "dev": true, + "license": "MIT", "dependencies": { - "@solana/qr-code-styling": "^1.6.0", - "@solana/spl-token": "^0.4.13", - "@solana/web3.js": "^1.98.2", - "bignumber.js": "^9.1.0", - "cross-fetch": "^3.1.5", - "js-base64": "^3.7.2", - "tweetnacl": "^1.0.3" - }, - "engines": { - "node": ">=16" + "@types/node": "*" } }, - "node_modules/@solana/qr-code-styling": { - "version": "1.6.0", - "dev": true, + "node_modules/@types/yargs": { + "version": "17.0.33", "license": "MIT", + "peer": true, "dependencies": { - "qrcode-generator": "^1.4.3" + "@types/yargs-parser": "*" } }, - "node_modules/@solana/spl-token": { - "version": "0.4.13", + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "license": "MIT", + "peer": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.38.0", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "@solana/buffer-layout": "^4.0.0", - "@solana/buffer-layout-utils": "^0.2.0", - "@solana/spl-token-group": "^0.0.7", - "@solana/spl-token-metadata": "^0.1.6", - "buffer": "^6.0.3" + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.38.0", + "@typescript-eslint/type-utils": "8.38.0", + "@typescript-eslint/utils": "8.38.0", + "@typescript-eslint/visitor-keys": "8.38.0", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" }, "engines": { - "node": ">=16" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@solana/web3.js": "^1.95.5" + "@typescript-eslint/parser": "^8.38.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/@solana/spl-token-group": { - "version": "0.0.7", + "node_modules/@typescript-eslint/parser": { + "version": "8.38.0", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "@solana/codecs": "2.0.0-rc.1" + "@typescript-eslint/scope-manager": "8.38.0", + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/typescript-estree": "8.38.0", + "@typescript-eslint/visitor-keys": "8.38.0", + "debug": "^4.3.4" }, "engines": { - "node": ">=16" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@solana/web3.js": "^1.95.3" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/@solana/spl-token-metadata": { - "version": "0.1.6", + "node_modules/@typescript-eslint/project-service": { + "version": "8.38.0", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "@solana/codecs": "2.0.0-rc.1" + "@typescript-eslint/tsconfig-utils": "^8.38.0", + "@typescript-eslint/types": "^8.38.0", + "debug": "^4.3.4" }, "engines": { - "node": ">=16" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@solana/web3.js": "^1.95.3" + "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/@solana/web3.js": { - "version": "1.98.2", + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.38.0", "dev": true, "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" + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/visitor-keys": "8.38.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@solana/web3.js/node_modules/@solana/codecs-core": { - "version": "2.1.0", + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.38.0", "dev": true, "license": "MIT", - "dependencies": { - "@solana/errors": "2.1.0" - }, "engines": { - "node": ">=20.18.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=5" + "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/@solana/web3.js/node_modules/@solana/codecs-numbers": { - "version": "2.1.0", + "node_modules/@typescript-eslint/type-utils": { + "version": "8.38.0", "dev": true, "license": "MIT", "dependencies": { - "@solana/codecs-core": "2.1.0", - "@solana/errors": "2.1.0" + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/typescript-estree": "8.38.0", + "@typescript-eslint/utils": "8.38.0", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" }, "engines": { - "node": ">=20.18.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=5" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/@solana/web3.js/node_modules/@solana/errors": { - "version": "2.1.0", + "node_modules/@typescript-eslint/types": { + "version": "8.38.0", "dev": true, "license": "MIT", - "dependencies": { - "chalk": "^5.3.0", - "commander": "^13.1.0" + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "bin": { - "errors": "bin/cli.mjs" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.38.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.38.0", + "@typescript-eslint/tsconfig-utils": "8.38.0", + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/visitor-keys": "8.38.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" }, "engines": { - "node": ">=20.18.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=5" + "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/@solana/web3.js/node_modules/base-x": { - "version": "3.0.11", + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.2", "dev": true, "license": "MIT", "dependencies": { - "safe-buffer": "^5.0.1" + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@solana/web3.js/node_modules/bs58": { - "version": "4.0.1", + "node_modules/@typescript-eslint/utils": { + "version": "8.38.0", "dev": true, "license": "MIT", "dependencies": { - "base-x": "^3.0.2" + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.38.0", + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/typescript-estree": "8.38.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/@solana/web3.js/node_modules/commander": { - "version": "13.1.0", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.38.0", "dev": true, "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.38.0", + "eslint-visitor-keys": "^4.2.1" + }, "engines": { - "node": ">=18" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@standard-schema/spec": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", - "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", - "license": "MIT", - "peer": true - }, - "node_modules/@swc/helpers": { - "version": "0.5.17", + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.1", "dev": true, "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.8.0" + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@types/babel__core": { - "version": "7.20.5", + "node_modules/@urql/core": { + "version": "5.1.1", "license": "MIT", "peer": true, "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" + "@0no-co/graphql.web": "^1.0.5", + "wonka": "^6.3.2" } }, - "node_modules/@types/babel__generator": { - "version": "7.27.0", + "node_modules/@urql/exchange-retry": { + "version": "1.3.1", "license": "MIT", "peer": true, "dependencies": { - "@babel/types": "^7.0.0" + "@urql/core": "^5.1.1", + "wonka": "^6.3.2" + }, + "peerDependencies": { + "@urql/core": "^5.0.0" } }, - "node_modules/@types/babel__template": { - "version": "7.4.4", + "node_modules/@vitest/coverage-v8": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.2.4.tgz", + "integrity": "sha512-EyF9SXU6kS5Ku/U82E259WSnvg6c8KTjppUncuNdm5QHpe17mwREHnjDzozC8x9MZ0xfBUFSaLkRv4TMA75ALQ==", + "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" + "@ampproject/remapping": "^2.3.0", + "@bcoe/v8-coverage": "^1.0.2", + "ast-v8-to-istanbul": "^0.3.3", + "debug": "^4.4.1", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-lib-source-maps": "^5.0.6", + "istanbul-reports": "^3.1.7", + "magic-string": "^0.30.17", + "magicast": "^0.3.5", + "std-env": "^3.9.0", + "test-exclude": "^7.0.1", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/browser": "3.2.4", + "vitest": "3.2.4" + }, + "peerDependenciesMeta": { + "@vitest/browser": { + "optional": true + } } }, - "node_modules/@types/babel__traverse": { - "version": "7.20.7", + "node_modules/@vitest/coverage-v8/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/types": "^7.20.7" + "balanced-match": "^1.0.0" } }, - "node_modules/@types/better-sqlite3": { - "version": "7.6.13", + "node_modules/@vitest/coverage-v8/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@types/node": "*" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@types/body-parser": { - "version": "1.19.5", + "node_modules/@vitest/coverage-v8/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@types/connect": "*", - "@types/node": "*" + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@types/chai": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.2.tgz", - "integrity": "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==", + "node_modules/@vitest/coverage-v8/node_modules/test-exclude": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", + "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@types/deep-eql": "*" + "@istanbuljs/schema": "^0.1.2", + "glob": "^10.4.1", + "minimatch": "^9.0.4" + }, + "engines": { + "node": ">=18" } }, - "node_modules/@types/connect": { - "version": "3.4.38", + "node_modules/@vitest/expect": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz", + "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "*" + "@types/chai": "^5.2.2", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", + "chai": "^5.2.0", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/@types/content-type": { - "version": "1.1.9", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/cookiejar": { - "version": "2.1.5", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/deep-eql": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", - "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "node_modules/@vitest/mocker": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz", + "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@vitest/spy": "3.2.4", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } }, - "node_modules/@types/express": { - "version": "5.0.1", + "node_modules/@vitest/pretty-format": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz", + "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", "dev": true, "license": "MIT", "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^5.0.0", - "@types/serve-static": "*" + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/@types/express-serve-static-core": { - "version": "5.0.6", + "node_modules/@vitest/runner": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.4.tgz", + "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" + "@vitest/utils": "3.2.4", + "pathe": "^2.0.3", + "strip-literal": "^3.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/@types/glob-to-regexp": { - "version": "0.4.4", + "node_modules/@vitest/snapshot": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.4.tgz", + "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==", "dev": true, - "license": "MIT" - }, - "node_modules/@types/graceful-fs": { - "version": "4.1.9", "license": "MIT", - "peer": true, "dependencies": { - "@types/node": "*" + "@vitest/pretty-format": "3.2.4", + "magic-string": "^0.30.17", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/@types/http-errors": { - "version": "2.0.4", + "node_modules/@vitest/spy": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz", + "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==", "dev": true, - "license": "MIT" - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", "license": "MIT", - "peer": true - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.3", - "license": "MIT", - "peer": true, "dependencies": { - "@types/istanbul-lib-coverage": "*" + "tinyspy": "^4.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.4", + "node_modules/@vitest/utils": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz", + "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==", + "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@types/istanbul-lib-report": "*" + "@vitest/pretty-format": "3.2.4", + "loupe": "^3.1.4", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/methods": { - "version": "1.1.4", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/mime": { - "version": "1.3.5", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "22.15.14", + "node_modules/@wagmi/connectors": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/@wagmi/connectors/-/connectors-5.10.0.tgz", + "integrity": "sha512-pG9a9PIOkxfJQF7kSdMUfPjZ52LOPjXboga99LnZHh+VXmXd2J93r7NGYO3kF0lhrt3hdbmYYsZCOgbPkXiHig==", "license": "MIT", "dependencies": { - "undici-types": "~6.21.0" + "@base-org/account": "1.1.1", + "@coinbase/wallet-sdk": "4.3.6", + "@gemini-wallet/core": "0.2.0", + "@metamask/sdk": "0.32.0", + "@safe-global/safe-apps-provider": "0.18.6", + "@safe-global/safe-apps-sdk": "9.1.0", + "@walletconnect/ethereum-provider": "2.21.1", + "cbw-sdk": "npm:@coinbase/wallet-sdk@3.9.3" + }, + "funding": { + "url": "https://github.com/sponsors/wevm" + }, + "peerDependencies": { + "@wagmi/core": "2.21.0", + "typescript": ">=5.0.4", + "viem": "2.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@types/qs": { - "version": "6.9.18", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/resolve": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", - "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", - "dev": true, - "license": "MIT" + "node_modules/@wagmi/connectors/node_modules/@base-org/account": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@base-org/account/-/account-1.1.1.tgz", + "integrity": "sha512-IfVJPrDPhHfqXRDb89472hXkpvJuQQR7FDI9isLPHEqSYt/45whIoBxSPgZ0ssTt379VhQo4+87PWI1DoLSfAQ==", + "license": "Apache-2.0", + "dependencies": { + "@noble/hashes": "1.4.0", + "clsx": "1.2.1", + "eventemitter3": "5.0.1", + "idb-keyval": "6.2.1", + "ox": "0.6.9", + "preact": "10.24.2", + "viem": "^2.31.7", + "zustand": "5.0.3" + } }, - "node_modules/@types/send": { - "version": "0.17.4", - "dev": true, + "node_modules/@wagmi/connectors/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", - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@types/serve-static": { - "version": "1.15.7", - "dev": true, + "node_modules/@wagmi/connectors/node_modules/ox": { + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.6.9.tgz", + "integrity": "sha512-wi5ShvzE4eOcTwQVsIPdFr+8ycyX+5le/96iAJutaZAvCes1J0+RvpEPg5QDPDiaR0XQQAvZVl7AwqQcINuUug==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], "license": "MIT", "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "*" + "@adraffy/ens-normalize": "^1.10.1", + "@noble/curves": "^1.6.0", + "@noble/hashes": "^1.5.0", + "@scure/bip32": "^1.5.0", + "@scure/bip39": "^1.4.0", + "abitype": "^1.0.6", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@types/stack-utils": { - "version": "2.0.3", + "node_modules/@wagmi/connectors/node_modules/ox/node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", "license": "MIT", - "peer": true + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } }, - "node_modules/@types/superagent": { - "version": "8.1.9", - "dev": true, + "node_modules/@wagmi/core": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/@wagmi/core/-/core-2.21.0.tgz", + "integrity": "sha512-ZtQBUvHEyfSM22BCeXZDjwcpby2vZjivjP8mMkQHxuVqRDnunaS5DIlZr2XPJKv01lPdlUajFSoiziNcIZlH5w==", "license": "MIT", "dependencies": { - "@types/cookiejar": "^2.1.5", - "@types/methods": "^1.1.4", - "@types/node": "*", - "form-data": "^4.0.0" + "eventemitter3": "5.0.1", + "mipd": "0.0.7", + "zustand": "5.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/wevm" + }, + "peerDependencies": { + "@tanstack/query-core": ">=5.0.0", + "typescript": ">=5.0.4", + "viem": "2.x" + }, + "peerDependenciesMeta": { + "@tanstack/query-core": { + "optional": true + }, + "typescript": { + "optional": true + } } }, - "node_modules/@types/supertest": { - "version": "6.0.3", - "dev": true, + "node_modules/@wagmi/core/node_modules/zustand": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.0.tgz", + "integrity": "sha512-LE+VcmbartOPM+auOjCCLQOsQ05zUTp8RkgwRzefUk+2jISdMMFnxvyTjA4YNWr5ZGXYbVsEMZosttuxUBkojQ==", "license": "MIT", - "dependencies": { - "@types/methods": "^1.1.4", - "@types/superagent": "^8.1.0" + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=18.0.0", + "immer": ">=9.0.6", + "react": ">=18.0.0", + "use-sync-external-store": ">=1.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + }, + "use-sync-external-store": { + "optional": true + } } }, - "node_modules/@types/uuid": { - "version": "8.3.4", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/ws": { - "version": "7.4.7", - "dev": true, - "license": "MIT", + "node_modules/@walletconnect/core": { + "version": "2.21.1", + "resolved": "https://registry.npmjs.org/@walletconnect/core/-/core-2.21.1.tgz", + "integrity": "sha512-Tp4MHJYcdWD846PH//2r+Mu4wz1/ZU/fr9av1UWFiaYQ2t2TPLDiZxjLw54AAEpMqlEHemwCgiRiAmjR1NDdTQ==", + "license": "Apache-2.0", "dependencies": { - "@types/node": "*" + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-provider": "1.0.14", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/jsonrpc-ws-connection": "1.0.16", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "2.1.2", + "@walletconnect/relay-api": "1.0.11", + "@walletconnect/relay-auth": "1.1.0", + "@walletconnect/safe-json": "1.0.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.21.1", + "@walletconnect/utils": "2.21.1", + "@walletconnect/window-getters": "1.0.1", + "es-toolkit": "1.33.0", + "events": "3.3.0", + "uint8arrays": "3.1.0" + }, + "engines": { + "node": ">=18" } }, - "node_modules/@types/yargs": { - "version": "17.0.33", + "node_modules/@walletconnect/environment": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@walletconnect/environment/-/environment-1.0.1.tgz", + "integrity": "sha512-T426LLZtHj8e8rYnKfzsw1aG6+M0BT1ZxayMdv/p8yM0MU+eJDISqNY3/bccxRr4LrF9csq02Rhqt08Ibl0VRg==", "license": "MIT", - "peer": true, "dependencies": { - "@types/yargs-parser": "*" + "tslib": "1.14.1" } }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "license": "MIT", - "peer": true + "node_modules/@walletconnect/environment/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, + "node_modules/@walletconnect/ethereum-provider": { + "version": "2.21.1", + "resolved": "https://registry.npmjs.org/@walletconnect/ethereum-provider/-/ethereum-provider-2.21.1.tgz", + "integrity": "sha512-SSlIG6QEVxClgl1s0LMk4xr2wg4eT3Zn/Hb81IocyqNSGfXpjtawWxKxiC5/9Z95f1INyBD6MctJbL/R1oBwIw==", + "license": "Apache-2.0", + "dependencies": { + "@reown/appkit": "1.7.8", + "@walletconnect/jsonrpc-http-connection": "1.0.8", + "@walletconnect/jsonrpc-provider": "1.0.14", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/sign-client": "2.21.1", + "@walletconnect/types": "2.21.1", + "@walletconnect/universal-provider": "2.21.1", + "@walletconnect/utils": "2.21.1", + "events": "3.3.0" + } }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.38.0", - "dev": true, + "node_modules/@walletconnect/events": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@walletconnect/events/-/events-1.0.1.tgz", + "integrity": "sha512-NPTqaoi0oPBVNuLv7qPaJazmGHs5JGyO8eEAk5VGKmJzDR7AHzD4k6ilox5kxk1iwiOnFopBOOMLs86Oa76HpQ==", "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.38.0", - "@typescript-eslint/type-utils": "8.38.0", - "@typescript-eslint/utils": "8.38.0", - "@typescript-eslint/visitor-keys": "8.38.0", - "graphemer": "^1.4.0", - "ignore": "^7.0.0", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.38.0", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "keyvaluestorage-interface": "^1.0.0", + "tslib": "1.14.1" } }, - "node_modules/@typescript-eslint/parser": { - "version": "8.38.0", - "dev": true, + "node_modules/@walletconnect/events/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, + "node_modules/@walletconnect/heartbeat": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@walletconnect/heartbeat/-/heartbeat-1.2.2.tgz", + "integrity": "sha512-uASiRmC5MwhuRuf05vq4AT48Pq8RMi876zV8rr8cV969uTOzWdB/k+Lj5yI2PBtB1bGQisGen7MM1GcZlQTBXw==", "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.38.0", - "@typescript-eslint/types": "8.38.0", - "@typescript-eslint/typescript-estree": "8.38.0", - "@typescript-eslint/visitor-keys": "8.38.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "@walletconnect/events": "^1.0.1", + "@walletconnect/time": "^1.0.2", + "events": "^3.3.0" } }, - "node_modules/@typescript-eslint/project-service": { - "version": "8.38.0", - "dev": true, + "node_modules/@walletconnect/jsonrpc-http-connection": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-http-connection/-/jsonrpc-http-connection-1.0.8.tgz", + "integrity": "sha512-+B7cRuaxijLeFDJUq5hAzNyef3e3tBDIxyaCNmFtjwnod5AGis3RToNqzFU33vpVcxFhofkpE7Cx+5MYejbMGw==", "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.38.0", - "@typescript-eslint/types": "^8.38.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" + "@walletconnect/jsonrpc-utils": "^1.0.6", + "@walletconnect/safe-json": "^1.0.1", + "cross-fetch": "^3.1.4", + "events": "^3.3.0" } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "8.38.0", - "dev": true, + "node_modules/@walletconnect/jsonrpc-provider": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-provider/-/jsonrpc-provider-1.0.14.tgz", + "integrity": "sha512-rtsNY1XqHvWj0EtITNeuf8PHMvlCLiS3EjQL+WOkxEOA4KPxsohFnBDeyPYiNm4ZvkQdLnece36opYidmtbmow==", "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.38.0", - "@typescript-eslint/visitor-keys": "8.38.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "@walletconnect/jsonrpc-utils": "^1.0.8", + "@walletconnect/safe-json": "^1.0.2", + "events": "^3.3.0" } }, - "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.38.0", - "dev": true, + "node_modules/@walletconnect/jsonrpc-types": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-types/-/jsonrpc-types-1.0.4.tgz", + "integrity": "sha512-P6679fG/M+wuWg9TY8mh6xFSdYnFyFjwFelxyISxMDrlbXokorEVXYOxiqEbrU3x1BmBoCAJJ+vtEaEoMlpCBQ==", "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" + "dependencies": { + "events": "^3.3.0", + "keyvaluestorage-interface": "^1.0.0" } }, - "node_modules/@typescript-eslint/type-utils": { - "version": "8.38.0", - "dev": true, + "node_modules/@walletconnect/jsonrpc-utils": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-utils/-/jsonrpc-utils-1.0.8.tgz", + "integrity": "sha512-vdeb03bD8VzJUL6ZtzRYsFMq1eZQcM3EAzT0a3st59dyLfJ0wq+tKMpmGH7HlB7waD858UWgfIcudbPFsbzVdw==", "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.38.0", - "@typescript-eslint/typescript-estree": "8.38.0", - "@typescript-eslint/utils": "8.38.0", - "debug": "^4.3.4", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "@walletconnect/environment": "^1.0.1", + "@walletconnect/jsonrpc-types": "^1.0.3", + "tslib": "1.14.1" } }, - "node_modules/@typescript-eslint/types": { - "version": "8.38.0", - "dev": true, + "node_modules/@walletconnect/jsonrpc-utils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, + "node_modules/@walletconnect/jsonrpc-ws-connection": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-ws-connection/-/jsonrpc-ws-connection-1.0.16.tgz", + "integrity": "sha512-G81JmsMqh5nJheE1mPst1W0WfVv0SG3N7JggwLLGnI7iuDZJq8cRJvQwLGKHn5H1WTW7DEPCo00zz5w62AbL3Q==", "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "dependencies": { + "@walletconnect/jsonrpc-utils": "^1.0.6", + "@walletconnect/safe-json": "^1.0.2", + "events": "^3.3.0", + "ws": "^7.5.1" } }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.38.0", - "dev": true, + "node_modules/@walletconnect/keyvaluestorage": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@walletconnect/keyvaluestorage/-/keyvaluestorage-1.1.1.tgz", + "integrity": "sha512-V7ZQq2+mSxAq7MrRqDxanTzu2RcElfK1PfNYiaVnJgJ7Q7G7hTVwF8voIBx92qsRyGHZihrwNPHuZd1aKkd0rA==", "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.38.0", - "@typescript-eslint/tsconfig-utils": "8.38.0", - "@typescript-eslint/types": "8.38.0", - "@typescript-eslint/visitor-keys": "8.38.0", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "@walletconnect/safe-json": "^1.0.1", + "idb-keyval": "^6.2.1", + "unstorage": "^1.9.0" }, "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" + "@react-native-async-storage/async-storage": "1.x" + }, + "peerDependenciesMeta": { + "@react-native-async-storage/async-storage": { + "optional": true + } } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.2", - "dev": true, + "node_modules/@walletconnect/logger": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@walletconnect/logger/-/logger-2.1.2.tgz", + "integrity": "sha512-aAb28I3S6pYXZHQm5ESB+V6rDqIYfsnHaQyzFbwUUBFY4H0OXx/YtTl8lvhUNhMMfb9UxbwEBS253TlXUYJWSw==", "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "@walletconnect/safe-json": "^1.0.2", + "pino": "7.11.0" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "dev": true, - "license": "ISC", + "node_modules/@walletconnect/relay-api": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@walletconnect/relay-api/-/relay-api-1.0.11.tgz", + "integrity": "sha512-tLPErkze/HmC9aCmdZOhtVmYZq1wKfWTJtygQHoWtgg722Jd4homo54Cs4ak2RUFUZIGO2RsOpIcWipaua5D5Q==", + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "@walletconnect/jsonrpc-types": "^1.0.2" } }, - "node_modules/@typescript-eslint/utils": { - "version": "8.38.0", - "dev": true, + "node_modules/@walletconnect/relay-auth": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@walletconnect/relay-auth/-/relay-auth-1.1.0.tgz", + "integrity": "sha512-qFw+a9uRz26jRCDgL7Q5TA9qYIgcNY8jpJzI1zAWNZ8i7mQjaijRnWFKsCHAU9CyGjvt6RKrRXyFtFOpWTVmCQ==", "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.38.0", - "@typescript-eslint/types": "8.38.0", - "@typescript-eslint/typescript-estree": "8.38.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "@noble/curves": "1.8.0", + "@noble/hashes": "1.7.0", + "@walletconnect/safe-json": "^1.0.1", + "@walletconnect/time": "^1.0.2", + "uint8arrays": "^3.0.0" } }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.38.0", - "dev": true, + "node_modules/@walletconnect/relay-auth/node_modules/@noble/curves": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.0.tgz", + "integrity": "sha512-j84kjAbzEnQHaSIhRPUmB3/eVXu2k3dKPl2LOrR8fSOIL+89U+7lV117EWHtq/GHM3ReGHM46iRBdZfpc4HRUQ==", "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.38.0", - "eslint-visitor-keys": "^4.2.1" + "@noble/hashes": "1.7.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^14.21.3 || >=16" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "dev": true, - "license": "Apache-2.0", + "node_modules/@walletconnect/relay-auth/node_modules/@noble/hashes": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.0.tgz", + "integrity": "sha512-HXydb0DgzTpDPwbVeDGCG1gIu7X6+AuU6Zl6av/E/KG8LMsvPntvq+w17CHRpKBmN6Ybdrt1eP3k4cj8DJa78w==", + "license": "MIT", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^14.21.3 || >=16" }, "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@urql/core": { - "version": "5.1.1", - "license": "MIT", - "peer": true, - "dependencies": { - "@0no-co/graphql.web": "^1.0.5", - "wonka": "^6.3.2" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@urql/exchange-retry": { - "version": "1.3.1", + "node_modules/@walletconnect/safe-json": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@walletconnect/safe-json/-/safe-json-1.0.2.tgz", + "integrity": "sha512-Ogb7I27kZ3LPC3ibn8ldyUr5544t3/STow9+lzz7Sfo808YD7SBWk7SAsdBFlYgP2zDRy2hS3sKRcuSRM0OTmA==", "license": "MIT", - "peer": true, "dependencies": { - "@urql/core": "^5.1.1", - "wonka": "^6.3.2" - }, - "peerDependencies": { - "@urql/core": "^5.0.0" + "tslib": "1.14.1" } }, - "node_modules/@vitest/coverage-v8": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.2.4.tgz", - "integrity": "sha512-EyF9SXU6kS5Ku/U82E259WSnvg6c8KTjppUncuNdm5QHpe17mwREHnjDzozC8x9MZ0xfBUFSaLkRv4TMA75ALQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.3.0", - "@bcoe/v8-coverage": "^1.0.2", - "ast-v8-to-istanbul": "^0.3.3", - "debug": "^4.4.1", - "istanbul-lib-coverage": "^3.2.2", - "istanbul-lib-report": "^3.0.1", - "istanbul-lib-source-maps": "^5.0.6", - "istanbul-reports": "^3.1.7", - "magic-string": "^0.30.17", - "magicast": "^0.3.5", - "std-env": "^3.9.0", - "test-exclude": "^7.0.1", - "tinyrainbow": "^2.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@vitest/browser": "3.2.4", - "vitest": "3.2.4" - }, - "peerDependenciesMeta": { - "@vitest/browser": { - "optional": true - } + "node_modules/@walletconnect/safe-json/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, + "node_modules/@walletconnect/sign-client": { + "version": "2.21.1", + "resolved": "https://registry.npmjs.org/@walletconnect/sign-client/-/sign-client-2.21.1.tgz", + "integrity": "sha512-QaXzmPsMnKGV6tc4UcdnQVNOz4zyXgarvdIQibJ4L3EmLat73r5ZVl4c0cCOcoaV7rgM9Wbphgu5E/7jNcd3Zg==", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/core": "2.21.1", + "@walletconnect/events": "1.0.1", + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/logger": "2.1.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.21.1", + "@walletconnect/utils": "2.21.1", + "events": "3.3.0" } }, - "node_modules/@vitest/coverage-v8/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, + "node_modules/@walletconnect/time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@walletconnect/time/-/time-1.0.2.tgz", + "integrity": "sha512-uzdd9woDcJ1AaBZRhqy5rNC9laqWGErfc4dxA9a87mPdKOgWMD85mcFo9dIYIts/Jwocfwn07EC6EzclKubk/g==", "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "tslib": "1.14.1" } }, - "node_modules/@vitest/coverage-v8/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "license": "ISC", + "node_modules/@walletconnect/time/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, + "node_modules/@walletconnect/types": { + "version": "2.21.1", + "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-2.21.1.tgz", + "integrity": "sha512-UeefNadqP6IyfwWC1Yi7ux+ljbP2R66PLfDrDm8izmvlPmYlqRerJWJvYO4t0Vvr9wrG4Ko7E0c4M7FaPKT/sQ==", + "license": "Apache-2.0", "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" + "@walletconnect/events": "1.0.1", + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "2.1.2", + "events": "3.3.0" + } + }, + "node_modules/@walletconnect/universal-provider": { + "version": "2.21.1", + "resolved": "https://registry.npmjs.org/@walletconnect/universal-provider/-/universal-provider-2.21.1.tgz", + "integrity": "sha512-Wjx9G8gUHVMnYfxtasC9poGm8QMiPCpXpbbLFT+iPoQskDDly8BwueWnqKs4Mx2SdIAWAwuXeZ5ojk5qQOxJJg==", + "license": "Apache-2.0", + "dependencies": { + "@walletconnect/events": "1.0.1", + "@walletconnect/jsonrpc-http-connection": "1.0.8", + "@walletconnect/jsonrpc-provider": "1.0.14", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "2.1.2", + "@walletconnect/sign-client": "2.21.1", + "@walletconnect/types": "2.21.1", + "@walletconnect/utils": "2.21.1", + "es-toolkit": "1.33.0", + "events": "3.3.0" + } + }, + "node_modules/@walletconnect/utils": { + "version": "2.21.1", + "resolved": "https://registry.npmjs.org/@walletconnect/utils/-/utils-2.21.1.tgz", + "integrity": "sha512-VPZvTcrNQCkbGOjFRbC24mm/pzbRMUq2DSQoiHlhh0X1U7ZhuIrzVtAoKsrzu6rqjz0EEtGxCr3K1TGRqDG4NA==", + "license": "Apache-2.0", + "dependencies": { + "@noble/ciphers": "1.2.1", + "@noble/curves": "1.8.1", + "@noble/hashes": "1.7.1", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/relay-api": "1.0.11", + "@walletconnect/relay-auth": "1.1.0", + "@walletconnect/safe-json": "1.0.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.21.1", + "@walletconnect/window-getters": "1.0.1", + "@walletconnect/window-metadata": "1.0.1", + "bs58": "6.0.0", + "detect-browser": "5.3.0", + "query-string": "7.1.3", + "uint8arrays": "3.1.0", + "viem": "2.23.2" + } + }, + "node_modules/@walletconnect/utils/node_modules/@noble/ciphers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.2.1.tgz", + "integrity": "sha512-rONPWMC7PeExE077uLE4oqWrZ1IvAfz3oH9LibVAcVCopJiA9R62uavnbEzdkVmJYI6M6Zgkbeb07+tWjlq2XA==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@vitest/coverage-v8/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", + "node_modules/@walletconnect/utils/node_modules/@noble/curves": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.1.tgz", + "integrity": "sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==", + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.1" + "@noble/hashes": "1.7.1" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "^14.21.3 || >=16" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@vitest/coverage-v8/node_modules/test-exclude": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", - "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", - "dev": true, - "license": "ISC", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^10.4.1", - "minimatch": "^9.0.4" - }, + "node_modules/@walletconnect/utils/node_modules/@noble/hashes": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz", + "integrity": "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==", + "license": "MIT", "engines": { - "node": ">=18" + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@vitest/expect": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz", - "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==", - "dev": true, + "node_modules/@walletconnect/utils/node_modules/@scure/bip32": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.6.2.tgz", + "integrity": "sha512-t96EPDMbtGgtb7onKKqxRLfE5g05k7uHnHRM2xdE6BP/ZmxaLtPek4J4KfVn/90IQNrU1IOAqMgiDtUdtbe3nw==", "license": "MIT", "dependencies": { - "@types/chai": "^5.2.2", - "@vitest/spy": "3.2.4", - "@vitest/utils": "3.2.4", - "chai": "^5.2.0", - "tinyrainbow": "^2.0.0" + "@noble/curves": "~1.8.1", + "@noble/hashes": "~1.7.1", + "@scure/base": "~1.2.2" }, "funding": { - "url": "https://opencollective.com/vitest" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@vitest/mocker": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz", - "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", - "dev": true, + "node_modules/@walletconnect/utils/node_modules/@scure/bip39": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.5.4.tgz", + "integrity": "sha512-TFM4ni0vKvCfBpohoh+/lY05i9gRbSwXWngAsF4CABQxoaOHijxuaZ2R6cStDQ5CHtHO9aGJTr4ksVJASRRyMA==", "license": "MIT", "dependencies": { - "@vitest/spy": "3.2.4", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.17" + "@noble/hashes": "~1.7.1", + "@scure/base": "~1.2.4" }, "funding": { - "url": "https://opencollective.com/vitest" + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@walletconnect/utils/node_modules/isows": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.6.tgz", + "integrity": "sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/@walletconnect/utils/node_modules/ox": { + "version": "0.6.7", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.6.7.tgz", + "integrity": "sha512-17Gk/eFsFRAZ80p5eKqv89a57uXjd3NgIf1CaXojATPBuujVc/fQSVhBeAU9JCRB+k7J50WQAyWTxK19T9GgbA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@adraffy/ens-normalize": "^1.10.1", + "@noble/curves": "^1.6.0", + "@noble/hashes": "^1.5.0", + "@scure/bip32": "^1.5.0", + "@scure/bip39": "^1.4.0", + "abitype": "^1.0.6", + "eventemitter3": "5.0.1" }, "peerDependencies": { - "msw": "^2.4.9", - "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + "typescript": ">=5.4.0" }, "peerDependenciesMeta": { - "msw": { - "optional": true - }, - "vite": { + "typescript": { "optional": true } } }, - "node_modules/@vitest/pretty-format": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz", - "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", - "dev": true, + "node_modules/@walletconnect/utils/node_modules/viem": { + "version": "2.23.2", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.23.2.tgz", + "integrity": "sha512-NVmW/E0c5crMOtbEAqMF0e3NmvQykFXhLOc/CkLIXOlzHSA6KXVz3CYVmaKqBF8/xtjsjHAGjdJN3Ru1kFJLaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], "license": "MIT", "dependencies": { - "tinyrainbow": "^2.0.0" + "@noble/curves": "1.8.1", + "@noble/hashes": "1.7.1", + "@scure/bip32": "1.6.2", + "@scure/bip39": "1.5.4", + "abitype": "1.0.8", + "isows": "1.0.6", + "ox": "0.6.7", + "ws": "8.18.0" }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.4.tgz", - "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/utils": "3.2.4", - "pathe": "^2.0.3", - "strip-literal": "^3.0.0" + "peerDependencies": { + "typescript": ">=5.0.4" }, - "funding": { - "url": "https://opencollective.com/vitest" + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@vitest/snapshot": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.4.tgz", - "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==", - "dev": true, + "node_modules/@walletconnect/utils/node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "3.2.4", - "magic-string": "^0.30.17", - "pathe": "^2.0.3" + "engines": { + "node": ">=10.0.0" }, - "funding": { - "url": "https://opencollective.com/vitest" + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, - "node_modules/@vitest/spy": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz", - "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==", - "dev": true, + "node_modules/@walletconnect/window-getters": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@walletconnect/window-getters/-/window-getters-1.0.1.tgz", + "integrity": "sha512-vHp+HqzGxORPAN8gY03qnbTMnhqIwjeRJNOMOAzePRg4xVEEE2WvYsI9G2NMjOknA8hnuYbU3/hwLcKbjhc8+Q==", "license": "MIT", "dependencies": { - "tinyspy": "^4.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "tslib": "1.14.1" } }, - "node_modules/@vitest/utils": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz", - "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==", - "dev": true, + "node_modules/@walletconnect/window-getters/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, + "node_modules/@walletconnect/window-metadata": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@walletconnect/window-metadata/-/window-metadata-1.0.1.tgz", + "integrity": "sha512-9koTqyGrM2cqFRW517BPY/iEtUDx2r1+Pwwu5m7sJ7ka79wi3EyqhqcICk/yDmv6jAS1rjKgTKXlEhanYjijcA==", "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.2.4", - "loupe": "^3.1.4", - "tinyrainbow": "^2.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "@walletconnect/window-getters": "^1.0.1", + "tslib": "1.14.1" } }, + "node_modules/@walletconnect/window-metadata/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, "node_modules/@xmldom/xmldom": { "version": "0.8.10", "license": "MIT", @@ -5900,7 +10089,6 @@ "node_modules/anymatch": { "version": "3.1.3", "license": "ISC", - "peer": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -5912,7 +10100,6 @@ "node_modules/anymatch/node_modules/picomatch": { "version": "2.3.1", "license": "MIT", - "peer": true, "engines": { "node": ">=8.6" }, @@ -6089,14 +10276,31 @@ "license": "MIT", "peer": true }, + "node_modules/async-mutex": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.2.6.tgz", + "integrity": "sha512-Hs4R+4SPgamu6rSGW8C7cV9gaWUKEHykfzCCvIRuaVv636Ju10ZdeUbvb4TBEW0INuq2DHZqXbK4Nd3yG4RaRw==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + } + }, "node_modules/asynckit": { "version": "0.4.0", "dev": true, "license": "MIT" }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/available-typed-arrays": { "version": "1.0.7", - "dev": true, "license": "MIT", "dependencies": { "possible-typed-array-names": "^1.0.0" @@ -6344,7 +10548,6 @@ }, "node_modules/base-x": { "version": "5.0.1", - "dev": true, "license": "MIT" }, "node_modules/base64-js": { @@ -6414,6 +10617,19 @@ "node": ">=0.6" } }, + "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", "dev": true, @@ -6477,7 +10693,6 @@ }, "node_modules/bn.js": { "version": "5.2.2", - "dev": true, "license": "MIT" }, "node_modules/body-parser": { @@ -6524,6 +10739,12 @@ "base-x": "^3.0.2" } }, + "node_modules/bowser": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.12.1.tgz", + "integrity": "sha512-z4rE2Gxh7tvshQ4hluIT7XcFrgLIQaw9X3A+kTTRdovCz5PMukm/0QC/BKSYPj3omF5Qfypn9O/c5kgpmvYUCw==", + "license": "MIT" + }, "node_modules/bplist-creator": { "version": "0.1.0", "license": "MIT", @@ -6594,7 +10815,6 @@ }, "node_modules/bs58": { "version": "6.0.0", - "dev": true, "license": "MIT", "dependencies": { "base-x": "^5.0.0" @@ -6610,7 +10830,6 @@ }, "node_modules/buffer": { "version": "6.0.3", - "dev": true, "funding": [ { "type": "github", @@ -6640,7 +10859,6 @@ "version": "4.0.9", "hasInstallScript": true, "license": "MIT", - "optional": true, "dependencies": { "node-gyp-build": "^4.3.0" }, @@ -6667,7 +10885,6 @@ }, "node_modules/call-bind": { "version": "1.0.8", - "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.0", @@ -6740,7 +10957,6 @@ "node_modules/camelcase": { "version": "5.3.1", "license": "MIT", - "peer": true, "engines": { "node": ">=6" } @@ -6764,6 +10980,24 @@ "license": "CC-BY-4.0", "peer": true }, + "node_modules/cbw-sdk": { + "name": "@coinbase/wallet-sdk", + "version": "3.9.3", + "resolved": "https://registry.npmjs.org/@coinbase/wallet-sdk/-/wallet-sdk-3.9.3.tgz", + "integrity": "sha512-N/A2DRIf0Y3PHc1XAMvbBUu4zisna6qAdqABMZwBMNEfWrXpAwx16pZGkYCLGE+Rvv1edbcB2LYDRnACNcmCiw==", + "license": "Apache-2.0", + "dependencies": { + "bn.js": "^5.2.1", + "buffer": "^6.0.3", + "clsx": "^1.2.1", + "eth-block-tracker": "^7.1.0", + "eth-json-rpc-filters": "^6.0.0", + "eventemitter3": "^5.0.1", + "keccak": "^3.0.3", + "preact": "^10.16.0", + "sha.js": "^2.4.11" + } + }, "node_modules/chai": { "version": "5.3.3", "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", @@ -6783,7 +11017,6 @@ }, "node_modules/chalk": { "version": "5.4.1", - "dev": true, "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" @@ -6802,6 +11035,21 @@ "node": ">= 16" } }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/chownr": { "version": "3.0.0", "license": "BlueOak-1.0.0", @@ -7113,6 +11361,12 @@ "node": ">= 0.6" } }, + "node_modules/cookie-es": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-1.2.2.tgz", + "integrity": "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==", + "license": "MIT" + }, "node_modules/cookie-signature": { "version": "1.2.2", "license": "MIT", @@ -7149,6 +11403,12 @@ "url": "https://opencollective.com/core-js" } }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" + }, "node_modules/cors": { "version": "2.8.5", "license": "MIT", @@ -7174,6 +11434,18 @@ "node": ">=4" } }, + "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/cron-schedule": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/cron-schedule/-/cron-schedule-5.0.4.tgz", @@ -7186,7 +11458,6 @@ }, "node_modules/cross-fetch": { "version": "3.2.0", - "dev": true, "license": "MIT", "dependencies": { "node-fetch": "^2.7.0" @@ -7204,6 +11475,15 @@ "node": ">= 8" } }, + "node_modules/crossws": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/crossws/-/crossws-0.3.5.tgz", + "integrity": "sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==", + "license": "MIT", + "dependencies": { + "uncrypto": "^0.1.3" + } + }, "node_modules/crypto-random-string": { "version": "2.0.0", "license": "MIT", @@ -7328,6 +11608,28 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "license": "MIT" + }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -7345,11 +11647,29 @@ } } }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/decimal.js": { "version": "10.5.0", "dev": true, "license": "MIT" }, + "node_modules/decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, "node_modules/decompress-response": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", @@ -7407,7 +11727,6 @@ }, "node_modules/define-data-property": { "version": "1.1.4", - "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", @@ -7445,6 +11764,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "license": "MIT" + }, "node_modules/delay": { "version": "5.0.0", "dev": true, @@ -7488,6 +11813,21 @@ "node": ">=6" } }, + "node_modules/derive-valtio": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/derive-valtio/-/derive-valtio-0.1.0.tgz", + "integrity": "sha512-OCg2UsLbXK7GmmpzMXhYkdO64vhJ1ROUUGaTFyHjVwEdMEcTTRj7W1TxLbSBxdY8QLBPCcp66MTyaSy0RpO17A==", + "license": "MIT", + "peerDependencies": { + "valtio": "*" + } + }, + "node_modules/destr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", + "license": "MIT" + }, "node_modules/destroy": { "version": "1.2.0", "license": "MIT", @@ -7497,6 +11837,12 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-browser": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/detect-browser/-/detect-browser-5.3.0.tgz", + "integrity": "sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w==", + "license": "MIT" + }, "node_modules/detect-libc": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", @@ -7515,6 +11861,12 @@ "wrappy": "1" } }, + "node_modules/dijkstrajs": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", + "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==", + "license": "MIT" + }, "node_modules/doctrine": { "version": "2.1.0", "dev": true, @@ -7562,10 +11914,39 @@ "node": ">= 0.4" } }, + "node_modules/duplexify": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz", + "integrity": "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.2" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "license": "MIT" }, + "node_modules/eciesjs": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/eciesjs/-/eciesjs-0.4.15.tgz", + "integrity": "sha512-r6kEJXDKecVOCj2nLMuXK/FCPeurW33+3JRpfXVbjLja3XUYFfD9I/JBreH6sUyzcm3G/YQboBjMla6poKeSdA==", + "license": "MIT", + "dependencies": { + "@ecies/ciphers": "^0.2.3", + "@noble/ciphers": "^1.3.0", + "@noble/curves": "^1.9.1", + "@noble/hashes": "^1.8.0" + }, + "engines": { + "bun": ">=1", + "deno": ">=2", + "node": ">=16" + } + }, "node_modules/ee-first": { "version": "1.1.1", "license": "MIT" @@ -7579,6 +11960,12 @@ "version": "8.0.0", "license": "MIT" }, + "node_modules/encode-utf8": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz", + "integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==", + "license": "MIT" + }, "node_modules/encodeurl": { "version": "2.0.0", "license": "MIT", @@ -7595,6 +11982,66 @@ "once": "^1.4.0" } }, + "node_modules/engine.io-client": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz", + "integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==", + "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.1.1" + } + }, + "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/entities": { "version": "6.0.1", "dev": true, @@ -7769,6 +12216,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-toolkit": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.33.0.tgz", + "integrity": "sha512-X13Q/ZSc+vsO1q600bvNK4bxgXMkHcf//RxCmYDaRY5DAcT+eoXjY5hoAPGMdRnWQjvyLEcyauG3b6hz76LNqg==", + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks" + ] + }, "node_modules/es6-promise": { "version": "4.2.8", "dev": true, @@ -8228,6 +12685,166 @@ "node": ">= 0.6" } }, + "node_modules/eth-block-tracker": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/eth-block-tracker/-/eth-block-tracker-7.1.0.tgz", + "integrity": "sha512-8YdplnuE1IK4xfqpf4iU7oBxnOYAc35934o083G8ao+8WM8QQtt/mVlAY6yIAdY1eMeLqg4Z//PZjJGmWGPMRg==", + "license": "MIT", + "dependencies": { + "@metamask/eth-json-rpc-provider": "^1.0.0", + "@metamask/safe-event-emitter": "^3.0.0", + "@metamask/utils": "^5.0.1", + "json-rpc-random-id": "^1.0.1", + "pify": "^3.0.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/eth-block-tracker/node_modules/@metamask/utils": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-5.0.2.tgz", + "integrity": "sha512-yfmE79bRQtnMzarnKfX7AEJBwFTxvTyw3nBQlu/5rmGXrjAeAMltoGxO62TFurxrQAFMNa/fEjIHNvungZp0+g==", + "license": "ISC", + "dependencies": { + "@ethereumjs/tx": "^4.1.2", + "@types/debug": "^4.1.7", + "debug": "^4.3.4", + "semver": "^7.3.8", + "superstruct": "^1.0.3" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/eth-block-tracker/node_modules/superstruct": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-1.0.4.tgz", + "integrity": "sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/eth-json-rpc-filters": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/eth-json-rpc-filters/-/eth-json-rpc-filters-6.0.1.tgz", + "integrity": "sha512-ITJTvqoCw6OVMLs7pI8f4gG92n/St6x80ACtHodeS+IXmO0w+t1T5OOzfSt7KLSMLRkVUoexV7tztLgDxg+iig==", + "license": "ISC", + "dependencies": { + "@metamask/safe-event-emitter": "^3.0.0", + "async-mutex": "^0.2.6", + "eth-query": "^2.1.2", + "json-rpc-engine": "^6.1.0", + "pify": "^5.0.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/eth-json-rpc-filters/node_modules/pify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", + "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eth-query": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/eth-query/-/eth-query-2.1.2.tgz", + "integrity": "sha512-srES0ZcvwkR/wd5OQBRA1bIJMww1skfGS0s8wlwK3/oNP4+wnds60krvu5R1QbpRQjMmpG5OMIWro5s7gvDPsA==", + "license": "ISC", + "dependencies": { + "json-rpc-random-id": "^1.0.0", + "xtend": "^4.0.1" + } + }, + "node_modules/eth-rpc-errors": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eth-rpc-errors/-/eth-rpc-errors-4.0.3.tgz", + "integrity": "sha512-Z3ymjopaoft7JDoxZcEb3pwdGh7yiYMhOwm2doUt6ASXlMavpNlK6Cre0+IMl2VSGyEU9rkiperQhp5iRxn5Pg==", + "license": "MIT", + "dependencies": { + "fast-safe-stringify": "^2.0.6" + } + }, + "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/event-target-polyfill": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/event-target-polyfill/-/event-target-polyfill-0.0.4.tgz", @@ -8243,10 +12860,25 @@ "node": ">=6" } }, + "node_modules/eventemitter2": { + "version": "6.4.9", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz", + "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==", + "license": "MIT" + }, "node_modules/eventemitter3": { "version": "5.0.1", "license": "MIT" }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, "node_modules/eventsource": { "version": "3.0.7", "license": "MIT", @@ -8632,6 +13264,19 @@ "express": "^4.11 || 5 || ^5.0.0-beta.1" } }, + "node_modules/extension-port-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/extension-port-stream/-/extension-port-stream-3.0.0.tgz", + "integrity": "sha512-an2S5quJMiy5bnZKEf6AkfH/7r8CzHvhchU40gxN+OM6HPhe7Z9T1FUychcf2M9PpPOO0Hf7BAEfJkw2TDIBDw==", + "license": "ISC", + "dependencies": { + "readable-stream": "^3.6.2 || ^4.4.2", + "webextension-polyfill": ">=0.10.0 <1.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/eyes": { "version": "0.1.8", "dev": true, @@ -8678,9 +13323,17 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-redact": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", + "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/fast-safe-stringify": { "version": "2.1.1", - "dev": true, "license": "MIT" }, "node_modules/fast-stable-stringify": { @@ -8690,7 +13343,6 @@ }, "node_modules/fastestsmallesttextencoderdecoder": { "version": "1.0.22", - "dev": true, "license": "CC0-1.0", "peer": true }, @@ -8767,6 +13419,15 @@ "node": ">=8" } }, + "node_modules/filter-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", + "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/finalhandler": { "version": "2.1.0", "license": "MIT", @@ -8785,7 +13446,6 @@ "node_modules/find-up": { "version": "4.1.0", "license": "MIT", - "peer": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -8823,7 +13483,6 @@ }, "node_modules/for-each": { "version": "0.3.5", - "dev": true, "license": "MIT", "dependencies": { "is-callable": "^1.2.7" @@ -8998,7 +13657,6 @@ "node_modules/get-caller-file": { "version": "2.0.5", "license": "ISC", - "peer": true, "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -9163,6 +13821,23 @@ "dev": true, "license": "MIT" }, + "node_modules/h3": { + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.4.tgz", + "integrity": "sha512-z5cFQWDffyOe4vQ9xIqNfCZdV4p//vy6fBnr8Q1AWnVZ0teurKMG66rLj++TKwKPUP3u7iMUvrvKaEUiQw2QWQ==", + "license": "MIT", + "dependencies": { + "cookie-es": "^1.2.2", + "crossws": "^0.3.5", + "defu": "^6.1.4", + "destr": "^2.0.5", + "iron-webcrypto": "^1.2.1", + "node-mock-http": "^1.0.2", + "radix3": "^1.1.2", + "ufo": "^1.6.1", + "uncrypto": "^0.1.3" + } + }, "node_modules/happy-dom": { "version": "15.11.7", "dev": true, @@ -9215,7 +13890,6 @@ }, "node_modules/has-property-descriptors": { "version": "1.0.2", - "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0" @@ -9250,7 +13924,6 @@ }, "node_modules/has-tostringtag": { "version": "1.0.2", - "dev": true, "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" @@ -9514,6 +14187,31 @@ "node": ">= 0.10" } }, + "node_modules/iron-webcrypto": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz", + "integrity": "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/brc-dd" + } + }, + "node_modules/is-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-array-buffer": { "version": "3.0.5", "dev": true, @@ -9584,7 +14282,6 @@ }, "node_modules/is-callable": { "version": "1.2.7", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -9690,7 +14387,6 @@ }, "node_modules/is-generator-function": { "version": "1.1.0", - "dev": true, "license": "MIT", "dependencies": { "call-bound": "^1.0.3", @@ -9788,7 +14484,6 @@ }, "node_modules/is-regex": { "version": "1.2.1", - "dev": true, "license": "MIT", "dependencies": { "call-bound": "^1.0.2", @@ -9828,6 +14523,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-string": { "version": "1.1.1", "dev": true, @@ -9861,7 +14568,6 @@ }, "node_modules/is-typed-array": { "version": "1.1.15", - "dev": true, "license": "MIT", "dependencies": { "which-typed-array": "^1.1.16" @@ -9926,7 +14632,6 @@ }, "node_modules/isarray": { "version": "2.0.5", - "dev": true, "license": "MIT" }, "node_modules/isexe": { @@ -10521,6 +15226,31 @@ "license": "MIT", "peer": true }, + "node_modules/json-rpc-engine": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/json-rpc-engine/-/json-rpc-engine-6.1.0.tgz", + "integrity": "sha512-NEdLrtrq1jUZyfjkr9OCz9EzCNhnRyWtt1PAnvnhwy6e8XETS0Dtc+ZNCO2gvuAoKsIn2+vCSowXTYE4CkgnAQ==", + "license": "ISC", + "dependencies": { + "@metamask/safe-event-emitter": "^2.0.0", + "eth-rpc-errors": "^4.0.2" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/json-rpc-engine/node_modules/@metamask/safe-event-emitter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@metamask/safe-event-emitter/-/safe-event-emitter-2.0.0.tgz", + "integrity": "sha512-/kSXhY692qiV1MXu6EeOZvg5nECLclxNXcKCxJ3cXQgYuRymRHpdx/t7JXfsK+JLjwA1e1c1/SBrlQYpusC29Q==", + "license": "ISC" + }, + "node_modules/json-rpc-random-id": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz", + "integrity": "sha512-RJ9YYNCkhVDBuP4zN5BBtYAzEl03yq/jIIsyif0JY9qyJuQQZNeDK7anAPKKlyEtLSj2s8h6hNh2F8zO5q7ScA==", + "license": "ISC" + }, "node_modules/json-schema": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", @@ -10553,6 +15283,21 @@ "node": ">=6" } }, + "node_modules/keccak": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz", + "integrity": "sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/keyv": { "version": "4.5.4", "dev": true, @@ -10561,6 +15306,12 @@ "json-buffer": "3.0.1" } }, + "node_modules/keyvaluestorage-interface": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/keyvaluestorage-interface/-/keyvaluestorage-interface-1.0.0.tgz", + "integrity": "sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g==", + "license": "MIT" + }, "node_modules/kleur": { "version": "3.0.3", "license": "MIT", @@ -10662,10 +15413,40 @@ "license": "MIT", "peer": true }, + "node_modules/lit": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lit/-/lit-3.3.0.tgz", + "integrity": "sha512-DGVsqsOIHBww2DqnuZzW7QsuCdahp50ojuDaBPC7jUDRpYoH0z7kHBBYZewRzer75FwtrkmkKk7iOAwSaWdBmw==", + "license": "BSD-3-Clause", + "dependencies": { + "@lit/reactive-element": "^2.1.0", + "lit-element": "^4.2.0", + "lit-html": "^3.3.0" + } + }, + "node_modules/lit-element": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.2.1.tgz", + "integrity": "sha512-WGAWRGzirAgyphK2urmYOV72tlvnxw7YfyLDgQ+OZnM9vQQBQnumQ7jUJe6unEzwGU3ahFOjuz1iz1jjrpCPuw==", + "license": "BSD-3-Clause", + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.4.0", + "@lit/reactive-element": "^2.1.0", + "lit-html": "^3.3.0" + } + }, + "node_modules/lit-html": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.3.1.tgz", + "integrity": "sha512-S9hbyDu/vs1qNrithiNyeyv64c9yqiW9l+DBgI18fL+MTvOtWoFR0FWiyq1TxaYef5wNlpEmzlXoBlZEO+WjoA==", + "license": "BSD-3-Clause", + "dependencies": { + "@types/trusted-types": "^2.0.2" + } + }, "node_modules/locate-path": { "version": "5.0.0", "license": "MIT", - "peer": true, "dependencies": { "p-locate": "^4.1.0" }, @@ -10673,6 +15454,12 @@ "node": ">=8" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, "node_modules/lodash.debounce": { "version": "4.0.8", "license": "MIT", @@ -11257,6 +16044,12 @@ "node": ">=8" } }, + "node_modules/micro-ftch": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/micro-ftch/-/micro-ftch-0.3.1.tgz", + "integrity": "sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==", + "license": "MIT" + }, "node_modules/micromatch": { "version": "4.0.8", "license": "MIT", @@ -11400,6 +16193,26 @@ "node": ">= 18" } }, + "node_modules/mipd": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mipd/-/mipd-0.0.7.tgz", + "integrity": "sha512-aAPZPNDQ3uMTdKbuO2YmAw2TxLHO0moa4YKAyETM/DTj5FloZo+a+8tU+iv4GmW+sOxKLSRwcSFuczk+Cpt6fg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wagmi-dev" + } + ], + "license": "MIT", + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/mkdirp": { "version": "1.0.4", "license": "MIT", @@ -11421,6 +16234,12 @@ "version": "2.1.3", "license": "MIT" }, + "node_modules/multiformats": { + "version": "9.9.0", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz", + "integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==", + "license": "(Apache-2.0 AND MIT)" + }, "node_modules/mz": { "version": "2.7.0", "license": "MIT", @@ -11482,9 +16301,14 @@ "node": ">=10" } }, + "node_modules/node-addon-api": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", + "license": "MIT" + }, "node_modules/node-fetch": { "version": "2.7.0", - "dev": true, "license": "MIT", "dependencies": { "whatwg-url": "^5.0.0" @@ -11501,6 +16325,12 @@ } } }, + "node_modules/node-fetch-native": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", + "license": "MIT" + }, "node_modules/node-forge": { "version": "1.3.1", "license": "(BSD-3-Clause OR GPL-2.0)", @@ -11512,7 +16342,6 @@ "node_modules/node-gyp-build": { "version": "4.8.4", "license": "MIT", - "optional": true, "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", @@ -11524,6 +16353,12 @@ "license": "MIT", "peer": true }, + "node_modules/node-mock-http": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.3.tgz", + "integrity": "sha512-jN8dK25fsfnMrVsEhluUTPkBFY+6ybu7jSB1n+ri/vOGjJxU8J9CZhpSGkHXSkFjtUhbmoncG/YG9ta5Ludqog==", + "license": "MIT" + }, "node_modules/node-mocks-http": { "version": "1.17.2", "dev": true, @@ -11650,7 +16485,6 @@ "node_modules/normalize-path": { "version": "3.0.0", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -11697,6 +16531,53 @@ "node": ">=18.18" } }, + "node_modules/obj-multiplex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/obj-multiplex/-/obj-multiplex-1.0.0.tgz", + "integrity": "sha512-0GNJAOsHoBHeNTvl5Vt6IWnpUEcc3uSRxzBri7EDyIcMgYvnY2JL2qdeV5zTMjWQX5OHcD5amcW2HFfDh0gjIA==", + "license": "ISC", + "dependencies": { + "end-of-stream": "^1.4.0", + "once": "^1.4.0", + "readable-stream": "^2.3.3" + } + }, + "node_modules/obj-multiplex/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/obj-multiplex/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/obj-multiplex/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/obj-multiplex/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "license": "MIT", @@ -11788,6 +16669,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/ofetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.4.1.tgz", + "integrity": "sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw==", + "license": "MIT", + "dependencies": { + "destr": "^2.0.3", + "node-fetch-native": "^1.6.4", + "ufo": "^1.5.4" + } + }, + "node_modules/on-exit-leak-free": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-0.2.0.tgz", + "integrity": "sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg==", + "license": "MIT" + }, "node_modules/on-finished": { "version": "2.4.1", "license": "MIT", @@ -12001,7 +16899,6 @@ "node_modules/p-limit": { "version": "2.3.0", "license": "MIT", - "peer": true, "dependencies": { "p-try": "^2.0.0" }, @@ -12015,7 +16912,6 @@ "node_modules/p-locate": { "version": "4.1.0", "license": "MIT", - "peer": true, "dependencies": { "p-limit": "^2.2.0" }, @@ -12026,7 +16922,6 @@ "node_modules/p-try": { "version": "2.2.0", "license": "MIT", - "peer": true, "engines": { "node": ">=6" } @@ -12222,6 +17117,53 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/pino": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-7.11.0.tgz", + "integrity": "sha512-dMACeu63HtRLmCG8VKdy4cShCPKaYDR4youZqoSWLxl5Gu99HUw8bw75thbPv9Nip+H+QYX8o3ZJbTdVZZ2TVg==", + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.0.0", + "on-exit-leak-free": "^0.2.0", + "pino-abstract-transport": "v0.5.0", + "pino-std-serializers": "^4.0.0", + "process-warning": "^1.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.1.0", + "safe-stable-stringify": "^2.1.0", + "sonic-boom": "^2.2.1", + "thread-stream": "^0.15.1" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-0.5.0.tgz", + "integrity": "sha512-+KAgmVeqXYbTtU2FScx1XS3kNyfZ5TrXY07V96QnUSFqo2gAqlvmaxH67Lj7SWazqsMabf+58ctdTcBgnOLUOQ==", + "license": "MIT", + "dependencies": { + "duplexify": "^4.1.2", + "split2": "^4.0.0" + } + }, + "node_modules/pino-std-serializers": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-4.0.0.tgz", + "integrity": "sha512-cK0pekc1Kjy5w9V2/n+8MkZwusa6EyyxfeQCB799CQRhRt/CqYKiWs5adeu8Shve2ZNffvfC/7J64A2PJo1W/Q==", + "license": "MIT" + }, "node_modules/pirates": { "version": "4.0.7", "license": "MIT", @@ -12258,9 +17200,17 @@ "node": ">=4.0.0" } }, + "node_modules/pony-cause": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/pony-cause/-/pony-cause-2.1.11.tgz", + "integrity": "sha512-M7LhCsdNbNgiLYiP4WjsfLUuFmCfnjdF6jKe2R9NKl4WFN+HZPGHJZ9lnLP7f9ZnKe3U9nuWD0szirmj+migUg==", + "license": "0BSD", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/possible-typed-array-names": { "version": "1.1.0", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -12369,6 +17319,18 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, + "node_modules/process-warning": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-1.0.0.tgz", + "integrity": "sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==", + "license": "MIT" + }, "node_modules/progress": { "version": "2.0.3", "license": "MIT", @@ -12408,6 +17370,12 @@ "node": ">= 0.10" } }, + "node_modules/proxy-compare": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-2.6.0.tgz", + "integrity": "sha512-8xuCeM3l8yqdmbPoYeLbrAXCBWu19XEYc5/F28f5qOaoAIMyfmBUkl5axiK+x9olUvRlcekvnm98AP9RDngOIw==", + "license": "MIT" + }, "node_modules/pump": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", @@ -12425,6 +17393,24 @@ "node": ">=6" } }, + "node_modules/qrcode": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.3.tgz", + "integrity": "sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==", + "license": "MIT", + "dependencies": { + "dijkstrajs": "^1.0.1", + "encode-utf8": "^1.0.3", + "pngjs": "^5.0.0", + "yargs": "^15.3.1" + }, + "bin": { + "qrcode": "bin/qrcode" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/qrcode-generator": { "version": "1.4.4", "dev": true, @@ -12437,6 +17423,96 @@ "qrcode-terminal": "bin/qrcode-terminal.js" } }, + "node_modules/qrcode/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/qrcode/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/qrcode/node_modules/pngjs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", + "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/qrcode/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "license": "ISC" + }, + "node_modules/qrcode/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "license": "MIT", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/qs": { "version": "6.14.0", "license": "BSD-3-Clause", @@ -12450,6 +17526,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/query-string": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz", + "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==", + "license": "MIT", + "dependencies": { + "decode-uri-component": "^0.2.2", + "filter-obj": "^1.1.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/queue": { "version": "6.0.2", "license": "MIT", @@ -12477,6 +17571,18 @@ ], "license": "MIT" }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", + "license": "MIT" + }, + "node_modules/radix3": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.2.tgz", + "integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==", + "license": "MIT" + }, "node_modules/range-parser": { "version": "1.2.1", "license": "MIT", @@ -12680,6 +17786,28 @@ "node": ">= 6" } }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/real-require": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.1.0.tgz", + "integrity": "sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg==", + "license": "MIT", + "engines": { + "node": ">= 12.13.0" + } + }, "node_modules/redis-errors": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", @@ -12816,7 +17944,6 @@ "node_modules/require-directory": { "version": "2.1.1", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -12829,6 +17956,12 @@ "node": ">=0.10.0" } }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "license": "ISC" + }, "node_modules/requireg": { "version": "0.2.2", "peer": true, @@ -13247,7 +18380,6 @@ }, "node_modules/safe-regex-test": { "version": "1.1.0", - "dev": true, "license": "MIT", "dependencies": { "call-bound": "^1.0.2", @@ -13261,6 +18393,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "license": "MIT" @@ -13337,9 +18478,14 @@ "node": ">= 18" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC" + }, "node_modules/set-function-length": { "version": "1.2.2", - "dev": true, "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", @@ -13384,6 +18530,26 @@ "version": "1.2.0", "license": "ISC" }, + "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/shebang-command": { "version": "2.0.0", "license": "MIT", @@ -13573,6 +18739,77 @@ "node": ">=8.0.0" } }, + "node_modules/socket.io-client": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz", + "integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.6.1", + "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.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser/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/sonic-boom": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-2.8.0.tgz", + "integrity": "sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg==", + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, "node_modules/source-map": { "version": "0.5.7", "license": "BSD-3-Clause", @@ -13605,6 +18842,24 @@ "node": ">=0.10.0" } }, + "node_modules/split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "license": "BSD-3-Clause", @@ -13701,6 +18956,21 @@ "stream-chain": "^2.2.5" } }, + "node_modules/stream-shift": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", + "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", + "license": "MIT" + }, + "node_modules/strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -14174,6 +19444,15 @@ "node": ">=0.8" } }, + "node_modules/thread-stream": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-0.15.2.tgz", + "integrity": "sha512-UkEhKIg2pD+fjkHQKyJO3yoIvAP3N6RlNFt2dUhcS1FGvCD1cQa1M/PGknCLFIyZdtJOWQjejp7bdNqmN7zwdA==", + "license": "MIT", + "dependencies": { + "real-require": "^0.1.0" + } + }, "node_modules/throat": { "version": "5.0.0", "license": "MIT", @@ -14255,6 +19534,20 @@ "license": "BSD-3-Clause", "peer": true }, + "node_modules/to-buffer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.1.tgz", + "integrity": "sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==", + "license": "MIT", + "dependencies": { + "isarray": "^2.0.5", + "safe-buffer": "^5.2.1", + "typed-array-buffer": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "license": "MIT", @@ -14285,7 +19578,6 @@ }, "node_modules/tr46": { "version": "0.0.3", - "dev": true, "license": "MIT" }, "node_modules/ts-api-utils": { @@ -14330,7 +19622,6 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, "license": "0BSD" }, "node_modules/tsx": { @@ -14412,7 +19703,6 @@ }, "node_modules/typed-array-buffer": { "version": "1.0.3", - "dev": true, "license": "MIT", "dependencies": { "call-bound": "^1.0.3", @@ -14482,7 +19772,6 @@ }, "node_modules/typescript": { "version": "5.8.3", - "devOptional": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -14492,6 +19781,21 @@ "node": ">=14.17" } }, + "node_modules/ufo": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", + "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", + "license": "MIT" + }, + "node_modules/uint8arrays": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.1.0.tgz", + "integrity": "sha512-ei5rfKtoRO8OyOIor2Rz5fhzjThwIHJZ3uyDPnDHTXbP0aMQ1RN/6AI5B5d9dBxJOU+BvOAk7ZQ1xphsX8Lrog==", + "license": "MIT", + "dependencies": { + "multiformats": "^9.4.2" + } + }, "node_modules/unbox-primitive": { "version": "1.1.0", "dev": true, @@ -14509,6 +19813,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/uncrypto": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz", + "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==", + "license": "MIT" + }, "node_modules/undici": { "version": "6.21.3", "license": "MIT", @@ -14575,6 +19885,108 @@ "node": ">= 0.8" } }, + "node_modules/unstorage": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.1.tgz", + "integrity": "sha512-KKGwRTT0iVBCErKemkJCLs7JdxNVfqTPc/85ae1XES0+bsHbc/sFBfVi5kJp156cc51BHinIH2l3k0EZ24vOBQ==", + "license": "MIT", + "dependencies": { + "anymatch": "^3.1.3", + "chokidar": "^4.0.3", + "destr": "^2.0.5", + "h3": "^1.15.4", + "lru-cache": "^10.4.3", + "node-fetch-native": "^1.6.7", + "ofetch": "^1.4.1", + "ufo": "^1.6.1" + }, + "peerDependencies": { + "@azure/app-configuration": "^1.8.0", + "@azure/cosmos": "^4.2.0", + "@azure/data-tables": "^13.3.0", + "@azure/identity": "^4.6.0", + "@azure/keyvault-secrets": "^4.9.0", + "@azure/storage-blob": "^12.26.0", + "@capacitor/preferences": "^6.0.3 || ^7.0.0", + "@deno/kv": ">=0.9.0", + "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", + "@planetscale/database": "^1.19.0", + "@upstash/redis": "^1.34.3", + "@vercel/blob": ">=0.27.1", + "@vercel/functions": "^2.2.12 || ^3.0.0", + "@vercel/kv": "^1.0.1", + "aws4fetch": "^1.0.20", + "db0": ">=0.2.1", + "idb-keyval": "^6.2.1", + "ioredis": "^5.4.2", + "uploadthing": "^7.4.4" + }, + "peerDependenciesMeta": { + "@azure/app-configuration": { + "optional": true + }, + "@azure/cosmos": { + "optional": true + }, + "@azure/data-tables": { + "optional": true + }, + "@azure/identity": { + "optional": true + }, + "@azure/keyvault-secrets": { + "optional": true + }, + "@azure/storage-blob": { + "optional": true + }, + "@capacitor/preferences": { + "optional": true + }, + "@deno/kv": { + "optional": true + }, + "@netlify/blobs": { + "optional": true + }, + "@planetscale/database": { + "optional": true + }, + "@upstash/redis": { + "optional": true + }, + "@vercel/blob": { + "optional": true + }, + "@vercel/functions": { + "optional": true + }, + "@vercel/kv": { + "optional": true + }, + "aws4fetch": { + "optional": true + }, + "db0": { + "optional": true + }, + "idb-keyval": { + "optional": true + }, + "ioredis": { + "optional": true + }, + "uploadthing": { + "optional": true + } + } + }, + "node_modules/unstorage/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, "node_modules/update-browserslist-db": { "version": "1.1.3", "funding": [ @@ -14611,11 +20023,19 @@ "punycode": "^2.1.0" } }, + "node_modules/use-sync-external-store": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz", + "integrity": "sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/utf-8-validate": { "version": "5.0.10", "hasInstallScript": true, "license": "MIT", - "optional": true, "dependencies": { "node-gyp-build": "^4.3.0" }, @@ -14623,6 +20043,19 @@ "node": ">=6.14.2" } }, + "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/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -14639,7 +20072,6 @@ }, "node_modules/uuid": { "version": "8.3.2", - "dev": true, "license": "MIT", "bin": { "uuid": "dist/bin/uuid" @@ -14653,6 +20085,41 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/valtio": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/valtio/-/valtio-1.13.2.tgz", + "integrity": "sha512-Qik0o+DSy741TmkqmRfjq+0xpZBXi/Y6+fXZLn0xNF1z/waFMbE3rkivv5Zcf9RrMUp6zswf2J7sbh2KBlba5A==", + "license": "MIT", + "dependencies": { + "derive-valtio": "0.1.0", + "proxy-compare": "2.6.0", + "use-sync-external-store": "1.2.0" + }, + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=16.8", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + } + } + }, + "node_modules/valtio/node_modules/use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/vary": { "version": "1.1.2", "license": "MIT", @@ -14894,6 +20361,31 @@ "node": ">=18" } }, + "node_modules/wagmi": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/wagmi/-/wagmi-2.17.0.tgz", + "integrity": "sha512-NxdS/oHG3j4l3JzNIAb0zL14p3GXOS9YU4Q3WS+0eTChFIfdqBrurQMImPLNC9P5rXYym6cjC2feeqhHVMJjpg==", + "license": "MIT", + "dependencies": { + "@wagmi/connectors": "5.10.0", + "@wagmi/core": "2.21.0", + "use-sync-external-store": "1.4.0" + }, + "funding": { + "url": "https://github.com/sponsors/wevm" + }, + "peerDependencies": { + "@tanstack/react-query": ">=5.0.0", + "react": ">=18", + "typescript": ">=5.0.4", + "viem": "2.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/walker": { "version": "1.0.8", "license": "Apache-2.0", @@ -14910,9 +20402,14 @@ "defaults": "^1.0.3" } }, + "node_modules/webextension-polyfill": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/webextension-polyfill/-/webextension-polyfill-0.10.0.tgz", + "integrity": "sha512-c5s35LgVa5tFaHhrZDnr3FpQpjj1BB+RXhLTYUxGqBVN460HkbM8TBtEqdXWbpTKfzwCcjAZVF7zXCYSKtcp9g==", + "license": "MPL-2.0" + }, "node_modules/webidl-conversions": { "version": "3.0.1", - "dev": true, "license": "BSD-2-Clause" }, "node_modules/whatwg-encoding": { @@ -14941,7 +20438,6 @@ }, "node_modules/whatwg-url": { "version": "5.0.0", - "dev": true, "license": "MIT", "dependencies": { "tr46": "~0.0.3", @@ -15063,9 +20559,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "license": "ISC" + }, "node_modules/which-typed-array": { "version": "1.1.19", - "dev": true, "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", @@ -15205,6 +20706,23 @@ } } }, + "node_modules/x402": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/x402/-/x402-0.6.1.tgz", + "integrity": "sha512-9UmeCSsYzFGav5FdVP70VplKlR3V90P0DZ9fPSrlLVp0ifUVi1S9TztvegkmIHE9xTGZ1GWNi+bkne6N0Ea58w==", + "license": "Apache-2.0", + "dependencies": { + "@scure/base": "^1.2.6", + "@solana-program/compute-budget": "^0.8.0", + "@solana-program/token": "^0.5.1", + "@solana-program/token-2022": "^0.4.2", + "@solana/kit": "^2.1.1", + "@solana/transaction-confirmation": "^2.1.1", + "viem": "^2.21.26", + "wagmi": "^2.15.6", + "zod": "^3.24.2" + } + }, "node_modules/xcode": { "version": "3.0.1", "license": "Apache-2.0", @@ -15266,6 +20784,23 @@ "dev": true, "license": "MIT" }, + "node_modules/xmlhttprequest-ssl": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", + "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, "node_modules/y18n": { "version": "5.0.8", "license": "ISC", @@ -15393,7 +20928,8 @@ "@atxp/common": "0.4.0", "@modelcontextprotocol/sdk": "^1.15.0", "bignumber.js": "^9.3.0", - "oauth4webapi": "^3.5.0" + "oauth4webapi": "^3.5.0", + "x402": "^0.6.1" }, "devDependencies": { "@solana/pay": "^0.2.5", diff --git a/packages/atxp-client/package.json b/packages/atxp-client/package.json index 2a7a18f4..c39a8bb4 100644 --- a/packages/atxp-client/package.json +++ b/packages/atxp-client/package.json @@ -36,7 +36,8 @@ "@atxp/common": "0.4.0", "@modelcontextprotocol/sdk": "^1.15.0", "bignumber.js": "^9.3.0", - "oauth4webapi": "^3.5.0" + "oauth4webapi": "^3.5.0", + "x402": "^0.6.1" }, "peerDependencies": { "@solana/pay": "^0.2.5", diff --git a/packages/atxp-client/src/basePaymentMaker.ts b/packages/atxp-client/src/basePaymentMaker.ts index 8e024e7d..7e12a58b 100644 --- a/packages/atxp-client/src/basePaymentMaker.ts +++ b/packages/atxp-client/src/basePaymentMaker.ts @@ -9,6 +9,7 @@ import { encodeFunctionData, WalletClient, PublicActions, + getAddress, } from "viem"; import { base } from "viem/chains"; import { BigNumber } from "bignumber.js"; @@ -205,7 +206,7 @@ export class BasePaymentMaker implements PaymentMaker { // Create EIP-3009 authorization parameters const validAfter = Math.floor(Date.now() / 1000); // Valid immediately - const validBefore = Math.floor(Date.now() / 1000) + 3600; // Valid for 1 hour + const validBefore = Math.floor(Date.now() / 1000) + 660; // Valid for 11 minutes (matching x402-fetch) const nonce = '0x' + Array.from(crypto.getRandomValues(new Uint8Array(32)), b => b.toString(16).padStart(2, '0')).join(''); // Convert amount to USDC units (6 decimals) @@ -217,7 +218,7 @@ export class BasePaymentMaker implements PaymentMaker { name: 'USD Coin', version: '2', chainId: base.id, // Base mainnet chain ID (8453) - verifyingContract: USDC_CONTRACT_ADDRESS_BASE as `0x${string}`, + verifyingContract: getAddress(USDC_CONTRACT_ADDRESS_BASE), }, types: { TransferWithAuthorization: [ @@ -231,8 +232,8 @@ export class BasePaymentMaker implements PaymentMaker { }, primaryType: 'TransferWithAuthorization' as const, message: { - from: this.signingClient.account!.address, - to: receiver as Address, + from: getAddress(this.signingClient.account!.address), + to: getAddress(receiver), value, validAfter: validAfter.toString(), validBefore: validBefore.toString(), @@ -252,8 +253,8 @@ export class BasePaymentMaker implements PaymentMaker { return { signature, authorization: { - from: this.signingClient.account!.address, - to: receiver, + from: getAddress(this.signingClient.account!.address), + to: getAddress(receiver), value, validAfter: validAfter.toString(), validBefore: validBefore.toString(), diff --git a/packages/atxp-client/src/index.ts b/packages/atxp-client/src/index.ts index 7732b3a8..a87179dc 100644 --- a/packages/atxp-client/src/index.ts +++ b/packages/atxp-client/src/index.ts @@ -66,3 +66,16 @@ export { export { wrapWithX402 } from './x402Wrapper.js'; + +export { + wrapWithX402V2 +} from './x402WrapperV2.js'; + +export { + wrapWithX402UsingLibrary +} from './x402WrapperUsingX402.js'; + +export { + RemoteSigner, + createRemoteSigner +} from './remoteSigner.js'; diff --git a/packages/atxp-client/src/remoteSigner.ts b/packages/atxp-client/src/remoteSigner.ts new file mode 100644 index 00000000..2247f4cc --- /dev/null +++ b/packages/atxp-client/src/remoteSigner.ts @@ -0,0 +1,113 @@ +import { Hex, Address, LocalAccount, SignableMessage, TypedData, TransactionSerializable, Hash } from 'viem'; +import { FetchLike } from '@atxp/common'; + +/** + * Creates a remote signer that delegates signing operations to the accounts-x402 API. + * This implements the LocalAccount interface from viem to be compatible with x402-fetch. + */ +export class RemoteSigner implements LocalAccount { + public readonly type = 'local' as const; + + constructor( + public readonly address: Address, + private accountsApiUrl: string, + private fetchFn: FetchLike = fetch as FetchLike + ) {} + + /** + * Sign a typed data structure using EIP-712 + * This is what x402-fetch will call for EIP-3009 authorization + */ + async signTypedData< + const TTypedData extends TypedData | { [key: string]: unknown }, + TPrimaryType extends string = string, + >(typedData: TTypedData): Promise { + // Extract the actual typed data parameters + const { domain, types, primaryType, message } = typedData as any; + + // For EIP-3009, we need to send this to accounts-x402's /create-payment-authorization endpoint + if (primaryType === 'TransferWithAuthorization') { + const response = await this.fetchFn(`${this.accountsApiUrl}/create-payment-authorization`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + from: message.from, + to: message.to, + value: message.value, + validAfter: message.validAfter, + validBefore: message.validBefore, + nonce: message.nonce, + asset: domain.verifyingContract, + network: this.getNetworkFromChainId(domain.chainId), + extra: { + name: domain.name, + version: domain.version + } + }) + }); + + if (!response.ok) { + throw new Error(`Failed to sign authorization: ${response.status} ${response.statusText}`); + } + + const result = await response.json(); + return result.signature as Hex; + } + + throw new Error('Unsupported typed data signing'); + } + + /** + * Sign a message - required by LocalAccount interface but not used for X402 + */ + async signMessage({ message }: { message: SignableMessage }): Promise { + throw new Error('Message signing not implemented for remote signer'); + } + + /** + * Sign a transaction - required by LocalAccount interface but not used for X402 + */ + async signTransaction(transaction: TransactionSerializable, args?: any): Promise { + throw new Error('Transaction signing not implemented for remote signer'); + } + + /** + * Get public key - required by LocalAccount interface + */ + async publicKey(): Promise { + // Return a dummy public key since we don't have access to it + return '0x0000000000000000000000000000000000000000000000000000000000000000' as Hex; + } + + /** + * Get chain ID from network - helper method + */ + private getNetworkFromChainId(chainId: number): string { + const chainIdToNetwork: { [key: number]: string } = { + 8453: 'base', + 84532: 'base-sepolia', + 43114: 'avalanche', + 43113: 'avalanche-fuji', + 1329: 'sei', + 1328: 'sei-testnet' + }; + + return chainIdToNetwork[chainId] || 'base'; + } +} + +/** + * Create a remote signer for use with x402-fetch + * @param address The address of the account + * @param accountsApiUrl The URL of the accounts-x402 API + * @param fetchFn Optional fetch function to use + */ +export function createRemoteSigner( + address: Address, + accountsApiUrl: string, + fetchFn?: FetchLike +): RemoteSigner { + return new RemoteSigner(address, accountsApiUrl, fetchFn); +} \ No newline at end of file diff --git a/packages/atxp-client/src/x402Wrapper.ts b/packages/atxp-client/src/x402Wrapper.ts index 258c189b..a20cf16d 100644 --- a/packages/atxp-client/src/x402Wrapper.ts +++ b/packages/atxp-client/src/x402Wrapper.ts @@ -73,12 +73,12 @@ export function wrapWithX402(fetchFn: FetchLike, account: Account, logger?: Logg ? Buffer.from(x402MessageJson).toString('base64') : btoa(x402MessageJson); - // Send the X402 message in the X-Payment header + // Send the X402 message in the X-PAYMENT header const retryInit = { ...init, headers: { ...(init?.headers || {}), - 'X-Payment': x402MessageBase64 + 'X-PAYMENT': x402MessageBase64 } }; diff --git a/packages/atxp-client/src/x402WrapperUsingX402.ts b/packages/atxp-client/src/x402WrapperUsingX402.ts new file mode 100644 index 00000000..e8562a35 --- /dev/null +++ b/packages/atxp-client/src/x402WrapperUsingX402.ts @@ -0,0 +1,100 @@ +import type { Account } from './types.js'; +import { FetchLike, Logger, ConsoleLogger } from '@atxp/common'; +import { createPaymentHeader, selectPaymentRequirements } from 'x402/client'; +import { createSigner, type Signer } from 'x402/types'; +import type { Hex } from 'viem'; + +/** + * Wraps fetch with X402 payment support using the official x402 library + * This version directly uses x402's createPaymentHeader function like x402-fetch does + * + * Note: This requires the account to have a private key available for creating + * the x402 Signer object. For remote signing, use the RemoteSigner approach instead. + */ +export function wrapWithX402UsingLibrary( + fetchFn: FetchLike, + privateKey: Hex, + logger?: Logger +): FetchLike { + const log = logger ?? new ConsoleLogger(); + + return async function x402FetchWrapper(input: string | URL, init?: RequestInit): Promise { + const response = await fetchFn(input, init); + + // Check if this is an X402 payment challenge + if (response.status !== 402) { + return response; + } + + log.info('Received X402 payment challenge'); + + try { + // Parse the X402 payment requirements from response body + const responseBody = await response.text(); + const { x402Version, accepts } = JSON.parse(responseBody); + + // Check if this is a valid X402 response + if (!x402Version || !accepts || !Array.isArray(accepts)) { + log.debug('Received 402 response without valid X402 format'); + return response; + } + + // Use x402's selectPaymentRequirements to find the best option + const selectedPaymentRequirements = selectPaymentRequirements( + accepts, + 'base', + 'exact' + ); + + if (!selectedPaymentRequirements) { + log.error('No suitable payment requirements found'); + return response; + } + + const { network, maxAmountRequired, payTo } = selectedPaymentRequirements; + + // Convert amount from wei to human-readable for logging + const amountInUsdc = Number(maxAmountRequired) / (10 ** 6); + log.debug(`Payment required: ${amountInUsdc} USDC on ${network} to ${payTo}`); + + // Create an x402 signer for the network + const signer = await createSigner(network, privateKey); + + // Use x402's createPaymentHeader directly - this is the key difference! + // This function handles all the EIP-3009 signing internally + log.debug(`Creating payment header using x402 library`); + const paymentHeader = await createPaymentHeader( + signer, + x402Version, + selectedPaymentRequirements + ); + + // Add headers exactly like x402-fetch does + const retryInit = { + ...init, + headers: { + ...(init?.headers || {}), + 'X-PAYMENT': paymentHeader, + 'Access-Control-Expose-Headers': 'X-PAYMENT-RESPONSE' + } + }; + + log.info('Retrying request with X-Payment header'); + + // Retry the request + const retryResponse = await fetchFn(input, retryInit); + + if (retryResponse.ok) { + log.info('X402 payment accepted, request successful'); + } else { + log.warn(`Request failed after payment with status ${retryResponse.status}`); + } + + return retryResponse; + } catch (error) { + // If there's an error processing the payment, return the original 402 response + log.error(`Failed to handle X402 payment challenge: ${error}`); + return response; + } + }; +} \ No newline at end of file diff --git a/packages/atxp-client/src/x402WrapperV2.ts b/packages/atxp-client/src/x402WrapperV2.ts new file mode 100644 index 00000000..e64fe9bc --- /dev/null +++ b/packages/atxp-client/src/x402WrapperV2.ts @@ -0,0 +1,125 @@ +import type { Account, X402Message } from './types.js'; +import { FetchLike, Logger, ConsoleLogger } from '@atxp/common'; +import { BigNumber } from 'bignumber.js'; +import { + createPaymentHeader, + selectPaymentRequirements, + type PaymentRequirements +} from 'x402/client'; +import { createSigner } from 'x402/types'; +import type { Hex } from 'viem'; + +/** + * Wraps fetch with X402 payment support using the official x402 library functions + * This version uses x402's createPaymentHeader directly instead of our custom implementation + */ +export function wrapWithX402V2(fetchFn: FetchLike, account: Account, logger?: Logger): FetchLike { + const log = logger ?? new ConsoleLogger(); + + return async function x402FetchWrapper(input: string | URL, init?: RequestInit): Promise { + const response = await fetchFn(input, init); + + // Check if this is an X402 payment challenge + if (response.status !== 402) { + return response; + } + + log.info('Received X402 payment challenge'); + + try { + // Parse the X402 payment requirements from response body + const responseBody = await response.text(); + const paymentChallenge = JSON.parse(responseBody); + + // Check if this is a valid X402 response + if (!paymentChallenge.x402Version || !paymentChallenge.accepts || !Array.isArray(paymentChallenge.accepts)) { + log.debug('Received 402 response without valid X402 format'); + return response; + } + + const { x402Version, accepts } = paymentChallenge; + + // Use x402's selectPaymentRequirements to find the best option + // This matches what x402-fetch does internally + const selectedPaymentRequirements = selectPaymentRequirements( + accepts as PaymentRequirements[], + 'base', // We only support base for now + 'exact' + ); + + if (!selectedPaymentRequirements) { + log.error('No suitable payment requirements found'); + return response; + } + + const { network, maxAmountRequired, payTo: recipient, asset } = selectedPaymentRequirements; + + // Convert maxAmountRequired from wei to decimal (USDC has 6 decimals) + const amount = new BigNumber(maxAmountRequired).dividedBy(new BigNumber(10).pow(6)).toString(); + const currency = 'USDC'; + + log.debug(`Payment required: ${amount} ${currency} on ${network} to ${recipient}`); + + // Find the appropriate payment maker + const paymentMaker = account.paymentMakers[network]; + + if (!paymentMaker) { + log.info(`No payment maker found for ${network}`); + return response; + } + + // For now, we'll use our existing EIP-3009 authorization method + // In a real implementation, we'd use x402's createPaymentHeader with a proper signer + log.debug(`Creating EIP-3009 payment authorization`); + + const eip3009Authorization = await paymentMaker.createPaymentAuthorization( + new BigNumber(amount), + currency, + recipient, + '' + ); + + // Wrap in X402 message format (same as before) + const x402Message: X402Message = { + x402Version: x402Version, + scheme: 'exact', + network: network, + payload: eip3009Authorization + }; + + // Base64 encode the X402 message + const x402MessageJson = JSON.stringify(x402Message); + log.debug(`X402 message being sent: ${x402MessageJson}`); + const x402MessageBase64 = typeof Buffer !== 'undefined' + ? Buffer.from(x402MessageJson).toString('base64') + : btoa(x402MessageJson); + + // Add the Access-Control-Expose-Headers header like x402-fetch does + const retryInit = { + ...init, + headers: { + ...(init?.headers || {}), + 'X-PAYMENT': x402MessageBase64, + 'Access-Control-Expose-Headers': 'X-PAYMENT-RESPONSE' + } + }; + + log.info('Retrying request with X-Payment header'); + + // Retry the request + const retryResponse = await fetchFn(input, retryInit); + + if (retryResponse.ok) { + log.info('X402 payment accepted, request successful'); + } else { + log.warn(`Request failed after payment with status ${retryResponse.status}`); + } + + return retryResponse; + } catch (error) { + // If there's an error processing the payment, return the original 402 response + log.error(`Failed to handle X402 payment challenge: ${error}`); + return response; + } + }; +} \ No newline at end of file From 3373dd578b6cc3efaa7c32b0556acce8fc99e2db Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 16:14:55 -0700 Subject: [PATCH 29/61] Working version with local signer --- examples/x402-server/src/test-client.ts | 18 +- packages/atxp-client/src/baseAccount.ts | 27 ++- .../atxp-client/src/x402WrapperWithSigner.ts | 177 ++++++++++++++++++ 3 files changed, 211 insertions(+), 11 deletions(-) create mode 100644 packages/atxp-client/src/x402WrapperWithSigner.ts diff --git a/examples/x402-server/src/test-client.ts b/examples/x402-server/src/test-client.ts index 93215dd1..a8612940 100644 --- a/examples/x402-server/src/test-client.ts +++ b/examples/x402-server/src/test-client.ts @@ -32,11 +32,21 @@ async function testX402Client() { console.log('Using wrapWithX402 (our custom implementation)'); // Wrap fetch with X402 support using our custom implementation - const x402Fetch = wrapWithX402( - fetch as any, + const x402Fetch = wrapWithX402({ account, - logger - ); + logger, + fetchFn: fetch as any, + approvePayment: async (payment) => { + console.log(`Approving payment of ${payment.amount} ${payment.currency} to ${payment.iss}`); + return true; + }, + onPayment: async ({ payment }) => { + console.log(`Payment made: ${payment.amount} ${payment.currency}`); + }, + onPaymentFailure: async ({ payment, error }) => { + console.error(`Payment failed: ${error.message}`); + } + }); // Make a single request to the protected endpoint const serverUrl = process.env.X402_SERVER_URL || 'http://localhost:3001'; diff --git a/packages/atxp-client/src/baseAccount.ts b/packages/atxp-client/src/baseAccount.ts index baa6c2a7..c84fafd5 100644 --- a/packages/atxp-client/src/baseAccount.ts +++ b/packages/atxp-client/src/baseAccount.ts @@ -1,12 +1,16 @@ import type { Account, PaymentMaker, Hex } from './types.js'; -import { privateKeyToAccount } from 'viem/accounts'; +import { privateKeyToAccount, PrivateKeyAccount } from 'viem/accounts'; import { BasePaymentMaker } from './basePaymentMaker.js'; -import { createWalletClient, http } from 'viem'; +import { createWalletClient, http, WalletClient } from 'viem'; import { base } from 'viem/chains'; +import { LocalSigner } from './localSigner.js'; +import { LocalAccount } from 'viem'; export class BaseAccount implements Account { accountId: string; paymentMakers: { [key: string]: PaymentMaker }; + private walletClient: WalletClient; + private account: PrivateKeyAccount; constructor(baseRPCUrl: string, sourceSecretKey: string) { if (!baseRPCUrl) { @@ -16,16 +20,25 @@ export class BaseAccount implements Account { throw new Error('Source secret key is required'); } - const account = privateKeyToAccount(sourceSecretKey as Hex); + this.account = privateKeyToAccount(sourceSecretKey as Hex); - this.accountId = account.address; - const walletClient = createWalletClient({ - account: account, + this.accountId = this.account.address; + this.walletClient = createWalletClient({ + account: this.account, chain: base, transport: http(baseRPCUrl), }); this.paymentMakers = { - 'base': new BasePaymentMaker(baseRPCUrl, walletClient), + 'base': new BasePaymentMaker(baseRPCUrl, this.walletClient), } } + + /** + * Get a signer that can be used with the x402 library + * This is only available for EVM-based accounts + */ + getSigner(): LocalAccount { + // Return the viem account directly - it implements LocalAccount interface + return this.account; + } } \ No newline at end of file diff --git a/packages/atxp-client/src/x402WrapperWithSigner.ts b/packages/atxp-client/src/x402WrapperWithSigner.ts new file mode 100644 index 00000000..d715864f --- /dev/null +++ b/packages/atxp-client/src/x402WrapperWithSigner.ts @@ -0,0 +1,177 @@ +import { ClientConfig, ProspectivePayment } from './types.js'; +import { BaseAccount } from './baseAccount.js'; +import { FetchLike, Logger, Network } from '@atxp/common'; +import { BigNumber } from 'bignumber.js'; +import { createPaymentHeader, selectPaymentRequirements } from 'x402/client'; +import { LocalAccount } from 'viem'; + +/** + * Wraps fetch with X402 payment support using a local signer + * This wrapper intercepts 402 responses and creates payments using the x402 library + * + * @param config - ClientConfig containing account, logger, and fetch function + * @returns A wrapped fetch function that handles X402 payments + */ +export function wrapWithX402(config: ClientConfig): FetchLike { + const { account, logger, fetchFn = fetch, approvePayment, onPayment, onPaymentFailure } = config; + const log = logger ?? console; + + // Check if account has getSigner method (only BaseAccount for now) + const accountWithSigner = account as any; + if (!accountWithSigner.getSigner) { + throw new Error('Account does not support getSigner, X402 payments will not work'); + } + + const signer: LocalAccount = accountWithSigner.getSigner(); + log.debug('Using local signer for X402 payments'); + + return async function x402FetchWrapper(input: string | URL, init?: RequestInit): Promise { + const response = await fetchFn(input, init); + + // Check if this is an X402 payment challenge + if (response.status !== 402) { + return response; + } + + log.info('Received X402 payment challenge'); + + try { + // Parse the X402 payment requirements from response body + const responseBody = await response.text(); + const paymentChallenge = JSON.parse(responseBody); + + // Check if this is a valid X402 response + if (!paymentChallenge.x402Version || !paymentChallenge.accepts || !Array.isArray(paymentChallenge.accepts)) { + log.debug('Received 402 response without valid X402 format'); + // Return a new Response with the original body since we consumed it + return new Response(responseBody, { + status: response.status, + statusText: response.statusText, + headers: response.headers + }); + } + + // Select the best payment requirements (prefer base network, exact scheme) + const selectedPaymentRequirements = selectPaymentRequirements( + paymentChallenge.accepts, + 'base', + 'exact' + ); + + if (!selectedPaymentRequirements) { + log.info('No suitable X402 payment option found'); + return new Response(responseBody, { + status: response.status, + statusText: response.statusText, + headers: response.headers + }); + } + + // Convert amount from wei to human-readable for logging and approval + const amountInUsdc = Number(selectedPaymentRequirements.maxAmountRequired) / (10 ** 6); + log.debug(`Payment required: ${amountInUsdc} USDC on ${selectedPaymentRequirements.network} to ${selectedPaymentRequirements.payTo}`); + + // Create the ProspectivePayment object for callbacks + const url = typeof input === 'string' ? input : input.toString(); + const prospectivePayment: ProspectivePayment = { + accountId: account.accountId, + resourceUrl: url, + resourceName: selectedPaymentRequirements.description || url, + network: selectedPaymentRequirements.network as Network, + currency: 'USDC', + amount: new BigNumber(amountInUsdc), + iss: selectedPaymentRequirements.payTo + }; + + // Check if payment should be approved + if (approvePayment) { + const approved = await approvePayment(prospectivePayment); + + if (!approved) { + log.info('Payment not approved by user'); + if (onPaymentFailure) { + await onPaymentFailure({ + payment: prospectivePayment, + error: new Error('Payment not approved') + }); + } + return new Response(responseBody, { + status: response.status, + statusText: response.statusText, + headers: response.headers + }); + } + } + + // Create the X402 payment header using the x402 library + log.debug('Creating X402 payment header with signer'); + const paymentHeader = await createPaymentHeader( + signer, + paymentChallenge.x402Version, + selectedPaymentRequirements + ); + + // Add the payment header and retry the request + const retryInit = { + ...init, + headers: { + ...(init?.headers || {}), + 'X-PAYMENT': paymentHeader, + // Request the payment response header + 'Access-Control-Expose-Headers': 'X-PAYMENT-RESPONSE' + } + }; + + log.info('Retrying request with X-PAYMENT header'); + const retryResponse = await fetchFn(input, retryInit); + + if (retryResponse.ok) { + log.info('X402 payment accepted, request successful'); + + // Call onPayment callback if provided + if (onPayment) { + await onPayment({ payment: prospectivePayment }); + } + } else { + log.warn(`Request failed after payment with status ${retryResponse.status}`); + + if (onPaymentFailure) { + await onPaymentFailure({ + payment: prospectivePayment, + error: new Error(`Request failed with status ${retryResponse.status}`) + }); + } + } + + return retryResponse; + } catch (error) { + // If there's an error processing the payment, call failure callback and return original response + log.error(`Failed to handle X402 payment challenge: ${error}`); + + // Try to recreate the response with the body we might have consumed + const responseBody = await response.text(); + const paymentChallenge = JSON.parse(responseBody); + + if (onPaymentFailure && paymentChallenge?.accepts?.[0]) { + const firstOption = paymentChallenge.accepts[0]; + const amount = Number(firstOption.maxAmountRequired) / (10 ** 6); + const url = typeof input === 'string' ? input : input.toString(); + await onPaymentFailure({ + payment: { + accountId: account.accountId, + resourceUrl: url, + resourceName: firstOption.description || url, + network: firstOption.network as Network, + currency: 'USDC', + amount: new BigNumber(amount), + iss: firstOption.payTo + }, + error: error as Error + }); + } + + // Return the original response + return response; + } + }; +} \ No newline at end of file From a8bf4a169fa7520934af320d688904e1db8795af Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 16:15:05 -0700 Subject: [PATCH 30/61] Cleanup --- package-lock.json | 14 +- package.json | 3 +- packages/atxp-client/src/atxpAccount.ts | 83 ++++-- packages/atxp-client/src/baseAccount.ts | 4 +- packages/atxp-client/src/basePaymentMaker.ts | 91 +------ packages/atxp-client/src/index.ts | 8 - packages/atxp-client/src/types.ts | 1 - packages/atxp-client/src/x402Wrapper.test.ts | 152 ----------- packages/atxp-client/src/x402Wrapper.ts | 246 +++++++++++------- .../atxp-client/src/x402WrapperUsingX402.ts | 100 ------- packages/atxp-client/src/x402WrapperV2.ts | 125 --------- .../atxp-client/src/x402WrapperWithSigner.ts | 177 ------------- 12 files changed, 232 insertions(+), 772 deletions(-) delete mode 100644 packages/atxp-client/src/x402Wrapper.test.ts delete mode 100644 packages/atxp-client/src/x402WrapperUsingX402.ts delete mode 100644 packages/atxp-client/src/x402WrapperV2.ts delete mode 100644 packages/atxp-client/src/x402WrapperWithSigner.ts diff --git a/package-lock.json b/package-lock.json index c61a23f3..296ffea2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,8 @@ "packages/atxp-cloudflare" ], "dependencies": { - "dotenv": "^16.5.0" + "dotenv": "^16.5.0", + "x402-fetch": "^0.6.0" }, "devDependencies": { "@rollup/plugin-commonjs": "^28.0.6", @@ -20723,6 +20724,17 @@ "zod": "^3.24.2" } }, + "node_modules/x402-fetch": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/x402-fetch/-/x402-fetch-0.6.0.tgz", + "integrity": "sha512-c7ZQQOjgBWyX9xbmRCliUguVeG0RCofTlcnPKBrAgNYxEo8p/yuQr2PRvyN9tdQdXVTlGgIsII7GO1wLHJpLhA==", + "license": "Apache-2.0", + "dependencies": { + "viem": "^2.21.26", + "x402": "^0.6.0", + "zod": "^3.24.2" + } + }, "node_modules/xcode": { "version": "3.0.1", "license": "Apache-2.0", diff --git a/package.json b/package.json index 848f6808..9ed85db7 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,8 @@ "prepack:all": "npm run prepack --workspaces --if-present" }, "dependencies": { - "dotenv": "^16.5.0" + "dotenv": "^16.5.0", + "x402-fetch": "^0.6.0" }, "devDependencies": { "@rollup/plugin-commonjs": "^28.0.6", diff --git a/packages/atxp-client/src/atxpAccount.ts b/packages/atxp-client/src/atxpAccount.ts index a654e7d7..22ed520c 100644 --- a/packages/atxp-client/src/atxpAccount.ts +++ b/packages/atxp-client/src/atxpAccount.ts @@ -1,6 +1,8 @@ -import type { Account, PaymentMaker, EIP3009Authorization } from './types.js'; +import type { Account, PaymentMaker } from './types.js'; import type { FetchLike, Network, Currency } from '@atxp/common' import BigNumber from 'bignumber.js'; +import { LocalAccount } from 'viem'; +import { RemoteSigner } from './remoteSigner.js'; function toBasicAuth(token: string): string { // Basic auth is base64("username:password"), password is blank @@ -58,31 +60,6 @@ class ATXPHttpPaymentMaker implements PaymentMaker { return json.txHash; } - async createPaymentAuthorization(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { - // Create an EIP-3009 payment authorization via the HTTP endpoint - const response = await this.fetchFn(`${this.origin}/create-payment-authorization`, { - method: 'POST', - headers: { - 'Authorization': toBasicAuth(this.token), - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - amount: amount.toString(), - currency, - receiver, - memo, - }), - }); - - if (!response.ok) { - const text = await response.text(); - throw new Error(`ATXPAccount: /create-payment-authorization failed: ${response.status} ${response.statusText} ${text}`); - } - - // Return the EIP-3009 authorization from the accounts service - return await response.json() as EIP3009Authorization; - } - async generateJWT(params: { paymentRequestId: string; codeChallenge: string }): Promise { const response = await this.fetchFn(`${this.origin}/sign`, { method: 'POST', @@ -110,16 +87,70 @@ class ATXPHttpPaymentMaker implements PaymentMaker { export class ATXPAccount implements Account { accountId: string; paymentMakers: { [key: string]: PaymentMaker }; + private origin: string; + private token: string; + private fetchFn: FetchLike; constructor(connectionString: string, opts?: { fetchFn?: FetchLike; network?: Network }) { const { origin, token } = parseConnectionString(connectionString); const fetchFn = opts?.fetchFn ?? fetch; const network = opts?.network ?? 'base'; + // Store for use in X402 payment creation + this.origin = origin; + this.token = token; + this.fetchFn = fetchFn; + // Use token as a stable accountId namespace to keep OAuth/ATXP state per-connection this.accountId = `atxp:${token}`; this.paymentMakers = { [network]: new ATXPHttpPaymentMaker(origin, token, fetchFn), }; } + + /** + * Create an X402 payment header by calling the accounts-x402 server + * @param x402Challenge The X402 challenge object from the 402 response + * @returns The X402 payment header to send in the retry request + */ + async createX402Payment(x402Challenge: { x402Version: number; accepts: any[] }): Promise { + const response = await this.fetchFn(`${this.origin}/create-x402-payment`, { + method: 'POST', + headers: { + 'Authorization': toBasicAuth(this.token), + 'Content-Type': 'application/json', + }, + body: JSON.stringify(x402Challenge), + }); + + if (!response.ok) { + const text = await response.text(); + throw new Error(`ATXPAccount: Failed to create X402 payment: ${response.status} ${response.statusText} ${text}`); + } + + const result = await response.json() as { paymentHeader?: string }; + if (!result?.paymentHeader) { + throw new Error('ATXPAccount: Server did not return payment header'); + } + + return result.paymentHeader; + } + + /** + * Get a signer that can be used with the x402 library + * This will use RemoteSigner to delegate signing to the accounts-x402 server + * NOTE: This requires the accounts-x402 server to implement a signTypedData endpoint + */ + getSigner(): LocalAccount { + // TODO: We need to get the wallet address from the accounts-x402 server + // For now, throw an error indicating this is not yet implemented + throw new Error('ATXPAccount.getSigner() is not yet implemented - requires signTypedData endpoint on accounts-x402 server'); + + // Future implementation: + // return new RemoteSigner( + // walletAddress, + // this.origin, + // this.fetchFn + // ); + } } \ No newline at end of file diff --git a/packages/atxp-client/src/baseAccount.ts b/packages/atxp-client/src/baseAccount.ts index c84fafd5..f7d3a696 100644 --- a/packages/atxp-client/src/baseAccount.ts +++ b/packages/atxp-client/src/baseAccount.ts @@ -1,10 +1,8 @@ import type { Account, PaymentMaker, Hex } from './types.js'; import { privateKeyToAccount, PrivateKeyAccount } from 'viem/accounts'; import { BasePaymentMaker } from './basePaymentMaker.js'; -import { createWalletClient, http, WalletClient } from 'viem'; +import { createWalletClient, http, WalletClient, LocalAccount } from 'viem'; import { base } from 'viem/chains'; -import { LocalSigner } from './localSigner.js'; -import { LocalAccount } from 'viem'; export class BaseAccount implements Account { accountId: string; diff --git a/packages/atxp-client/src/basePaymentMaker.ts b/packages/atxp-client/src/basePaymentMaker.ts index 7e12a58b..a59f799c 100644 --- a/packages/atxp-client/src/basePaymentMaker.ts +++ b/packages/atxp-client/src/basePaymentMaker.ts @@ -1,4 +1,4 @@ -import type { PaymentMaker, Hex, EIP3009Authorization } from './types.js'; +import type { PaymentMaker, Hex } from './types.js'; import { InsufficientFundsError as InsufficientFundsErrorClass, PaymentNetworkError as PaymentNetworkErrorClass } from './types.js'; import { Logger, Currency } from '@atxp/common'; import { ConsoleLogger } from '@atxp/common'; @@ -181,93 +181,4 @@ export class BasePaymentMaker implements PaymentMaker { } } - async createPaymentAuthorization(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { - if (currency.toUpperCase() !== 'USDC') { - throw new PaymentNetworkErrorClass('Only USDC is supported for EIP-3009 authorizations'); - } - - this.logger.info(`Creating EIP-3009 authorization for ${amount} ${currency} to ${receiver}`); - - try { - // Check balance before creating authorization - const balanceRaw = await this.signingClient.readContract({ - address: USDC_CONTRACT_ADDRESS_BASE as Address, - abi: ERC20_ABI, - functionName: 'balanceOf', - args: [this.signingClient.account!.address], - }) as bigint; - - const balance = new BigNumber(balanceRaw.toString()).dividedBy(10 ** USDC_DECIMALS); - - if (balance.lt(amount)) { - this.logger.warn(`Insufficient ${currency} balance for authorization. Required: ${amount}, Available: ${balance}`); - throw new InsufficientFundsErrorClass(currency, amount, balance, 'base'); - } - - // Create EIP-3009 authorization parameters - const validAfter = Math.floor(Date.now() / 1000); // Valid immediately - const validBefore = Math.floor(Date.now() / 1000) + 660; // Valid for 11 minutes (matching x402-fetch) - const nonce = '0x' + Array.from(crypto.getRandomValues(new Uint8Array(32)), b => b.toString(16).padStart(2, '0')).join(''); - - // Convert amount to USDC units (6 decimals) - const value = amount.multipliedBy(10 ** USDC_DECIMALS).toFixed(0); - - // Create the EIP-712 typed data for signing - const typedData = { - domain: { - name: 'USD Coin', - version: '2', - chainId: base.id, // Base mainnet chain ID (8453) - verifyingContract: getAddress(USDC_CONTRACT_ADDRESS_BASE), - }, - types: { - TransferWithAuthorization: [ - { name: 'from', type: 'address' }, - { name: 'to', type: 'address' }, - { name: 'value', type: 'uint256' }, - { name: 'validAfter', type: 'uint256' }, - { name: 'validBefore', type: 'uint256' }, - { name: 'nonce', type: 'bytes32' }, - ], - }, - primaryType: 'TransferWithAuthorization' as const, - message: { - from: getAddress(this.signingClient.account!.address), - to: getAddress(receiver), - value, - validAfter: validAfter.toString(), - validBefore: validBefore.toString(), - nonce, - }, - }; - - // Sign the typed data - const signature = await this.signingClient.signTypedData({ - account: this.signingClient.account!, - ...typedData, - }); - - this.logger.info(`Created EIP-3009 authorization with signature: ${signature}`); - - // Return EIP-3009 authorization in the expected format - return { - signature, - authorization: { - from: getAddress(this.signingClient.account!.address), - to: getAddress(receiver), - value, - validAfter: validAfter.toString(), - validBefore: validBefore.toString(), - nonce, - } - }; - } catch (error) { - if (error instanceof InsufficientFundsErrorClass || error instanceof PaymentNetworkErrorClass) { - throw error; - } - - // Wrap other errors in PaymentNetworkError - throw new PaymentNetworkErrorClass(`Failed to create EIP-3009 authorization: ${(error as Error).message}`, error as Error); - } - } } \ No newline at end of file diff --git a/packages/atxp-client/src/index.ts b/packages/atxp-client/src/index.ts index a87179dc..f3670613 100644 --- a/packages/atxp-client/src/index.ts +++ b/packages/atxp-client/src/index.ts @@ -67,14 +67,6 @@ export { wrapWithX402 } from './x402Wrapper.js'; -export { - wrapWithX402V2 -} from './x402WrapperV2.js'; - -export { - wrapWithX402UsingLibrary -} from './x402WrapperUsingX402.js'; - export { RemoteSigner, createRemoteSigner diff --git a/packages/atxp-client/src/types.ts b/packages/atxp-client/src/types.ts index 94cf5fb5..2e6127de 100644 --- a/packages/atxp-client/src/types.ts +++ b/packages/atxp-client/src/types.ts @@ -90,6 +90,5 @@ export type X402Message = { export interface PaymentMaker { makePayment: (amount: BigNumber, currency: Currency, receiver: string, memo: string) => Promise; - createPaymentAuthorization: (amount: BigNumber, currency: Currency, receiver: string, memo: string) => Promise; generateJWT: (params: {paymentRequestId: string, codeChallenge: string}) => Promise; } diff --git a/packages/atxp-client/src/x402Wrapper.test.ts b/packages/atxp-client/src/x402Wrapper.test.ts deleted file mode 100644 index 1253857b..00000000 --- a/packages/atxp-client/src/x402Wrapper.test.ts +++ /dev/null @@ -1,152 +0,0 @@ -import { describe, it, expect, vi } from 'vitest'; -import { wrapWithX402 } from './x402Wrapper.js'; -import type { Account, EIP3009Authorization, X402Message } from './types.js'; -import { BigNumber } from 'bignumber.js'; - -describe('X402 Wrapper', () => { - it('should produce valid X402 message structure matching protocol specification', async () => { - // Mock account with test payment maker - const mockAccount: Account = { - accountId: 'test-account', - paymentMakers: { - 'base:USDC': { - async createPaymentAuthorization( - amount: BigNumber, - _currency: string, - receiver: string, - _memo: string - ): Promise { - // Mock EIP-3009 authorization response - return { - signature: '0xabcdef123456789', - authorization: { - from: '0x1234567890123456789012345678901234567890', - to: receiver, - value: amount.multipliedBy(1e6).toFixed(0), // USDC has 6 decimals - validAfter: Math.floor(Date.now() / 1000).toString(), - validBefore: (Math.floor(Date.now() / 1000) + 3600).toString(), - nonce: '0x' + '0'.repeat(64) - } - }; - } - } - } - }; - - // Mock fetch that returns 402 with payment requirements - const mockFetch = vi.fn(async (url: string | URL, init?: RequestInit) => { - if (!init?.headers || !(init.headers as any)['X-Payment']) { - // First request - return 402 challenge - return { - status: 402, - ok: false, - json: async () => ({}), - text: async () => '', - headers: { - get: (name: string) => { - if (name === 'X-Payment-Required') { - return JSON.stringify({ - network: 'base', - currency: 'USDC', - amount: '0.01', - recipient: '0xrecipient123', - memo: 'test payment' - }); - } - return null; - } - } - }; - } - - // Second request with payment - verify X402 message structure - const x402Message = JSON.parse((init.headers as any)['X-Payment']) as X402Message; - - // Verify top-level X402 protocol fields - expect(x402Message).toHaveProperty('x402Version'); - expect(x402Message).toHaveProperty('scheme'); - expect(x402Message).toHaveProperty('network'); - expect(x402Message).toHaveProperty('payload'); - - expect(x402Message.x402Version).toBe(1); - expect(x402Message.scheme).toBe('exact'); - expect(x402Message.network).toBe('base'); - - // Verify EIP-3009 payload structure - expect(x402Message.payload).toHaveProperty('signature'); - expect(x402Message.payload).toHaveProperty('authorization'); - - const auth = x402Message.payload.authorization; - expect(auth).toHaveProperty('from'); - expect(auth).toHaveProperty('to'); - expect(auth).toHaveProperty('value'); - expect(auth).toHaveProperty('validAfter'); - expect(auth).toHaveProperty('validBefore'); - expect(auth).toHaveProperty('nonce'); - - // Verify value is correctly converted to USDC units (6 decimals) - expect(auth.value).toBe('10000'); // 0.01 USDC = 10000 units - expect(auth.to).toBe('0xrecipient123'); - - return { - status: 200, - ok: true, - json: async () => ({ success: true }), - text: async () => JSON.stringify({ success: true }), - headers: { - get: () => null - } - }; - }); - - const wrappedFetch = wrapWithX402(mockFetch as any, mockAccount); - const response = await wrappedFetch('https://example.com/api/resource'); - - expect(response.status).toBe(200); - expect(mockFetch).toHaveBeenCalledTimes(2); - }); - - it('should handle non-402 responses without modification', async () => { - const mockAccount: Account = { - accountId: 'test-account', - paymentMakers: {} - }; - const mockFetch = vi.fn(async () => ({ - status: 200, - ok: true, - json: async () => ({}), - text: async () => '', - headers: { - get: () => null - } - })); - - const wrappedFetch = wrapWithX402(mockFetch as any, mockAccount); - const response = await wrappedFetch('https://example.com/api/resource'); - - expect(response.status).toBe(200); - expect(mockFetch).toHaveBeenCalledTimes(1); - }); - - it('should handle 402 responses without X-Payment-Required header', async () => { - const mockAccount: Account = { - accountId: 'test-account', - paymentMakers: {} - }; - const mockFetch = vi.fn(async () => ({ - status: 402, - ok: false, - json: async () => ({}), - text: async () => '', - headers: { - get: () => null - } - })); - - const wrappedFetch = wrapWithX402(mockFetch as any, mockAccount); - const response = await wrappedFetch('https://example.com/api/resource'); - - expect(response.status).toBe(402); - expect(mockFetch).toHaveBeenCalledTimes(1); - }); -}); \ No newline at end of file diff --git a/packages/atxp-client/src/x402Wrapper.ts b/packages/atxp-client/src/x402Wrapper.ts index a20cf16d..5ab05d7d 100644 --- a/packages/atxp-client/src/x402Wrapper.ts +++ b/packages/atxp-client/src/x402Wrapper.ts @@ -1,107 +1,177 @@ -import type { Account, X402Message } from './types.js'; -import { FetchLike, Logger, ConsoleLogger } from '@atxp/common'; +import { ClientConfig, ProspectivePayment } from './types.js'; +import { BaseAccount } from './baseAccount.js'; +import { FetchLike, Logger, Network } from '@atxp/common'; import { BigNumber } from 'bignumber.js'; +import { createPaymentHeader, selectPaymentRequirements } from 'x402/client'; +import { LocalAccount } from 'viem'; + +/** + * Wraps fetch with X402 payment support using a local signer + * This wrapper intercepts 402 responses and creates payments using the x402 library + * + * @param config - ClientConfig containing account, logger, and fetch function + * @returns A wrapped fetch function that handles X402 payments + */ +export function wrapWithX402(config: ClientConfig): FetchLike { + const { account, logger, fetchFn = fetch, approvePayment, onPayment, onPaymentFailure } = config; + const log = logger ?? console; + + // Check if account has getSigner method (only BaseAccount for now) + const accountWithSigner = account as any; + if (!accountWithSigner.getSigner) { + throw new Error('Account does not support getSigner, X402 payments will not work'); + } + + const signer: LocalAccount = accountWithSigner.getSigner(); + log.debug('Using local signer for X402 payments'); -export function wrapWithX402(fetchFn: FetchLike, account: Account, logger?: Logger): FetchLike { - const log = logger ?? new ConsoleLogger(); return async function x402FetchWrapper(input: string | URL, init?: RequestInit): Promise { const response = await fetchFn(input, init); // Check if this is an X402 payment challenge - if (response.status === 402) { - log.info('Received X402 payment challenge'); - - try { - // Parse the X402 payment requirements from response body - const responseBody = await response.text(); - const paymentChallenge = JSON.parse(responseBody); - - // Check if this is a valid X402 response - if (!paymentChallenge.x402Version || !paymentChallenge.accepts || !Array.isArray(paymentChallenge.accepts)) { - log.debug('Received 402 response without valid X402 format'); - return response; - } - - // Find the accept option for base:USDC - const baseUsdcOption = paymentChallenge.accepts.find((option: any) => - option.network === 'base' && option.asset === '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' - ); - - if (!baseUsdcOption) { - log.error('No base:USDC accept option found in payment challenge'); - throw new Error('No base:USDC accept option found in payment challenge'); - } - - const { network, maxAmountRequired, payTo: recipient, asset } = baseUsdcOption; - - // Convert maxAmountRequired from wei to decimal (USDC has 6 decimals) - const amount = new BigNumber(maxAmountRequired).dividedBy(new BigNumber(10).pow(6)).toString(); - const currency = 'USDC'; // Based on the asset address in the response + if (response.status !== 402) { + return response; + } - log.debug(`Payment required: ${amount} ${currency} on ${network} to ${recipient}`); + log.info('Received X402 payment challenge'); + + try { + // Parse the X402 payment requirements from response body + const responseBody = await response.text(); + const paymentChallenge = JSON.parse(responseBody); + + // Check if this is a valid X402 response + if (!paymentChallenge.x402Version || !paymentChallenge.accepts || !Array.isArray(paymentChallenge.accepts)) { + log.debug('Received 402 response without valid X402 format'); + // Return a new Response with the original body since we consumed it + return new Response(responseBody, { + status: response.status, + statusText: response.statusText, + headers: response.headers + }); + } - // Find the appropriate payment maker using just the network name - const paymentMaker = account.paymentMakers[network]; + // Select the best payment requirements (prefer base network, exact scheme) + const selectedPaymentRequirements = selectPaymentRequirements( + paymentChallenge.accepts, + 'base', + 'exact' + ); + + if (!selectedPaymentRequirements) { + log.info('No suitable X402 payment option found'); + return new Response(responseBody, { + status: response.status, + statusText: response.statusText, + headers: response.headers + }); + } - if (!paymentMaker) { - log.info(`No payment maker found for ${network}`); - return response; + // Convert amount from wei to human-readable for logging and approval + const amountInUsdc = Number(selectedPaymentRequirements.maxAmountRequired) / (10 ** 6); + log.debug(`Payment required: ${amountInUsdc} USDC on ${selectedPaymentRequirements.network} to ${selectedPaymentRequirements.payTo}`); + + // Create the ProspectivePayment object for callbacks + const url = typeof input === 'string' ? input : input.toString(); + const prospectivePayment: ProspectivePayment = { + accountId: account.accountId, + resourceUrl: url, + resourceName: selectedPaymentRequirements.description || url, + network: selectedPaymentRequirements.network as Network, + currency: 'USDC', + amount: new BigNumber(amountInUsdc), + iss: selectedPaymentRequirements.payTo + }; + + // Check if payment should be approved + if (approvePayment) { + const approved = await approvePayment(prospectivePayment); + + if (!approved) { + log.info('Payment not approved by user'); + if (onPaymentFailure) { + await onPaymentFailure({ + payment: prospectivePayment, + error: new Error('Payment not approved') + }); + } + return new Response(responseBody, { + status: response.status, + statusText: response.statusText, + headers: response.headers + }); } + } - log.debug(`Creating EIP-3009 payment authorization`); - - // Create an EIP-3009 payment authorization - const eip3009Authorization = await paymentMaker.createPaymentAuthorization( - new BigNumber(amount), - currency, - recipient, - '' - ); - - // Wrap the EIP-3009 authorization in X402 protocol format - const x402Message: X402Message = { - x402Version: 1, - scheme: 'exact', - network: network, - payload: eip3009Authorization - }; - - // Base64 encode the X402 message for the X-Payment header - const x402MessageJson = JSON.stringify(x402Message); - log.debug(`X402 message being sent: ${x402MessageJson}`); - const x402MessageBase64 = typeof Buffer !== 'undefined' - ? Buffer.from(x402MessageJson).toString('base64') - : btoa(x402MessageJson); - - // Send the X402 message in the X-PAYMENT header - const retryInit = { - ...init, - headers: { - ...(init?.headers || {}), - 'X-PAYMENT': x402MessageBase64 - } - }; + // Create the X402 payment header using the x402 library + log.debug('Creating X402 payment header with signer'); + const paymentHeader = await createPaymentHeader( + signer, + paymentChallenge.x402Version, + selectedPaymentRequirements + ); + + // Add the payment header and retry the request + const retryInit = { + ...init, + headers: { + ...(init?.headers || {}), + 'X-PAYMENT': paymentHeader, + // Request the payment response header + 'Access-Control-Expose-Headers': 'X-PAYMENT-RESPONSE' + } + }; - log.info('Retrying request with X-Payment header'); + log.info('Retrying request with X-PAYMENT header'); + const retryResponse = await fetchFn(input, retryInit); - // Retry the request - const retryResponse = await fetchFn(input, retryInit); + if (retryResponse.ok) { + log.info('X402 payment accepted, request successful'); - if (retryResponse.ok) { - log.info('X402 payment accepted, request successful'); - } else { - log.warn(`Request failed after payment with status ${retryResponse.status}`); + // Call onPayment callback if provided + if (onPayment) { + await onPayment({ payment: prospectivePayment }); } + } else { + log.warn(`Request failed after payment with status ${retryResponse.status}`); + + if (onPaymentFailure) { + await onPaymentFailure({ + payment: prospectivePayment, + error: new Error(`Request failed with status ${retryResponse.status}`) + }); + } + } - return retryResponse; - } catch (error) { - // If there's an error processing the payment, return the original 402 response - log.error(`Failed to handle X402 payment challenge: ${error}`); - return response; + return retryResponse; + } catch (error) { + // If there's an error processing the payment, call failure callback and return original response + log.error(`Failed to handle X402 payment challenge: ${error}`); + + // Try to recreate the response with the body we might have consumed + const responseBody = await response.text(); + const paymentChallenge = JSON.parse(responseBody); + + if (onPaymentFailure && paymentChallenge?.accepts?.[0]) { + const firstOption = paymentChallenge.accepts[0]; + const amount = Number(firstOption.maxAmountRequired) / (10 ** 6); + const url = typeof input === 'string' ? input : input.toString(); + await onPaymentFailure({ + payment: { + accountId: account.accountId, + resourceUrl: url, + resourceName: firstOption.description || url, + network: firstOption.network as Network, + currency: 'USDC', + amount: new BigNumber(amount), + iss: firstOption.payTo + }, + error: error as Error + }); } - } - // Not a 402 response, return as-is - return response; + // Return the original response + return response; + } }; -} \ No newline at end of file +} diff --git a/packages/atxp-client/src/x402WrapperUsingX402.ts b/packages/atxp-client/src/x402WrapperUsingX402.ts deleted file mode 100644 index e8562a35..00000000 --- a/packages/atxp-client/src/x402WrapperUsingX402.ts +++ /dev/null @@ -1,100 +0,0 @@ -import type { Account } from './types.js'; -import { FetchLike, Logger, ConsoleLogger } from '@atxp/common'; -import { createPaymentHeader, selectPaymentRequirements } from 'x402/client'; -import { createSigner, type Signer } from 'x402/types'; -import type { Hex } from 'viem'; - -/** - * Wraps fetch with X402 payment support using the official x402 library - * This version directly uses x402's createPaymentHeader function like x402-fetch does - * - * Note: This requires the account to have a private key available for creating - * the x402 Signer object. For remote signing, use the RemoteSigner approach instead. - */ -export function wrapWithX402UsingLibrary( - fetchFn: FetchLike, - privateKey: Hex, - logger?: Logger -): FetchLike { - const log = logger ?? new ConsoleLogger(); - - return async function x402FetchWrapper(input: string | URL, init?: RequestInit): Promise { - const response = await fetchFn(input, init); - - // Check if this is an X402 payment challenge - if (response.status !== 402) { - return response; - } - - log.info('Received X402 payment challenge'); - - try { - // Parse the X402 payment requirements from response body - const responseBody = await response.text(); - const { x402Version, accepts } = JSON.parse(responseBody); - - // Check if this is a valid X402 response - if (!x402Version || !accepts || !Array.isArray(accepts)) { - log.debug('Received 402 response without valid X402 format'); - return response; - } - - // Use x402's selectPaymentRequirements to find the best option - const selectedPaymentRequirements = selectPaymentRequirements( - accepts, - 'base', - 'exact' - ); - - if (!selectedPaymentRequirements) { - log.error('No suitable payment requirements found'); - return response; - } - - const { network, maxAmountRequired, payTo } = selectedPaymentRequirements; - - // Convert amount from wei to human-readable for logging - const amountInUsdc = Number(maxAmountRequired) / (10 ** 6); - log.debug(`Payment required: ${amountInUsdc} USDC on ${network} to ${payTo}`); - - // Create an x402 signer for the network - const signer = await createSigner(network, privateKey); - - // Use x402's createPaymentHeader directly - this is the key difference! - // This function handles all the EIP-3009 signing internally - log.debug(`Creating payment header using x402 library`); - const paymentHeader = await createPaymentHeader( - signer, - x402Version, - selectedPaymentRequirements - ); - - // Add headers exactly like x402-fetch does - const retryInit = { - ...init, - headers: { - ...(init?.headers || {}), - 'X-PAYMENT': paymentHeader, - 'Access-Control-Expose-Headers': 'X-PAYMENT-RESPONSE' - } - }; - - log.info('Retrying request with X-Payment header'); - - // Retry the request - const retryResponse = await fetchFn(input, retryInit); - - if (retryResponse.ok) { - log.info('X402 payment accepted, request successful'); - } else { - log.warn(`Request failed after payment with status ${retryResponse.status}`); - } - - return retryResponse; - } catch (error) { - // If there's an error processing the payment, return the original 402 response - log.error(`Failed to handle X402 payment challenge: ${error}`); - return response; - } - }; -} \ No newline at end of file diff --git a/packages/atxp-client/src/x402WrapperV2.ts b/packages/atxp-client/src/x402WrapperV2.ts deleted file mode 100644 index e64fe9bc..00000000 --- a/packages/atxp-client/src/x402WrapperV2.ts +++ /dev/null @@ -1,125 +0,0 @@ -import type { Account, X402Message } from './types.js'; -import { FetchLike, Logger, ConsoleLogger } from '@atxp/common'; -import { BigNumber } from 'bignumber.js'; -import { - createPaymentHeader, - selectPaymentRequirements, - type PaymentRequirements -} from 'x402/client'; -import { createSigner } from 'x402/types'; -import type { Hex } from 'viem'; - -/** - * Wraps fetch with X402 payment support using the official x402 library functions - * This version uses x402's createPaymentHeader directly instead of our custom implementation - */ -export function wrapWithX402V2(fetchFn: FetchLike, account: Account, logger?: Logger): FetchLike { - const log = logger ?? new ConsoleLogger(); - - return async function x402FetchWrapper(input: string | URL, init?: RequestInit): Promise { - const response = await fetchFn(input, init); - - // Check if this is an X402 payment challenge - if (response.status !== 402) { - return response; - } - - log.info('Received X402 payment challenge'); - - try { - // Parse the X402 payment requirements from response body - const responseBody = await response.text(); - const paymentChallenge = JSON.parse(responseBody); - - // Check if this is a valid X402 response - if (!paymentChallenge.x402Version || !paymentChallenge.accepts || !Array.isArray(paymentChallenge.accepts)) { - log.debug('Received 402 response without valid X402 format'); - return response; - } - - const { x402Version, accepts } = paymentChallenge; - - // Use x402's selectPaymentRequirements to find the best option - // This matches what x402-fetch does internally - const selectedPaymentRequirements = selectPaymentRequirements( - accepts as PaymentRequirements[], - 'base', // We only support base for now - 'exact' - ); - - if (!selectedPaymentRequirements) { - log.error('No suitable payment requirements found'); - return response; - } - - const { network, maxAmountRequired, payTo: recipient, asset } = selectedPaymentRequirements; - - // Convert maxAmountRequired from wei to decimal (USDC has 6 decimals) - const amount = new BigNumber(maxAmountRequired).dividedBy(new BigNumber(10).pow(6)).toString(); - const currency = 'USDC'; - - log.debug(`Payment required: ${amount} ${currency} on ${network} to ${recipient}`); - - // Find the appropriate payment maker - const paymentMaker = account.paymentMakers[network]; - - if (!paymentMaker) { - log.info(`No payment maker found for ${network}`); - return response; - } - - // For now, we'll use our existing EIP-3009 authorization method - // In a real implementation, we'd use x402's createPaymentHeader with a proper signer - log.debug(`Creating EIP-3009 payment authorization`); - - const eip3009Authorization = await paymentMaker.createPaymentAuthorization( - new BigNumber(amount), - currency, - recipient, - '' - ); - - // Wrap in X402 message format (same as before) - const x402Message: X402Message = { - x402Version: x402Version, - scheme: 'exact', - network: network, - payload: eip3009Authorization - }; - - // Base64 encode the X402 message - const x402MessageJson = JSON.stringify(x402Message); - log.debug(`X402 message being sent: ${x402MessageJson}`); - const x402MessageBase64 = typeof Buffer !== 'undefined' - ? Buffer.from(x402MessageJson).toString('base64') - : btoa(x402MessageJson); - - // Add the Access-Control-Expose-Headers header like x402-fetch does - const retryInit = { - ...init, - headers: { - ...(init?.headers || {}), - 'X-PAYMENT': x402MessageBase64, - 'Access-Control-Expose-Headers': 'X-PAYMENT-RESPONSE' - } - }; - - log.info('Retrying request with X-Payment header'); - - // Retry the request - const retryResponse = await fetchFn(input, retryInit); - - if (retryResponse.ok) { - log.info('X402 payment accepted, request successful'); - } else { - log.warn(`Request failed after payment with status ${retryResponse.status}`); - } - - return retryResponse; - } catch (error) { - // If there's an error processing the payment, return the original 402 response - log.error(`Failed to handle X402 payment challenge: ${error}`); - return response; - } - }; -} \ No newline at end of file diff --git a/packages/atxp-client/src/x402WrapperWithSigner.ts b/packages/atxp-client/src/x402WrapperWithSigner.ts deleted file mode 100644 index d715864f..00000000 --- a/packages/atxp-client/src/x402WrapperWithSigner.ts +++ /dev/null @@ -1,177 +0,0 @@ -import { ClientConfig, ProspectivePayment } from './types.js'; -import { BaseAccount } from './baseAccount.js'; -import { FetchLike, Logger, Network } from '@atxp/common'; -import { BigNumber } from 'bignumber.js'; -import { createPaymentHeader, selectPaymentRequirements } from 'x402/client'; -import { LocalAccount } from 'viem'; - -/** - * Wraps fetch with X402 payment support using a local signer - * This wrapper intercepts 402 responses and creates payments using the x402 library - * - * @param config - ClientConfig containing account, logger, and fetch function - * @returns A wrapped fetch function that handles X402 payments - */ -export function wrapWithX402(config: ClientConfig): FetchLike { - const { account, logger, fetchFn = fetch, approvePayment, onPayment, onPaymentFailure } = config; - const log = logger ?? console; - - // Check if account has getSigner method (only BaseAccount for now) - const accountWithSigner = account as any; - if (!accountWithSigner.getSigner) { - throw new Error('Account does not support getSigner, X402 payments will not work'); - } - - const signer: LocalAccount = accountWithSigner.getSigner(); - log.debug('Using local signer for X402 payments'); - - return async function x402FetchWrapper(input: string | URL, init?: RequestInit): Promise { - const response = await fetchFn(input, init); - - // Check if this is an X402 payment challenge - if (response.status !== 402) { - return response; - } - - log.info('Received X402 payment challenge'); - - try { - // Parse the X402 payment requirements from response body - const responseBody = await response.text(); - const paymentChallenge = JSON.parse(responseBody); - - // Check if this is a valid X402 response - if (!paymentChallenge.x402Version || !paymentChallenge.accepts || !Array.isArray(paymentChallenge.accepts)) { - log.debug('Received 402 response without valid X402 format'); - // Return a new Response with the original body since we consumed it - return new Response(responseBody, { - status: response.status, - statusText: response.statusText, - headers: response.headers - }); - } - - // Select the best payment requirements (prefer base network, exact scheme) - const selectedPaymentRequirements = selectPaymentRequirements( - paymentChallenge.accepts, - 'base', - 'exact' - ); - - if (!selectedPaymentRequirements) { - log.info('No suitable X402 payment option found'); - return new Response(responseBody, { - status: response.status, - statusText: response.statusText, - headers: response.headers - }); - } - - // Convert amount from wei to human-readable for logging and approval - const amountInUsdc = Number(selectedPaymentRequirements.maxAmountRequired) / (10 ** 6); - log.debug(`Payment required: ${amountInUsdc} USDC on ${selectedPaymentRequirements.network} to ${selectedPaymentRequirements.payTo}`); - - // Create the ProspectivePayment object for callbacks - const url = typeof input === 'string' ? input : input.toString(); - const prospectivePayment: ProspectivePayment = { - accountId: account.accountId, - resourceUrl: url, - resourceName: selectedPaymentRequirements.description || url, - network: selectedPaymentRequirements.network as Network, - currency: 'USDC', - amount: new BigNumber(amountInUsdc), - iss: selectedPaymentRequirements.payTo - }; - - // Check if payment should be approved - if (approvePayment) { - const approved = await approvePayment(prospectivePayment); - - if (!approved) { - log.info('Payment not approved by user'); - if (onPaymentFailure) { - await onPaymentFailure({ - payment: prospectivePayment, - error: new Error('Payment not approved') - }); - } - return new Response(responseBody, { - status: response.status, - statusText: response.statusText, - headers: response.headers - }); - } - } - - // Create the X402 payment header using the x402 library - log.debug('Creating X402 payment header with signer'); - const paymentHeader = await createPaymentHeader( - signer, - paymentChallenge.x402Version, - selectedPaymentRequirements - ); - - // Add the payment header and retry the request - const retryInit = { - ...init, - headers: { - ...(init?.headers || {}), - 'X-PAYMENT': paymentHeader, - // Request the payment response header - 'Access-Control-Expose-Headers': 'X-PAYMENT-RESPONSE' - } - }; - - log.info('Retrying request with X-PAYMENT header'); - const retryResponse = await fetchFn(input, retryInit); - - if (retryResponse.ok) { - log.info('X402 payment accepted, request successful'); - - // Call onPayment callback if provided - if (onPayment) { - await onPayment({ payment: prospectivePayment }); - } - } else { - log.warn(`Request failed after payment with status ${retryResponse.status}`); - - if (onPaymentFailure) { - await onPaymentFailure({ - payment: prospectivePayment, - error: new Error(`Request failed with status ${retryResponse.status}`) - }); - } - } - - return retryResponse; - } catch (error) { - // If there's an error processing the payment, call failure callback and return original response - log.error(`Failed to handle X402 payment challenge: ${error}`); - - // Try to recreate the response with the body we might have consumed - const responseBody = await response.text(); - const paymentChallenge = JSON.parse(responseBody); - - if (onPaymentFailure && paymentChallenge?.accepts?.[0]) { - const firstOption = paymentChallenge.accepts[0]; - const amount = Number(firstOption.maxAmountRequired) / (10 ** 6); - const url = typeof input === 'string' ? input : input.toString(); - await onPaymentFailure({ - payment: { - accountId: account.accountId, - resourceUrl: url, - resourceName: firstOption.description || url, - network: firstOption.network as Network, - currency: 'USDC', - amount: new BigNumber(amount), - iss: firstOption.payTo - }, - error: error as Error - }); - } - - // Return the original response - return response; - } - }; -} \ No newline at end of file From 3f865853be9975b171138abe84e40783b8875ff5 Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 16:33:10 -0700 Subject: [PATCH 31/61] WIP: RemoteSigner --- packages/atxp-client/src/atxpAccount.ts | 34 +++++++----- packages/atxp-client/src/remoteSigner.ts | 71 +++++++----------------- packages/atxp-client/src/x402Wrapper.ts | 9 +-- 3 files changed, 47 insertions(+), 67 deletions(-) diff --git a/packages/atxp-client/src/atxpAccount.ts b/packages/atxp-client/src/atxpAccount.ts index 22ed520c..ad678d52 100644 --- a/packages/atxp-client/src/atxpAccount.ts +++ b/packages/atxp-client/src/atxpAccount.ts @@ -138,19 +138,27 @@ export class ATXPAccount implements Account { /** * Get a signer that can be used with the x402 library - * This will use RemoteSigner to delegate signing to the accounts-x402 server - * NOTE: This requires the accounts-x402 server to implement a signTypedData endpoint + * This uses RemoteSigner to delegate signing to the accounts-x402 server */ - getSigner(): LocalAccount { - // TODO: We need to get the wallet address from the accounts-x402 server - // For now, throw an error indicating this is not yet implemented - throw new Error('ATXPAccount.getSigner() is not yet implemented - requires signTypedData endpoint on accounts-x402 server'); - - // Future implementation: - // return new RemoteSigner( - // walletAddress, - // this.origin, - // this.fetchFn - // ); + async getSigner(): Promise { + // Get the wallet address from the destination endpoint + const response = await this.fetchFn(`${this.origin}/destination`, { + headers: { + 'Authorization': toBasicAuth(this.token) + } + }); + + if (!response.ok) { + throw new Error(`ATXPAccount: Failed to get wallet address: ${response.status} ${response.statusText}`); + } + + const { destination } = await response.json() as { destination: string }; + + return new RemoteSigner( + destination as `0x${string}`, + this.origin, + toBasicAuth(this.token), + this.fetchFn + ); } } \ No newline at end of file diff --git a/packages/atxp-client/src/remoteSigner.ts b/packages/atxp-client/src/remoteSigner.ts index 2247f4cc..75410c54 100644 --- a/packages/atxp-client/src/remoteSigner.ts +++ b/packages/atxp-client/src/remoteSigner.ts @@ -11,52 +11,37 @@ export class RemoteSigner implements LocalAccount { constructor( public readonly address: Address, private accountsApiUrl: string, + private authorizationHeader: string, private fetchFn: FetchLike = fetch as FetchLike ) {} /** * Sign a typed data structure using EIP-712 - * This is what x402-fetch will call for EIP-3009 authorization + * This is what x402 library will call for EIP-3009 authorization */ async signTypedData< const TTypedData extends TypedData | { [key: string]: unknown }, TPrimaryType extends string = string, >(typedData: TTypedData): Promise { - // Extract the actual typed data parameters - const { domain, types, primaryType, message } = typedData as any; + const response = await this.fetchFn(`${this.accountsApiUrl}/sign-typed-data`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + // Add authorization header if we have a token + ...(this.authorizationHeader ? { 'Authorization': this.authorizationHeader } : {}) + }, + body: JSON.stringify({ + typedData + }) + }); - // For EIP-3009, we need to send this to accounts-x402's /create-payment-authorization endpoint - if (primaryType === 'TransferWithAuthorization') { - const response = await this.fetchFn(`${this.accountsApiUrl}/create-payment-authorization`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - from: message.from, - to: message.to, - value: message.value, - validAfter: message.validAfter, - validBefore: message.validBefore, - nonce: message.nonce, - asset: domain.verifyingContract, - network: this.getNetworkFromChainId(domain.chainId), - extra: { - name: domain.name, - version: domain.version - } - }) - }); - - if (!response.ok) { - throw new Error(`Failed to sign authorization: ${response.status} ${response.statusText}`); - } - - const result = await response.json(); - return result.signature as Hex; + if (!response.ok) { + const errorText = await response.text(); + throw new Error(`Failed to sign typed data: ${response.status} ${response.statusText} ${errorText}`); } - throw new Error('Unsupported typed data signing'); + const result = await response.json(); + return result.signature as Hex; } /** @@ -80,34 +65,20 @@ export class RemoteSigner implements LocalAccount { // Return a dummy public key since we don't have access to it return '0x0000000000000000000000000000000000000000000000000000000000000000' as Hex; } - - /** - * Get chain ID from network - helper method - */ - private getNetworkFromChainId(chainId: number): string { - const chainIdToNetwork: { [key: number]: string } = { - 8453: 'base', - 84532: 'base-sepolia', - 43114: 'avalanche', - 43113: 'avalanche-fuji', - 1329: 'sei', - 1328: 'sei-testnet' - }; - - return chainIdToNetwork[chainId] || 'base'; - } } /** * Create a remote signer for use with x402-fetch * @param address The address of the account * @param accountsApiUrl The URL of the accounts-x402 API + * @param authorizationHeader The authorization header to use for API calls * @param fetchFn Optional fetch function to use */ export function createRemoteSigner( address: Address, accountsApiUrl: string, + authorizationHeader: string, fetchFn?: FetchLike ): RemoteSigner { - return new RemoteSigner(address, accountsApiUrl, fetchFn); + return new RemoteSigner(address, accountsApiUrl, authorizationHeader, fetchFn); } \ No newline at end of file diff --git a/packages/atxp-client/src/x402Wrapper.ts b/packages/atxp-client/src/x402Wrapper.ts index 5ab05d7d..7e8b6129 100644 --- a/packages/atxp-client/src/x402Wrapper.ts +++ b/packages/atxp-client/src/x402Wrapper.ts @@ -16,15 +16,12 @@ export function wrapWithX402(config: ClientConfig): FetchLike { const { account, logger, fetchFn = fetch, approvePayment, onPayment, onPaymentFailure } = config; const log = logger ?? console; - // Check if account has getSigner method (only BaseAccount for now) + // Check if account has getSigner method const accountWithSigner = account as any; if (!accountWithSigner.getSigner) { throw new Error('Account does not support getSigner, X402 payments will not work'); } - const signer: LocalAccount = accountWithSigner.getSigner(); - log.debug('Using local signer for X402 payments'); - return async function x402FetchWrapper(input: string | URL, init?: RequestInit): Promise { const response = await fetchFn(input, init); @@ -103,6 +100,10 @@ export function wrapWithX402(config: ClientConfig): FetchLike { } } + // Get the signer from the account + log.debug('Getting signer from account'); + const signer: LocalAccount = await accountWithSigner.getSigner(); + // Create the X402 payment header using the x402 library log.debug('Creating X402 payment header with signer'); const paymentHeader = await createPaymentHeader( From 745362444b6f82b5976bcf154eadf82ed93be344 Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 16:51:58 -0700 Subject: [PATCH 32/61] Cleanup --- examples/x402-server/src/decode-headers.ts | 47 ----------- examples/x402-server/src/test-compare.ts | 83 ------------------- .../x402-server/src/test-debug-wrapper.ts | 72 ---------------- examples/x402-server/src/test-hybrid.ts | 65 --------------- examples/x402-server/src/test-new-wrapper.ts | 60 -------------- examples/x402-server/src/test-x402-fetch.ts | 64 -------------- .../src/test-x402fetch-with-base.ts | 79 ------------------ package.json | 3 +- packages/atxp-base/src/baseAppPaymentMaker.ts | 7 +- .../atxp-base/src/mainWalletPaymentMaker.ts | 6 +- packages/atxp-client/src/atxpAccount.ts | 2 +- .../atxp-client/src/atxpClient.events.test.ts | 52 +----------- packages/atxp-client/src/atxpClient.test.ts | 43 ++-------- .../atxp-client/src/atxpFetcher.oauth.test.ts | 13 +-- .../src/atxpFetcher.payment.test.ts | 13 +-- packages/atxp-client/src/index.ts | 4 +- packages/atxp-client/src/remoteSigner.ts | 25 +++--- .../atxp-client/src/solanaPaymentMaker.ts | 7 +- packages/atxp-client/src/types.ts | 21 ----- 19 files changed, 32 insertions(+), 634 deletions(-) delete mode 100644 examples/x402-server/src/decode-headers.ts delete mode 100644 examples/x402-server/src/test-compare.ts delete mode 100644 examples/x402-server/src/test-debug-wrapper.ts delete mode 100644 examples/x402-server/src/test-hybrid.ts delete mode 100644 examples/x402-server/src/test-new-wrapper.ts delete mode 100644 examples/x402-server/src/test-x402-fetch.ts delete mode 100644 examples/x402-server/src/test-x402fetch-with-base.ts diff --git a/examples/x402-server/src/decode-headers.ts b/examples/x402-server/src/decode-headers.ts deleted file mode 100644 index 0b58c841..00000000 --- a/examples/x402-server/src/decode-headers.ts +++ /dev/null @@ -1,47 +0,0 @@ -// Decode and compare the X-Payment headers from both implementations - -const x402FetchHeader = 'eyJ4NDAyVmVyc2lvbiI6MSwic2NoZW1lIjoiZXhhY3QiLCJuZXR3b3JrIjoiYmFzZSIsInBheWxvYWQiOnsic2lnbmF0dXJlIjoiMHgyNzU5MWY4OTAzODcyY2QyZjEwNzEwN2I0NzM1MDVhYzhjMGQ1ZDI1NmYxY2MxN2I5MWQ3MWQ4NDU1MWEzMTVmNjVjZDZjNGY3YWJhOTJkM2NjYmQ0MDU4N2FiYzQ3OGM5OGIyYzI5MWQ1NTllNzBhOTFkYTEyMGE4OWNhNDhkMjFjIiwiYXV0aG9yaXphdGlvbiI6eyJmcm9tIjoiMHg3RjlEMWE4Nzk3NTAxNjhiOGY0QTU5NzM0QjEyNjJEMTc3OGZEQjVBIiwidG8iOiIweDMyMTQyMThDZEI2QTBFNTk3MDY3N0NkQ2E5ZUI2NTM2NWVmNTg3RkQiLCJ2YWx1ZSI6IjEwMDAwIiwidmFsaWRBZnRlciI6IjE3NTgyMjcxODciLCJ2YWxpZEJlZm9yZSI6IjE3NTgyMjc4NDciLCJub25jZSI6IjB4ZWIzOTgzYTQ3MWEwNGU0Njg2MGIyNzMxNzkzYjNkZThhMDRiN2I2ODQ3NjJkZGRiYjkwMzQ1M2U4MzVjNDAyOCJ9fX0='; - -const customWrapperHeader = 'eyJ4NDAyVmVyc2lvbiI6MSwic2NoZW1lIjoiZXhhY3QiLCJuZXR3b3JrIjoiYmFzZSIsInBheWxvYWQiOnsic2lnbmF0dXJlIjoiMHhlZWY1MWQ2YmJhZjJmMjU2MjBlNWJhZDgyOWZiMTBkMmM4ODFlNjdkNzg5NGQ2MmVkNWIyNDFlMjcxM2ZjZTNjNTJmMTM0Zjg5YWIwNzExNDNkN2JjMzliMmUxM2E1ZjgzN2U0NGEwZjI4YWQ1ZjMwNjkzNDcxNWExMzExNmI5YzFjIiwiYXV0aG9yaXphdGlvbiI6eyJmcm9tIjoiMHg3RjlEMWE4Nzk3NTAxNjhiOGY0QTU5NzM0QjEyNjJEMTc3OGZEQjVBIiwidG8iOiIweDMyMTQyMThDZEI2QTBFNTk3MDY3N0NkQ2E5ZUI2NTM2NWVmNTg3RkQiLCJ2YWx1ZSI6IjEwMDAwIiwidmFsaWRBZnRlciI6IjE3NTgyMjc3OTciLCJ2YWxpZEJlZm9yZSI6IjE3NTgyMzEzOTciLCJub25jZSI6IjB4YTk2YzRjNTcxMWYyNTMyOWE2MjY2Y2RmZjFlZTUyNTZiNzBlZTBmNDNkNWFlZDM5MTI0ZTM1NmQxMTVlNzE4MyJ9fX0='; - -console.log('=== X402-FETCH HEADER ==='); -const x402FetchDecoded = Buffer.from(x402FetchHeader, 'base64').toString('utf-8'); -const x402FetchJson = JSON.parse(x402FetchDecoded); -console.log(JSON.stringify(x402FetchJson, null, 2)); - -console.log('\n=== CUSTOM WRAPPER HEADER ==='); -const customWrapperDecoded = Buffer.from(customWrapperHeader, 'base64').toString('utf-8'); -const customWrapperJson = JSON.parse(customWrapperDecoded); -console.log(JSON.stringify(customWrapperJson, null, 2)); - -console.log('\n=== DIFFERENCES ==='); - -// Compare top-level fields -for (const key in x402FetchJson) { - if (key !== 'payload' && x402FetchJson[key] !== customWrapperJson[key]) { - console.log(`${key}: x402-fetch="${x402FetchJson[key]}" vs custom="${customWrapperJson[key]}"`); - } -} - -// Compare payload.authorization fields (excluding dynamic fields like nonce, validAfter, validBefore, signature) -const x402Auth = x402FetchJson.payload.authorization; -const customAuth = customWrapperJson.payload.authorization; - -console.log('\nStatic fields comparison:'); -console.log(`from: ${x402Auth.from === customAuth.from ? '✅ SAME' : '❌ DIFFERENT'} (${x402Auth.from})`); -console.log(`to: ${x402Auth.to === customAuth.to ? '✅ SAME' : '❌ DIFFERENT'} (${x402Auth.to})`); -console.log(`value: ${x402Auth.value === customAuth.value ? '✅ SAME' : '❌ DIFFERENT'} (${x402Auth.value})`); - -console.log('\nDynamic fields (expected to be different):'); -console.log(`signature: ${x402FetchJson.payload.signature.substring(0, 20)}... vs ${customWrapperJson.payload.signature.substring(0, 20)}...`); -console.log(`nonce: ${x402Auth.nonce.substring(0, 20)}... vs ${customAuth.nonce.substring(0, 20)}...`); -console.log(`validAfter: ${x402Auth.validAfter} vs ${customAuth.validAfter}`); -console.log(`validBefore: ${x402Auth.validBefore} vs ${customAuth.validBefore}`); - -// Check for any extra fields -console.log('\nField presence check:'); -const x402FetchFields = Object.keys(x402FetchJson.payload.authorization).sort(); -const customWrapperFields = Object.keys(customWrapperJson.payload.authorization).sort(); -console.log('x402-fetch fields:', x402FetchFields.join(', ')); -console.log('custom wrapper fields:', customWrapperFields.join(', ')); -console.log('Fields match:', JSON.stringify(x402FetchFields) === JSON.stringify(customWrapperFields) ? '✅ YES' : '❌ NO'); \ No newline at end of file diff --git a/examples/x402-server/src/test-compare.ts b/examples/x402-server/src/test-compare.ts deleted file mode 100644 index 113ab522..00000000 --- a/examples/x402-server/src/test-compare.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { wrapFetchWithPayment, createSigner, type Hex } from 'x402-fetch'; -import { wrapWithX402, BaseAccount } from '@atxp/client'; -import { ConsoleLogger, LogLevel } from '@atxp/common'; -import dotenv from 'dotenv'; -import path from 'path'; -import { fileURLToPath } from 'url'; - -const __dirname = path.dirname(fileURLToPath(import.meta.url)); - -// Load .env -dotenv.config(); -dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); - -async function compareImplementations() { - if (!process.env.BASE_RPC || !process.env.BASE_PRIVATE_KEY) { - console.error('Missing BASE_RPC and/or BASE_PRIVATE_KEY'); - process.exit(1); - } - - const serverUrl = process.env.X402_SERVER_URL || 'http://localhost:3001'; - const endpointPath = '/api/resource'; - const url = `${serverUrl}${endpointPath}`; - - console.log('=== Testing Official x402-fetch Library ==='); - try { - const privateKey = process.env.BASE_PRIVATE_KEY as Hex; - const signer = await createSigner('base', privateKey); - - // Intercept fetch to log headers - const originalFetch = fetch; - const loggingFetch = async (input: any, init?: any) => { - console.log('x402-fetch request headers:', init?.headers); - return originalFetch(input, init); - }; - - const fetchWithPayment = wrapFetchWithPayment(loggingFetch as any, signer, { - maxPaymentValue: 1000000000000000000n - }); - - const response = await fetchWithPayment(url, { method: 'GET' }); - - if (response.ok) { - const data = await response.json(); - console.log('✅ x402-fetch Success:', data); - } else { - console.log('❌ x402-fetch Failed:', response.status); - } - } catch (error) { - console.error('x402-fetch Error:', error); - } - - console.log('\n=== Testing Custom wrapWithX402 Implementation ==='); - try { - const account = new BaseAccount( - process.env.BASE_RPC, - process.env.BASE_PRIVATE_KEY - ); - - const logger = new ConsoleLogger({ prefix: '[Custom]', level: LogLevel.DEBUG }); - - // Intercept fetch to log headers - const originalFetch = fetch; - const loggingFetch = async (input: any, init?: any) => { - console.log('Custom wrapper request headers:', init?.headers); - return originalFetch(input, init); - }; - - const x402Fetch = wrapWithX402(loggingFetch as any, account, logger); - - const response = await x402Fetch(url); - - if (response.ok) { - const data = await response.json(); - console.log('✅ Custom wrapper Success:', data); - } else { - console.log('❌ Custom wrapper Failed:', response.status); - } - } catch (error) { - console.error('Custom wrapper Error:', error); - } -} - -compareImplementations().catch(console.error); \ No newline at end of file diff --git a/examples/x402-server/src/test-debug-wrapper.ts b/examples/x402-server/src/test-debug-wrapper.ts deleted file mode 100644 index 8a31360b..00000000 --- a/examples/x402-server/src/test-debug-wrapper.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { BaseAccount } from '@atxp/client'; -import { ConsoleLogger, LogLevel } from '@atxp/common'; -import { BigNumber } from 'bignumber.js'; -import dotenv from 'dotenv'; -import path from 'path'; -import { fileURLToPath } from 'url'; - -const __dirname = path.dirname(fileURLToPath(import.meta.url)); - -// Load .env -dotenv.config(); -dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); - -async function debugOurImplementation() { - console.log('=== Debugging Our signTypedData Implementation ===\n'); - - if (!process.env.BASE_RPC || !process.env.BASE_PRIVATE_KEY) { - console.error('Missing BASE_RPC and/or BASE_PRIVATE_KEY'); - process.exit(1); - } - - const account = new BaseAccount( - process.env.BASE_RPC, - process.env.BASE_PRIVATE_KEY - ); - - const logger = new ConsoleLogger({ prefix: '[Debug]', level: LogLevel.DEBUG }); - - // Create the exact same authorization parameters that would be created - const recipient = '0x3214218CdB6A0E5970677CdCa9EB65365eF587fD'; - const amount = new BigNumber('0.01'); - const currency = 'USDC'; - - console.log('Creating EIP-3009 authorization with:'); - console.log(' Amount:', amount.toString(), currency); - console.log(' Recipient:', recipient); - console.log(' From:', account.accountId); - - // Get the payment maker to see exactly what it's doing - const paymentMaker = account.paymentMakers['base']; - - try { - // Create the authorization and log the exact parameters - console.log('\nCalling createPaymentAuthorization...'); - const authorization = await paymentMaker.createPaymentAuthorization( - amount, - currency, - recipient, - '' - ); - - console.log('\n=== Authorization Result ==='); - console.log(JSON.stringify(authorization, null, 2)); - - // Now let's also look at what parameters were used for signing - // We'll need to check our BasePaymentMaker implementation - console.log('\nKey parameters from our implementation:'); - console.log('- validAfter: now'); - console.log('- validBefore: now + 660 seconds (11 minutes)'); - console.log('- nonce: random 32 bytes'); - console.log('- value: amount * 10^6 (USDC decimals)'); - console.log('- chainId: 8453 (Base mainnet)'); - console.log('- verifyingContract: 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 (USDC on Base)'); - console.log('- domain.name: "USD Coin"'); - console.log('- domain.version: "2"'); - - } catch (error) { - console.error('Error creating authorization:', error); - } -} - -debugOurImplementation().catch(console.error); \ No newline at end of file diff --git a/examples/x402-server/src/test-hybrid.ts b/examples/x402-server/src/test-hybrid.ts deleted file mode 100644 index d358fdb7..00000000 --- a/examples/x402-server/src/test-hybrid.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { wrapFetchWithPayment } from 'x402-fetch'; -import { createRemoteSigner } from '@atxp/client'; -import dotenv from 'dotenv'; -import path from 'path'; -import { fileURLToPath } from 'url'; - -const __dirname = path.dirname(fileURLToPath(import.meta.url)); - -// Load .env from current directory first, then from repo root -dotenv.config(); // Load local .env if it exists -dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); // Also load from repo root - -async function testHybridApproach() { - console.log('=== Testing Hybrid Approach: x402-fetch + Remote Signer ==='); - - // For now, we'll use the local signing since we don't have accounts-x402 running - // But this shows how we'd use the remote signer with x402-fetch - - const accountAddress = '0x7F9D1a879750168b8f4A59734B1262D1778fDB5A'; - const accountsApiUrl = 'https://accounts.atxp.ai'; // Would be the real accounts API - - console.log('Creating remote signer for address:', accountAddress); - console.log('Accounts API URL:', accountsApiUrl); - - // Create a remote signer that delegates to accounts-x402 - const remoteSigner = createRemoteSigner( - accountAddress as `0x${string}`, - accountsApiUrl - ); - - console.log('Remote signer created'); - - // Use x402-fetch's wrapFetchWithPayment with our remote signer - const fetchWithPayment = wrapFetchWithPayment(fetch as any, remoteSigner as any, { - maxPaymentValue: 1000000000000000000n // Maximum payment allowed - }); - - const serverUrl = process.env.X402_SERVER_URL || 'http://localhost:3001'; - const url = `${serverUrl}/api/resource`; - - console.log('Making request to:', url); - console.log('Note: This will fail since we don\'t have accounts-x402 running,'); - console.log('but it demonstrates how to combine x402-fetch with remote signing.'); - - try { - const response = await fetchWithPayment(url, { - method: 'GET' - }); - - if (response.ok) { - const data = await response.json(); - console.log('✅ Success! Response:', data); - } else { - console.log('❌ Request failed:', response.status, response.statusText); - const errorText = await response.text(); - console.log('Error details:', errorText); - } - } catch (error: any) { - console.log('❌ Error:', error.message || error); - console.log('\nThis is expected since we don\'t have the accounts-x402 API running.'); - console.log('In production, the remote signer would call the accounts API to sign.'); - } -} - -testHybridApproach().catch(console.error); \ No newline at end of file diff --git a/examples/x402-server/src/test-new-wrapper.ts b/examples/x402-server/src/test-new-wrapper.ts deleted file mode 100644 index 830fc9b0..00000000 --- a/examples/x402-server/src/test-new-wrapper.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { wrapWithX402UsingLibrary } from '@atxp/client'; -import { ConsoleLogger, LogLevel } from '@atxp/common'; -import dotenv from 'dotenv'; -import path from 'path'; -import { fileURLToPath } from 'url'; -import type { Hex } from 'viem'; - -const __dirname = path.dirname(fileURLToPath(import.meta.url)); - -// Load .env -dotenv.config(); -dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); - -async function testNewWrapper() { - console.log('=== Testing New Wrapper Using x402 Library Functions ==='); - - if (!process.env.BASE_PRIVATE_KEY) { - console.error('Missing BASE_PRIVATE_KEY'); - process.exit(1); - } - - const privateKey = process.env.BASE_PRIVATE_KEY as Hex; - const logger = new ConsoleLogger({ prefix: '[NewWrapper]', level: LogLevel.DEBUG }); - - // Use our new wrapper that uses x402's createPaymentHeader directly - const x402Fetch = wrapWithX402UsingLibrary(fetch as any, privateKey, logger); - - const serverUrl = process.env.X402_SERVER_URL || 'http://localhost:3001'; - const url = `${serverUrl}/api/resource`; - - console.log('Making request to:', url); - console.log('This wrapper uses x402\'s createPaymentHeader directly (same as x402-fetch)\n'); - - try { - const response = await x402Fetch(url); - - if (response.ok) { - const data = await response.json(); - console.log('✅ Success! Response:', data); - - // Try to decode payment response if available - const paymentResponseHeader = response.headers.get('x-payment-response'); - if (paymentResponseHeader) { - const paymentResponseJson = Buffer.from(paymentResponseHeader, 'base64').toString('utf-8'); - const paymentResponse = JSON.parse(paymentResponseJson); - console.log('Payment response:', paymentResponse); - } - - console.log('\n🎉 The new wrapper works! This proves we can use x402\'s functions directly.'); - } else { - console.log('❌ Request failed:', response.status, response.statusText); - const errorText = await response.text(); - console.log('Error details:', errorText); - } - } catch (error: any) { - console.log('❌ Error:', error.message || error); - } -} - -testNewWrapper().catch(console.error); \ No newline at end of file diff --git a/examples/x402-server/src/test-x402-fetch.ts b/examples/x402-server/src/test-x402-fetch.ts deleted file mode 100644 index 84909467..00000000 --- a/examples/x402-server/src/test-x402-fetch.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { wrapFetchWithPayment, createSigner, decodeXPaymentResponse, type Hex } from 'x402-fetch'; -import dotenv from 'dotenv'; -import path from 'path'; -import { fileURLToPath } from 'url'; - -const __dirname = path.dirname(fileURLToPath(import.meta.url)); - -// Load .env from current directory first, then from repo root -dotenv.config(); // Load local .env if it exists -dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); // Also load from repo root - -async function testX402Fetch() { - // Check for required environment variables - if (!process.env.BASE_PRIVATE_KEY) { - console.error('Missing BASE_PRIVATE_KEY'); - process.exit(1); - } - - const privateKey = process.env.BASE_PRIVATE_KEY as Hex; - const serverUrl = process.env.X402_SERVER_URL || 'http://localhost:3001'; - const endpointPath = '/api/resource'; - const url = `${serverUrl}${endpointPath}`; - - console.log('Using x402-fetch library'); - console.log('Server URL:', url); - - try { - // Create a signer for Base mainnet - const signer = await createSigner('base', privateKey); - console.log('Created signer with private key'); - - // Wrap fetch with payment functionality - const fetchWithPayment = wrapFetchWithPayment(fetch as any, signer, { - maxPaymentValue: 1000000000000000000n // Maximum payment allowed (1 USDC in wei with 6 decimals = 1000000) - }); - - console.log('Making request with x402-fetch...'); - - // Make a request that will trigger payment - const response = await fetchWithPayment(url, { - method: 'GET' - }); - - if (response.ok) { - const data = await response.json(); - console.log('Success! Response:', data); - - // Try to decode payment response if available - const paymentResponseHeader = response.headers.get('x-payment-response'); - if (paymentResponseHeader) { - const paymentResponse = decodeXPaymentResponse(paymentResponseHeader); - console.log('Payment response:', paymentResponse); - } - } else { - console.error('Request failed:', response.status, response.statusText); - const errorText = await response.text(); - console.error('Error details:', errorText); - } - } catch (error) { - console.error('Error:', error); - } -} - -testX402Fetch().catch(console.error); \ No newline at end of file diff --git a/examples/x402-server/src/test-x402fetch-with-base.ts b/examples/x402-server/src/test-x402fetch-with-base.ts deleted file mode 100644 index dd7c1f30..00000000 --- a/examples/x402-server/src/test-x402fetch-with-base.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { wrapFetchWithPayment, createSigner } from 'x402-fetch'; -import { BaseAccount } from '@atxp/client'; -import { ConsoleLogger, LogLevel } from '@atxp/common'; -import dotenv from 'dotenv'; -import path from 'path'; -import { fileURLToPath } from 'url'; -import type { Hex } from 'viem'; - -const __dirname = path.dirname(fileURLToPath(import.meta.url)); - -// Load .env -dotenv.config(); -dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); - -async function testX402FetchWithBaseAccount() { - console.log('=== Using x402-fetch with BaseAccount\'s Private Key ==='); - - if (!process.env.BASE_RPC || !process.env.BASE_PRIVATE_KEY) { - console.error('Missing BASE_RPC and/or BASE_PRIVATE_KEY'); - process.exit(1); - } - - // Create BaseAccount to verify we have the right credentials - const account = new BaseAccount( - process.env.BASE_RPC, - process.env.BASE_PRIVATE_KEY - ); - - console.log('BaseAccount created with address:', account.accountId); - - // Now use x402-fetch's createSigner with the same private key - const signer = await createSigner('base', process.env.BASE_PRIVATE_KEY as Hex); - console.log('x402-fetch signer created'); - - // Create logger - const logger = new ConsoleLogger({ prefix: '[X402-Fetch]', level: LogLevel.DEBUG }); - - // Wrap fetch with x402-fetch's payment handling - const fetchWithPayment = wrapFetchWithPayment(fetch as any, signer, { - maxPaymentValue: 1000000000000000000n // Maximum payment allowed - }); - - const serverUrl = process.env.X402_SERVER_URL || 'http://localhost:3001'; - const url = `${serverUrl}/api/resource`; - - console.log('Making request to:', url); - console.log('Using x402-fetch library with BaseAccount\'s credentials...\n'); - - try { - const response = await fetchWithPayment(url, { - method: 'GET' - }); - - if (response.ok) { - const data = await response.json(); - console.log('✅ Success! Response:', data); - - // Try to decode payment response if available - const paymentResponseHeader = response.headers.get('x-payment-response'); - if (paymentResponseHeader) { - // Decode base64 - const paymentResponseJson = Buffer.from(paymentResponseHeader, 'base64').toString('utf-8'); - const paymentResponse = JSON.parse(paymentResponseJson); - console.log('Payment response:', paymentResponse); - } - - console.log('\n✨ This proves x402-fetch works correctly with our Base credentials!'); - console.log('The issue with our custom wrapper must be in how we\'re creating/signing the authorization.'); - } else { - console.log('❌ Request failed:', response.status, response.statusText); - const errorText = await response.text(); - console.log('Error details:', errorText); - } - } catch (error: any) { - console.log('❌ Error:', error.message || error); - } -} - -testX402FetchWithBaseAccount().catch(console.error); \ No newline at end of file diff --git a/package.json b/package.json index 9ed85db7..848f6808 100644 --- a/package.json +++ b/package.json @@ -46,8 +46,7 @@ "prepack:all": "npm run prepack --workspaces --if-present" }, "dependencies": { - "dotenv": "^16.5.0", - "x402-fetch": "^0.6.0" + "dotenv": "^16.5.0" }, "devDependencies": { "@rollup/plugin-commonjs": "^28.0.6", diff --git a/packages/atxp-base/src/baseAppPaymentMaker.ts b/packages/atxp-base/src/baseAppPaymentMaker.ts index a36eb8c8..b8693562 100644 --- a/packages/atxp-base/src/baseAppPaymentMaker.ts +++ b/packages/atxp-base/src/baseAppPaymentMaker.ts @@ -1,4 +1,4 @@ -import { USDC_CONTRACT_ADDRESS_BASE, type PaymentMaker, type EIP3009Authorization, PaymentNetworkError } from '@atxp/client'; +import { USDC_CONTRACT_ADDRESS_BASE, type PaymentMaker, PaymentNetworkError } from '@atxp/client'; import { Logger, Currency, ConsoleLogger } from '@atxp/common'; import { Address, encodeFunctionData, Hex, parseEther } from 'viem'; import { SpendPermission } from './types.js'; @@ -184,11 +184,6 @@ export class BaseAppPaymentMaker implements PaymentMaker { return txHash; } - async createPaymentAuthorization(_amount: BigNumber, _currency: Currency, _receiver: string, _memo: string): Promise { - // BaseApp doesn't support EIP-3009 payment authorizations - throw new PaymentNetworkError('EIP-3009 payment authorizations are not supported by BaseAppPaymentMaker'); - } - /** * Dynamically import the appropriate spend-permission module based on environment. * Uses browser or node version as appropriate since prepareSpendCallData exists in both. diff --git a/packages/atxp-base/src/mainWalletPaymentMaker.ts b/packages/atxp-base/src/mainWalletPaymentMaker.ts index ec7b6888..f8a9bd27 100644 --- a/packages/atxp-base/src/mainWalletPaymentMaker.ts +++ b/packages/atxp-base/src/mainWalletPaymentMaker.ts @@ -1,4 +1,4 @@ -import { PaymentMaker, EIP3009Authorization, PaymentNetworkError } from '@atxp/client'; +import { PaymentMaker, PaymentNetworkError } from '@atxp/client'; import { encodeFunctionData, toHex } from 'viem'; import { USDC_CONTRACT_ADDRESS_BASE, type Hex } from '@atxp/client'; import BigNumber from 'bignumber.js'; @@ -184,8 +184,4 @@ export class MainWalletPaymentMaker implements PaymentMaker { this.logger.info(`Transaction confirmed with ${confirmations} confirmations`); } - async createPaymentAuthorization(_amount: BigNumber, _currency: Currency, _receiver: string, _memo: string): Promise { - // MainWalletPaymentMaker doesn't support EIP-3009 payment authorizations - throw new PaymentNetworkError('EIP-3009 payment authorizations are not supported by MainWalletPaymentMaker'); - } } diff --git a/packages/atxp-client/src/atxpAccount.ts b/packages/atxp-client/src/atxpAccount.ts index ad678d52..236849f5 100644 --- a/packages/atxp-client/src/atxpAccount.ts +++ b/packages/atxp-client/src/atxpAccount.ts @@ -157,7 +157,7 @@ export class ATXPAccount implements Account { return new RemoteSigner( destination as `0x${string}`, this.origin, - toBasicAuth(this.token), + this.token, this.fetchFn ); } diff --git a/packages/atxp-client/src/atxpClient.events.test.ts b/packages/atxp-client/src/atxpClient.events.test.ts index 5b05864c..7e5ac3fe 100644 --- a/packages/atxp-client/src/atxpClient.events.test.ts +++ b/packages/atxp-client/src/atxpClient.events.test.ts @@ -25,18 +25,7 @@ describe('atxpClient events', () => { const onAuthorize = vi.fn(); const paymentMaker = { makePayment: vi.fn(), - generateJWT: vi.fn().mockResolvedValue('testJWT'), - createPaymentAuthorization: vi.fn().mockResolvedValue({ - from: '0x123', - to: '0x456', - value: '1000000', - validAfter: 0, - validBefore: Math.floor(Date.now() / 1000) + 3600, - nonce: '0x789', - v: 27, - r: '0xabc', - s: '0xdef' - }) + generateJWT: vi.fn().mockResolvedValue('testJWT') }; const account = { accountId: 'bdj', @@ -75,18 +64,7 @@ describe('atxpClient events', () => { const onAuthorizeFailure = vi.fn(); const paymentMaker = { makePayment: vi.fn(), - generateJWT: vi.fn().mockResolvedValue('testJWT'), - createPaymentAuthorization: vi.fn().mockResolvedValue({ - from: '0x123', - to: '0x456', - value: '1000000', - validAfter: 0, - validBefore: Math.floor(Date.now() / 1000) + 3600, - nonce: '0x789', - v: 27, - r: '0xabc', - s: '0xdef' - }) + generateJWT: vi.fn().mockResolvedValue('testJWT') }; const account = { accountId: 'bdj', @@ -129,18 +107,7 @@ describe('atxpClient events', () => { const onPayment = vi.fn(); const paymentMaker = { makePayment: vi.fn().mockResolvedValue('test-payment-result-id'), - generateJWT: vi.fn().mockResolvedValue('testJWT'), - createPaymentAuthorization: vi.fn().mockResolvedValue({ - from: '0x123', - to: '0x456', - value: '1000000', - validAfter: 0, - validBefore: Math.floor(Date.now() / 1000) + 3600, - nonce: '0x789', - v: 27, - r: '0xabc', - s: '0xdef' - }) + generateJWT: vi.fn().mockResolvedValue('testJWT') }; const account = { accountId: 'bdj', @@ -184,18 +151,7 @@ describe('atxpClient events', () => { const onPaymentFailure = vi.fn(); const paymentMaker = { makePayment: vi.fn().mockImplementation(() => Promise.reject(new Error('Payment failed'))), - generateJWT: vi.fn().mockResolvedValue('testJWT'), - createPaymentAuthorization: vi.fn().mockResolvedValue({ - from: '0x123', - to: '0x456', - value: '1000000', - validAfter: 0, - validBefore: Math.floor(Date.now() / 1000) + 3600, - nonce: '0x789', - v: 27, - r: '0xabc', - s: '0xdef' - }) + generateJWT: vi.fn().mockResolvedValue('testJWT') }; const account = { accountId: 'bdj', diff --git a/packages/atxp-client/src/atxpClient.test.ts b/packages/atxp-client/src/atxpClient.test.ts index 7357ff81..53038671 100644 --- a/packages/atxp-client/src/atxpClient.test.ts +++ b/packages/atxp-client/src/atxpClient.test.ts @@ -13,7 +13,7 @@ describe('atxpClient', () => { .postOnce('https://example.com/mcp', CTH.authRequiredResponse()) .post('https://example.com/mcp', CTH.mcpResponseHandler(CTH.mcpToolResponse(1, 'hello world'))); mockAuthorizationServer(f, DEFAULT_AUTHORIZATION_SERVER) - // Respond to /authorize call + // Respond to /authorize call .get(`begin:${DEFAULT_AUTHORIZATION_SERVER}/authorize`, (req) => { const state = new URL(req.args[0] as any).searchParams.get('state'); return { @@ -24,18 +24,7 @@ describe('atxpClient', () => { const paymentMaker = { makePayment: vi.fn(), - generateJWT: vi.fn().mockResolvedValue('testJWT'), - createPaymentAuthorization: vi.fn().mockResolvedValue({ - from: '0x123', - to: '0x456', - value: '1000000', - validAfter: 0, - validBefore: Math.floor(Date.now() / 1000) + 3600, - nonce: '0x789', - v: 27, - r: '0xabc', - s: '0xdef' - }) + generateJWT: vi.fn().mockResolvedValue('testJWT') }; const account = { accountId: 'bdj', @@ -71,18 +60,7 @@ describe('atxpClient', () => { const paymentMaker = { makePayment: vi.fn().mockResolvedValue('test-payment-result-id'), - generateJWT: vi.fn().mockResolvedValue('testJWT'), - createPaymentAuthorization: vi.fn().mockResolvedValue({ - from: '0x123', - to: '0x456', - value: '1000000', - validAfter: 0, - validBefore: Math.floor(Date.now() / 1000) + 3600, - nonce: '0x789', - v: 27, - r: '0xabc', - s: '0xdef' - }) + generateJWT: vi.fn().mockResolvedValue('testJWT') }; const account = { accountId: 'bdj', @@ -131,18 +109,7 @@ describe('atxpClient', () => { const paymentMaker = { makePayment: vi.fn().mockResolvedValue('test-payment-result-id'), - generateJWT: vi.fn().mockResolvedValue('testJWT'), - createPaymentAuthorization: vi.fn().mockResolvedValue({ - from: '0x123', - to: '0x456', - value: '1000000', - validAfter: 0, - validBefore: Math.floor(Date.now() / 1000) + 3600, - nonce: '0x789', - v: 27, - r: '0xabc', - s: '0xdef' - }) + generateJWT: vi.fn().mockResolvedValue('testJWT') }; const account = { accountId: 'bdj', @@ -150,7 +117,7 @@ describe('atxpClient', () => { }; const client = await atxpClient({ mcpServer: 'https://example.com/mcp', - account, + account, fetchFn: f.fetchHandler }); diff --git a/packages/atxp-client/src/atxpFetcher.oauth.test.ts b/packages/atxp-client/src/atxpFetcher.oauth.test.ts index 892d510c..f7bedfdd 100644 --- a/packages/atxp-client/src/atxpFetcher.oauth.test.ts +++ b/packages/atxp-client/src/atxpFetcher.oauth.test.ts @@ -10,18 +10,7 @@ import { PaymentMaker } from './types.js'; function mockPaymentMakers(solanaPaymentMaker?: PaymentMaker) { solanaPaymentMaker = solanaPaymentMaker ?? { makePayment: vi.fn().mockResolvedValue('testPaymentId'), - generateJWT: vi.fn().mockResolvedValue('testJWT'), - createPaymentAuthorization: vi.fn().mockResolvedValue({ - from: '0x123', - to: '0x456', - value: '1000000', - validAfter: 0, - validBefore: Math.floor(Date.now() / 1000) + 3600, - nonce: '0x789', - v: 27, - r: '0xabc', - s: '0xdef' - }) + generateJWT: vi.fn().mockResolvedValue('testJWT') }; return {'solana': solanaPaymentMaker }; } diff --git a/packages/atxp-client/src/atxpFetcher.payment.test.ts b/packages/atxp-client/src/atxpFetcher.payment.test.ts index e29cd8f6..6eaf0811 100644 --- a/packages/atxp-client/src/atxpFetcher.payment.test.ts +++ b/packages/atxp-client/src/atxpFetcher.payment.test.ts @@ -12,18 +12,7 @@ import BigNumber from 'bignumber.js'; function mockPaymentMakers(solanaPaymentMaker?: PaymentMaker) { solanaPaymentMaker = solanaPaymentMaker ?? { makePayment: vi.fn().mockResolvedValue('testPaymentId'), - generateJWT: vi.fn().mockResolvedValue('testJWT'), - createPaymentAuthorization: vi.fn().mockResolvedValue({ - from: '0x123', - to: '0x456', - value: '1000000', - validAfter: 0, - validBefore: Math.floor(Date.now() / 1000) + 3600, - nonce: '0x789', - v: 27, - r: '0xabc', - s: '0xdef' - }) + generateJWT: vi.fn().mockResolvedValue('testJWT') }; return {'solana': solanaPaymentMaker }; } diff --git a/packages/atxp-client/src/index.ts b/packages/atxp-client/src/index.ts index f3670613..f1bca99f 100644 --- a/packages/atxp-client/src/index.ts +++ b/packages/atxp-client/src/index.ts @@ -57,9 +57,7 @@ export { type ClientConfig, InsufficientFundsError, PaymentNetworkError, - type PaymentMaker, - type EIP3009Authorization, - type X402Message + type PaymentMaker } from './types.js'; // X402 support diff --git a/packages/atxp-client/src/remoteSigner.ts b/packages/atxp-client/src/remoteSigner.ts index 75410c54..b4f37d32 100644 --- a/packages/atxp-client/src/remoteSigner.ts +++ b/packages/atxp-client/src/remoteSigner.ts @@ -1,6 +1,12 @@ import { Hex, Address, LocalAccount, SignableMessage, TypedData, TransactionSerializable, Hash } from 'viem'; import { FetchLike } from '@atxp/common'; +function toBasicAuth(token: string): string { + // Basic auth is base64("username:password"), password is blank + const b64 = Buffer.from(`${token}:`).toString('base64'); + return `Basic ${b64}`; +} + /** * Creates a remote signer that delegates signing operations to the accounts-x402 API. * This implements the LocalAccount interface from viem to be compatible with x402-fetch. @@ -10,8 +16,8 @@ export class RemoteSigner implements LocalAccount { constructor( public readonly address: Address, - private accountsApiUrl: string, - private authorizationHeader: string, + private origin: string, + private token: string, private fetchFn: FetchLike = fetch as FetchLike ) {} @@ -23,12 +29,11 @@ export class RemoteSigner implements LocalAccount { const TTypedData extends TypedData | { [key: string]: unknown }, TPrimaryType extends string = string, >(typedData: TTypedData): Promise { - const response = await this.fetchFn(`${this.accountsApiUrl}/sign-typed-data`, { + const response = await this.fetchFn(`${this.origin}/sign-typed-data`, { method: 'POST', headers: { + 'Authorization': toBasicAuth(this.token), 'Content-Type': 'application/json', - // Add authorization header if we have a token - ...(this.authorizationHeader ? { 'Authorization': this.authorizationHeader } : {}) }, body: JSON.stringify({ typedData @@ -70,15 +75,15 @@ export class RemoteSigner implements LocalAccount { /** * Create a remote signer for use with x402-fetch * @param address The address of the account - * @param accountsApiUrl The URL of the accounts-x402 API - * @param authorizationHeader The authorization header to use for API calls + * @param origin The origin URL of the accounts-x402 API + * @param token The connection token for authentication * @param fetchFn Optional fetch function to use */ export function createRemoteSigner( address: Address, - accountsApiUrl: string, - authorizationHeader: string, + origin: string, + token: string, fetchFn?: FetchLike ): RemoteSigner { - return new RemoteSigner(address, accountsApiUrl, authorizationHeader, fetchFn); + return new RemoteSigner(address, origin, token, fetchFn); } \ No newline at end of file diff --git a/packages/atxp-client/src/solanaPaymentMaker.ts b/packages/atxp-client/src/solanaPaymentMaker.ts index d8594a26..5717e743 100644 --- a/packages/atxp-client/src/solanaPaymentMaker.ts +++ b/packages/atxp-client/src/solanaPaymentMaker.ts @@ -1,4 +1,4 @@ -import type { PaymentMaker, EIP3009Authorization } from './types.js'; +import type { PaymentMaker } from './types.js'; import { InsufficientFundsError, PaymentNetworkError } from './types.js'; import { Keypair, Connection, PublicKey, ComputeBudgetProgram, sendAndConfirmTransaction } from "@solana/web3.js"; import { createTransfer, ValidateTransferError as _ValidateTransferError } from "@solana/pay"; @@ -110,9 +110,4 @@ export class SolanaPaymentMaker implements PaymentMaker { throw new PaymentNetworkError(`Payment failed on Solana network: ${(error as Error).message}`, error as Error); } } - - async createPaymentAuthorization(_amount: BigNumber, _currency: Currency, _receiver: string, _memo: string): Promise { - // EIP-3009 is an Ethereum/EVM standard, not supported on Solana - throw new PaymentNetworkError('EIP-3009 payment authorizations are not supported on Solana'); - } } \ No newline at end of file diff --git a/packages/atxp-client/src/types.ts b/packages/atxp-client/src/types.ts index 2e6127de..eb54bc92 100644 --- a/packages/atxp-client/src/types.ts +++ b/packages/atxp-client/src/types.ts @@ -67,27 +67,6 @@ export class PaymentNetworkError extends Error { } } -// EIP-3009 TransferWithAuthorization message -export type EIP3009Authorization = { - signature: string; - authorization: { - from: string; - to: string; - value: string; - validAfter: string; - validBefore: string; - nonce: string; - }; -} - -// X402 protocol message wrapper -export type X402Message = { - x402Version: number; - scheme: string; - network: string; - payload: EIP3009Authorization; -} - export interface PaymentMaker { makePayment: (amount: BigNumber, currency: Currency, receiver: string, memo: string) => Promise; generateJWT: (params: {paymentRequestId: string, codeChallenge: string}) => Promise; From 53c7627e8a35baabef2a68f5844512b885c3deca Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 17:23:54 -0700 Subject: [PATCH 33/61] lint/typecheck --- packages/atxp-base/src/baseAppPaymentMaker.ts | 2 +- .../atxp-base/src/mainWalletPaymentMaker.ts | 2 +- packages/atxp-client/src/atxpAccount.ts | 2 +- packages/atxp-client/src/basePaymentMaker.ts | 1 - packages/atxp-client/src/remoteSigner.ts | 19 ++++++++++--------- packages/atxp-client/src/x402Wrapper.ts | 7 +++---- tsconfig.json | 4 ++-- 7 files changed, 18 insertions(+), 19 deletions(-) diff --git a/packages/atxp-base/src/baseAppPaymentMaker.ts b/packages/atxp-base/src/baseAppPaymentMaker.ts index b8693562..6a87a4c0 100644 --- a/packages/atxp-base/src/baseAppPaymentMaker.ts +++ b/packages/atxp-base/src/baseAppPaymentMaker.ts @@ -1,4 +1,4 @@ -import { USDC_CONTRACT_ADDRESS_BASE, type PaymentMaker, PaymentNetworkError } from '@atxp/client'; +import { USDC_CONTRACT_ADDRESS_BASE, type PaymentMaker } from '@atxp/client'; import { Logger, Currency, ConsoleLogger } from '@atxp/common'; import { Address, encodeFunctionData, Hex, parseEther } from 'viem'; import { SpendPermission } from './types.js'; diff --git a/packages/atxp-base/src/mainWalletPaymentMaker.ts b/packages/atxp-base/src/mainWalletPaymentMaker.ts index f8a9bd27..7b65d7cd 100644 --- a/packages/atxp-base/src/mainWalletPaymentMaker.ts +++ b/packages/atxp-base/src/mainWalletPaymentMaker.ts @@ -1,4 +1,4 @@ -import { PaymentMaker, PaymentNetworkError } from '@atxp/client'; +import { PaymentMaker } from '@atxp/client'; import { encodeFunctionData, toHex } from 'viem'; import { USDC_CONTRACT_ADDRESS_BASE, type Hex } from '@atxp/client'; import BigNumber from 'bignumber.js'; diff --git a/packages/atxp-client/src/atxpAccount.ts b/packages/atxp-client/src/atxpAccount.ts index 236849f5..cd67b507 100644 --- a/packages/atxp-client/src/atxpAccount.ts +++ b/packages/atxp-client/src/atxpAccount.ts @@ -113,7 +113,7 @@ export class ATXPAccount implements Account { * @param x402Challenge The X402 challenge object from the 402 response * @returns The X402 payment header to send in the retry request */ - async createX402Payment(x402Challenge: { x402Version: number; accepts: any[] }): Promise { + async createX402Payment(x402Challenge: { x402Version: number; accepts: unknown[] }): Promise { const response = await this.fetchFn(`${this.origin}/create-x402-payment`, { method: 'POST', headers: { diff --git a/packages/atxp-client/src/basePaymentMaker.ts b/packages/atxp-client/src/basePaymentMaker.ts index a59f799c..5734c14b 100644 --- a/packages/atxp-client/src/basePaymentMaker.ts +++ b/packages/atxp-client/src/basePaymentMaker.ts @@ -9,7 +9,6 @@ import { encodeFunctionData, WalletClient, PublicActions, - getAddress, } from "viem"; import { base } from "viem/chains"; import { BigNumber } from "bignumber.js"; diff --git a/packages/atxp-client/src/remoteSigner.ts b/packages/atxp-client/src/remoteSigner.ts index b4f37d32..69133b58 100644 --- a/packages/atxp-client/src/remoteSigner.ts +++ b/packages/atxp-client/src/remoteSigner.ts @@ -1,4 +1,4 @@ -import { Hex, Address, LocalAccount, SignableMessage, TypedData, TransactionSerializable, Hash } from 'viem'; +import { Hex, Address, LocalAccount, SignableMessage, TypedData, TransactionSerializable } from 'viem'; import { FetchLike } from '@atxp/common'; function toBasicAuth(token: string): string { @@ -26,8 +26,7 @@ export class RemoteSigner implements LocalAccount { * This is what x402 library will call for EIP-3009 authorization */ async signTypedData< - const TTypedData extends TypedData | { [key: string]: unknown }, - TPrimaryType extends string = string, + const TTypedData extends TypedData | { [key: string]: unknown } >(typedData: TTypedData): Promise { const response = await this.fetchFn(`${this.origin}/sign-typed-data`, { method: 'POST', @@ -52,24 +51,26 @@ export class RemoteSigner implements LocalAccount { /** * Sign a message - required by LocalAccount interface but not used for X402 */ - async signMessage({ message }: { message: SignableMessage }): Promise { + async signMessage(_: { message: SignableMessage }): Promise { throw new Error('Message signing not implemented for remote signer'); } /** * Sign a transaction - required by LocalAccount interface but not used for X402 */ - async signTransaction(transaction: TransactionSerializable, args?: any): Promise { + async signTransaction(_transaction: TransactionSerializable, _args?: unknown): Promise { throw new Error('Transaction signing not implemented for remote signer'); } /** * Get public key - required by LocalAccount interface */ - async publicKey(): Promise { - // Return a dummy public key since we don't have access to it - return '0x0000000000000000000000000000000000000000000000000000000000000000' as Hex; - } + readonly publicKey = '0x0000000000000000000000000000000000000000000000000000000000000000' as Hex; + + /** + * Source - required by LocalAccount interface (set to 'custom') + */ + readonly source = 'custom' as const; } /** diff --git a/packages/atxp-client/src/x402Wrapper.ts b/packages/atxp-client/src/x402Wrapper.ts index 7e8b6129..2889d557 100644 --- a/packages/atxp-client/src/x402Wrapper.ts +++ b/packages/atxp-client/src/x402Wrapper.ts @@ -1,6 +1,5 @@ import { ClientConfig, ProspectivePayment } from './types.js'; -import { BaseAccount } from './baseAccount.js'; -import { FetchLike, Logger, Network } from '@atxp/common'; +import { FetchLike, Network } from '@atxp/common'; import { BigNumber } from 'bignumber.js'; import { createPaymentHeader, selectPaymentRequirements } from 'x402/client'; import { LocalAccount } from 'viem'; @@ -17,7 +16,7 @@ export function wrapWithX402(config: ClientConfig): FetchLike { const log = logger ?? console; // Check if account has getSigner method - const accountWithSigner = account as any; + const accountWithSigner = account as { getSigner?: () => Promise }; if (!accountWithSigner.getSigner) { throw new Error('Account does not support getSigner, X402 payments will not work'); } @@ -102,7 +101,7 @@ export function wrapWithX402(config: ClientConfig): FetchLike { // Get the signer from the account log.debug('Getting signer from account'); - const signer: LocalAccount = await accountWithSigner.getSigner(); + const signer: LocalAccount = await accountWithSigner.getSigner!(); // Create the X402 payment header using the x402 library log.debug('Creating X402 payment header with signer'); diff --git a/tsconfig.json b/tsconfig.json index 658e5e0a..767d0a38 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -13,6 +13,6 @@ "declaration": false, "allowSyntheticDefaultImports": true }, - "include": ["src/dev/**/*.ts"], - "exclude": ["node_modules", "dist", "examples", "packages"] + "include": [], + "exclude": ["node_modules", "dist"] } From ca44e23e19e05a918b8a7093375fdba22bdb04e6 Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 17:26:27 -0700 Subject: [PATCH 34/61] Test fixes for error message change --- packages/atxp-client/src/defaultPaymentFailureHandler.test.ts | 2 +- packages/atxp-client/src/errorClasses.test.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/atxp-client/src/defaultPaymentFailureHandler.test.ts b/packages/atxp-client/src/defaultPaymentFailureHandler.test.ts index baf4896d..143a3467 100644 --- a/packages/atxp-client/src/defaultPaymentFailureHandler.test.ts +++ b/packages/atxp-client/src/defaultPaymentFailureHandler.test.ts @@ -265,7 +265,7 @@ describe('Default Payment Failure Handler', () => { // Verify messages follow structured format expect(mockLogger.info).toHaveBeenCalledWith( - 'PAYMENT FAILED: Network error on base: Payment failed due to network error: Connection timeout. Please check your network connection and try again.' + 'PAYMENT FAILED: Network error on base: Payment failed due to network error: Connection timeout' ); }); }); diff --git a/packages/atxp-client/src/errorClasses.test.ts b/packages/atxp-client/src/errorClasses.test.ts index 8e34a3d2..ec0e1ba8 100644 --- a/packages/atxp-client/src/errorClasses.test.ts +++ b/packages/atxp-client/src/errorClasses.test.ts @@ -76,7 +76,7 @@ describe('PaymentNetworkError', () => { expect(error.name).toBe('PaymentNetworkError'); expect(error.message).toBe( - 'Payment failed due to network error: Network failed. Please check your network connection and try again.' + 'Payment failed due to network error: Network failed' ); expect(error.originalError).toBe(originalError); }); @@ -86,7 +86,7 @@ describe('PaymentNetworkError', () => { expect(error.name).toBe('PaymentNetworkError'); expect(error.message).toBe( - 'Payment failed due to network error: Transaction reverted. Please check your network connection and try again.' + 'Payment failed due to network error: Transaction reverted' ); expect(error.originalError).toBeUndefined(); }); From 76f994cc8a7b538fe922ae53c61760f503b78061 Mon Sep 17 00:00:00 2001 From: bdj Date: Thu, 18 Sep 2025 17:38:24 -0700 Subject: [PATCH 35/61] X402 package --- examples/x402-server/README.md | 4 +- examples/x402-server/package-lock.json | 25 ++++++ examples/x402-server/package.json | 1 + examples/x402-server/src/test-client.ts | 3 +- package-lock.json | 86 ++++++++++++------- package.json | 3 +- packages/atxp-client/package.json | 3 +- packages/atxp-client/src/index.ts | 5 -- packages/atxp-x402/package.json | 50 +++++++++++ packages/atxp-x402/rollup.config.js | 9 ++ packages/atxp-x402/src/index.ts | 1 + .../src/x402Wrapper.ts | 2 +- packages/atxp-x402/tsconfig.json | 26 ++++++ rollup.config.js | 4 +- 14 files changed, 180 insertions(+), 42 deletions(-) create mode 100644 packages/atxp-x402/package.json create mode 100644 packages/atxp-x402/rollup.config.js create mode 100644 packages/atxp-x402/src/index.ts rename packages/{atxp-client => atxp-x402}/src/x402Wrapper.ts (99%) create mode 100644 packages/atxp-x402/tsconfig.json diff --git a/examples/x402-server/README.md b/examples/x402-server/README.md index b4e8d4e2..765f0f13 100644 --- a/examples/x402-server/README.md +++ b/examples/x402-server/README.md @@ -79,7 +79,9 @@ app.use(paymentMiddleware( The ATXP SDK handles X402 automatically: ```typescript -const x402Fetch = wrapWithX402(fetch, account); +import { wrapWithX402 } from '@atxp/x402'; + +const x402Fetch = wrapWithX402({ account, fetchFn: fetch }); const response = await x402Fetch('http://localhost:3001/api/resource'); ``` diff --git a/examples/x402-server/package-lock.json b/examples/x402-server/package-lock.json index b90cde27..1071dba0 100644 --- a/examples/x402-server/package-lock.json +++ b/examples/x402-server/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@atxp/client": "file:../../packages/atxp-client", "@atxp/common": "file:../../packages/atxp-common", + "@atxp/x402": "file:../../packages/atxp-x402", "@coinbase/x402": "^0.3.8", "bignumber.js": "^9.1.2", "cors": "^2.8.5", @@ -85,6 +86,26 @@ "vitest": "^3.0.9" } }, + "../../packages/atxp-x402": { + "name": "@atxp/x402", + "version": "0.4.0", + "license": "MIT", + "dependencies": { + "@atxp/client": "0.4.0", + "@atxp/common": "0.4.0", + "bignumber.js": "^9.1.2", + "viem": "^2.21.54", + "x402": "^0.6.1" + }, + "devDependencies": { + "@types/node": "^22.13.0", + "@typescript-eslint/eslint-plugin": "^8.38.0", + "@typescript-eslint/parser": "^8.38.0", + "eslint": "^9.32.0", + "typescript": "^5.7.3", + "vitest": "^3.0.9" + } + }, "node_modules/@adraffy/ens-normalize": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.11.0.tgz", @@ -99,6 +120,10 @@ "resolved": "../../packages/atxp-common", "link": true }, + "node_modules/@atxp/x402": { + "resolved": "../../packages/atxp-x402", + "link": true + }, "node_modules/@babel/runtime": { "version": "7.28.4", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", diff --git a/examples/x402-server/package.json b/examples/x402-server/package.json index ef536f9d..87b4fc0c 100644 --- a/examples/x402-server/package.json +++ b/examples/x402-server/package.json @@ -11,6 +11,7 @@ "dependencies": { "@atxp/client": "file:../../packages/atxp-client", "@atxp/common": "file:../../packages/atxp-common", + "@atxp/x402": "file:../../packages/atxp-x402", "@coinbase/x402": "^0.3.8", "bignumber.js": "^9.1.2", "cors": "^2.8.5", diff --git a/examples/x402-server/src/test-client.ts b/examples/x402-server/src/test-client.ts index a8612940..147044fd 100644 --- a/examples/x402-server/src/test-client.ts +++ b/examples/x402-server/src/test-client.ts @@ -1,4 +1,5 @@ -import { wrapWithX402, BaseAccount } from '@atxp/client'; +import { BaseAccount } from '@atxp/client'; +import { wrapWithX402 } from '@atxp/x402'; import { ConsoleLogger, LogLevel } from '@atxp/common'; import dotenv from 'dotenv'; import path from 'path'; diff --git a/package-lock.json b/package-lock.json index 296ffea2..e7564fff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,11 +16,11 @@ "packages/atxp-client", "packages/atxp-base", "packages/atxp-express", - "packages/atxp-cloudflare" + "packages/atxp-cloudflare", + "packages/atxp-x402" ], "dependencies": { - "dotenv": "^16.5.0", - "x402-fetch": "^0.6.0" + "dotenv": "^16.5.0" }, "devDependencies": { "@rollup/plugin-commonjs": "^28.0.6", @@ -181,6 +181,10 @@ "resolved": "packages/atxp-sqlite", "link": true }, + "node_modules/@atxp/x402": { + "resolved": "packages/atxp-x402", + "link": true + }, "node_modules/@babel/code-frame": { "version": "7.27.1", "license": "MIT", @@ -1848,7 +1852,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.7.0", + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", "dev": true, "license": "MIT", "dependencies": { @@ -1886,7 +1892,9 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.3.0", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", + "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1894,7 +1902,9 @@ } }, "node_modules/@eslint/core": { - "version": "0.15.1", + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", + "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1996,7 +2006,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.32.0", + "version": "9.35.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.35.0.tgz", + "integrity": "sha512-30iXE9whjlILfWobBkNerJo+TXYsgVM5ERQwMcMKCHckHflCmf7wXDAHlARoWnh0s1U72WqlbeyE7iAcCzuCPw==", "dev": true, "license": "MIT", "engines": { @@ -2015,11 +2027,13 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.3.4", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", + "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.15.1", + "@eslint/core": "^0.15.2", "levn": "^0.4.1" }, "engines": { @@ -8592,6 +8606,8 @@ }, "node_modules/@types/json-schema": { "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true, "license": "MIT" }, @@ -8623,7 +8639,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.15.14", + "version": "22.18.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.6.tgz", + "integrity": "sha512-r8uszLPpeIWbNKtvWRt/DbVi5zbqZyj1PTmhRMqBMvDnaz1QpmSKujUtJLrqGZeoM8v72MfYggDceY4K1itzWQ==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -12302,18 +12320,20 @@ } }, "node_modules/eslint": { - "version": "9.32.0", + "version": "9.35.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.35.0.tgz", + "integrity": "sha512-QePbBFMJFjgmlE+cXAlbHZbHpdFVS2E/6vzCy7aKlebddvl1vadiC4JFV5u/wqTkNUwEV8WrQi257jf5f06hrg==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.0", - "@eslint/config-helpers": "^0.3.0", - "@eslint/core": "^0.15.0", + "@eslint/config-helpers": "^0.3.1", + "@eslint/core": "^0.15.2", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.32.0", - "@eslint/plugin-kit": "^0.3.4", + "@eslint/js": "9.35.0", + "@eslint/plugin-kit": "^0.3.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", @@ -20724,17 +20744,6 @@ "zod": "^3.24.2" } }, - "node_modules/x402-fetch": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/x402-fetch/-/x402-fetch-0.6.0.tgz", - "integrity": "sha512-c7ZQQOjgBWyX9xbmRCliUguVeG0RCofTlcnPKBrAgNYxEo8p/yuQr2PRvyN9tdQdXVTlGgIsII7GO1wLHJpLhA==", - "license": "Apache-2.0", - "dependencies": { - "viem": "^2.21.26", - "x402": "^0.6.0", - "zod": "^3.24.2" - } - }, "node_modules/xcode": { "version": "3.0.1", "license": "Apache-2.0", @@ -20940,8 +20949,7 @@ "@atxp/common": "0.4.0", "@modelcontextprotocol/sdk": "^1.15.0", "bignumber.js": "^9.3.0", - "oauth4webapi": "^3.5.0", - "x402": "^0.6.1" + "oauth4webapi": "^3.5.0" }, "devDependencies": { "@solana/pay": "^0.2.5", @@ -21285,6 +21293,26 @@ "typescript": "^5.7.3", "vitest": "^3.0.9" } + }, + "packages/atxp-x402": { + "name": "@atxp/x402", + "version": "0.4.0", + "license": "MIT", + "dependencies": { + "@atxp/client": "0.4.0", + "@atxp/common": "0.4.0", + "bignumber.js": "^9.1.2", + "viem": "^2.21.54", + "x402": "^0.6.1" + }, + "devDependencies": { + "@types/node": "^22.13.0", + "@typescript-eslint/eslint-plugin": "^8.38.0", + "@typescript-eslint/parser": "^8.38.0", + "eslint": "^9.32.0", + "typescript": "^5.7.3", + "vitest": "^3.0.9" + } } } } diff --git a/package.json b/package.json index 848f6808..05d9e7f2 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,8 @@ "packages/atxp-client", "packages/atxp-base", "packages/atxp-express", - "packages/atxp-cloudflare" + "packages/atxp-cloudflare", + "packages/atxp-x402" ], "repository": { "type": "git", diff --git a/packages/atxp-client/package.json b/packages/atxp-client/package.json index c39a8bb4..2a7a18f4 100644 --- a/packages/atxp-client/package.json +++ b/packages/atxp-client/package.json @@ -36,8 +36,7 @@ "@atxp/common": "0.4.0", "@modelcontextprotocol/sdk": "^1.15.0", "bignumber.js": "^9.3.0", - "oauth4webapi": "^3.5.0", - "x402": "^0.6.1" + "oauth4webapi": "^3.5.0" }, "peerDependencies": { "@solana/pay": "^0.2.5", diff --git a/packages/atxp-client/src/index.ts b/packages/atxp-client/src/index.ts index f1bca99f..c774edfb 100644 --- a/packages/atxp-client/src/index.ts +++ b/packages/atxp-client/src/index.ts @@ -60,11 +60,6 @@ export { type PaymentMaker } from './types.js'; -// X402 support -export { - wrapWithX402 -} from './x402Wrapper.js'; - export { RemoteSigner, createRemoteSigner diff --git a/packages/atxp-x402/package.json b/packages/atxp-x402/package.json new file mode 100644 index 00000000..2f3abcbf --- /dev/null +++ b/packages/atxp-x402/package.json @@ -0,0 +1,50 @@ +{ + "name": "@atxp/x402", + "version": "0.4.0", + "description": "ATXP X402 - X402 protocol integration for ATXP SDK", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/atxp-dev/sdk.git", + "directory": "packages/atxp-x402" + }, + "type": "module", + "sideEffects": false, + "main": "./dist/index.cjs", + "module": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "require": "./dist/index.cjs" + } + }, + "files": [ + "dist" + ], + "scripts": { + "build": "rollup -c", + "typecheck": "tsc --noEmit", + "lint": "eslint . --ext .ts", + "lint:fix": "eslint . --ext .ts --fix", + "test": "vitest run", + "prepack": "npm run build && npm run typecheck", + "pack:dry": "npm pack --dry-run" + }, + "dependencies": { + "@atxp/client": "0.4.0", + "@atxp/common": "0.4.0", + "bignumber.js": "^9.1.2", + "viem": "^2.21.54", + "x402": "^0.6.1" + }, + "devDependencies": { + "@types/node": "^22.13.0", + "@typescript-eslint/eslint-plugin": "^8.38.0", + "@typescript-eslint/parser": "^8.38.0", + "eslint": "^9.32.0", + "typescript": "^5.7.3", + "vitest": "^3.0.9" + } +} \ No newline at end of file diff --git a/packages/atxp-x402/rollup.config.js b/packages/atxp-x402/rollup.config.js new file mode 100644 index 00000000..7ff5596a --- /dev/null +++ b/packages/atxp-x402/rollup.config.js @@ -0,0 +1,9 @@ +import { createConfig } from '../../rollup.config.js'; + +export default createConfig('atxp-x402', { + platform: 'neutral', // Browser/React Native + external: [ + // x402 and its dependencies + 'x402' + ] +}); \ No newline at end of file diff --git a/packages/atxp-x402/src/index.ts b/packages/atxp-x402/src/index.ts new file mode 100644 index 00000000..d48811f4 --- /dev/null +++ b/packages/atxp-x402/src/index.ts @@ -0,0 +1 @@ +export { wrapWithX402 } from './x402Wrapper.js'; \ No newline at end of file diff --git a/packages/atxp-client/src/x402Wrapper.ts b/packages/atxp-x402/src/x402Wrapper.ts similarity index 99% rename from packages/atxp-client/src/x402Wrapper.ts rename to packages/atxp-x402/src/x402Wrapper.ts index 2889d557..6d860c91 100644 --- a/packages/atxp-client/src/x402Wrapper.ts +++ b/packages/atxp-x402/src/x402Wrapper.ts @@ -1,4 +1,4 @@ -import { ClientConfig, ProspectivePayment } from './types.js'; +import { ClientConfig, ProspectivePayment } from '@atxp/client'; import { FetchLike, Network } from '@atxp/common'; import { BigNumber } from 'bignumber.js'; import { createPaymentHeader, selectPaymentRequirements } from 'x402/client'; diff --git a/packages/atxp-x402/tsconfig.json b/packages/atxp-x402/tsconfig.json new file mode 100644 index 00000000..1ee12542 --- /dev/null +++ b/packages/atxp-x402/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "ESNext", + "moduleResolution": "bundler", + "lib": ["ES2020", "DOM"], + "outDir": "./dist", + "rootDir": "./src", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "allowSyntheticDefaultImports": true, + "composite": true + }, + "include": ["src/**/*.ts"], + "exclude": ["node_modules", "dist", "**/*.test.ts"], + "references": [ + { "path": "../atxp-client" }, + { "path": "../atxp-common" } + ] +} \ No newline at end of file diff --git a/rollup.config.js b/rollup.config.js index 325453d0..3a09edf8 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -17,8 +17,8 @@ const createConfig = (packageName, options = {}) => { const isExternal = (id) => { // Check exact matches first const exactMatches = [ - '@atxp/common', '@atxp/client', '@atxp/server', '@atxp/redis', - '@atxp/sqlite', '@atxp/base', '@modelcontextprotocol/sdk', + '@atxp/common', '@atxp/client', '@atxp/server', '@atxp/redis', + '@atxp/sqlite', '@atxp/base', '@atxp/x402', '@modelcontextprotocol/sdk', '@modelcontextprotocol/sdk/types.js', '@modelcontextprotocol/sdk/client', 'bignumber.js', 'oauth4webapi', 'jose', 'tweetnacl', 'tweetnacl-util', ...platformExternals[platform], From 1ad7ef6ced99a9d70545491ac125a9902ef4d339 Mon Sep 17 00:00:00 2001 From: bdj Date: Fri, 19 Sep 2025 08:29:58 -0700 Subject: [PATCH 36/61] WIP --- packages/atxp-client/src/atxpAccount.ts | 27 -- packages/atxp-client/src/index.ts | 3 +- packages/atxp-client/src/remoteSigner.ts | 15 - packages/atxp-x402/src/x402Wrapper.test.ts | 349 +++++++++++++++++++++ packages/atxp-x402/src/x402Wrapper.ts | 37 ++- 5 files changed, 375 insertions(+), 56 deletions(-) create mode 100644 packages/atxp-x402/src/x402Wrapper.test.ts diff --git a/packages/atxp-client/src/atxpAccount.ts b/packages/atxp-client/src/atxpAccount.ts index cd67b507..86cda909 100644 --- a/packages/atxp-client/src/atxpAccount.ts +++ b/packages/atxp-client/src/atxpAccount.ts @@ -108,33 +108,6 @@ export class ATXPAccount implements Account { }; } - /** - * Create an X402 payment header by calling the accounts-x402 server - * @param x402Challenge The X402 challenge object from the 402 response - * @returns The X402 payment header to send in the retry request - */ - async createX402Payment(x402Challenge: { x402Version: number; accepts: unknown[] }): Promise { - const response = await this.fetchFn(`${this.origin}/create-x402-payment`, { - method: 'POST', - headers: { - 'Authorization': toBasicAuth(this.token), - 'Content-Type': 'application/json', - }, - body: JSON.stringify(x402Challenge), - }); - - if (!response.ok) { - const text = await response.text(); - throw new Error(`ATXPAccount: Failed to create X402 payment: ${response.status} ${response.statusText} ${text}`); - } - - const result = await response.json() as { paymentHeader?: string }; - if (!result?.paymentHeader) { - throw new Error('ATXPAccount: Server did not return payment header'); - } - - return result.paymentHeader; - } /** * Get a signer that can be used with the x402 library diff --git a/packages/atxp-client/src/index.ts b/packages/atxp-client/src/index.ts index c774edfb..607d7f78 100644 --- a/packages/atxp-client/src/index.ts +++ b/packages/atxp-client/src/index.ts @@ -61,6 +61,5 @@ export { } from './types.js'; export { - RemoteSigner, - createRemoteSigner + RemoteSigner } from './remoteSigner.js'; diff --git a/packages/atxp-client/src/remoteSigner.ts b/packages/atxp-client/src/remoteSigner.ts index 69133b58..5d654e79 100644 --- a/packages/atxp-client/src/remoteSigner.ts +++ b/packages/atxp-client/src/remoteSigner.ts @@ -73,18 +73,3 @@ export class RemoteSigner implements LocalAccount { readonly source = 'custom' as const; } -/** - * Create a remote signer for use with x402-fetch - * @param address The address of the account - * @param origin The origin URL of the accounts-x402 API - * @param token The connection token for authentication - * @param fetchFn Optional fetch function to use - */ -export function createRemoteSigner( - address: Address, - origin: string, - token: string, - fetchFn?: FetchLike -): RemoteSigner { - return new RemoteSigner(address, origin, token, fetchFn); -} \ No newline at end of file diff --git a/packages/atxp-x402/src/x402Wrapper.test.ts b/packages/atxp-x402/src/x402Wrapper.test.ts new file mode 100644 index 00000000..d0b27cde --- /dev/null +++ b/packages/atxp-x402/src/x402Wrapper.test.ts @@ -0,0 +1,349 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { wrapWithX402 } from './x402Wrapper.js'; +import { BaseAccount } from '@atxp/client'; +import { ConsoleLogger, LogLevel } from '@atxp/common'; + +describe('wrapWithX402', () => { + let mockAccount: BaseAccount; + let mockFetch: ReturnType; + let mockLogger: ConsoleLogger; + let mockApprovePayment: ReturnType; + let mockOnPayment: ReturnType; + let mockOnPaymentFailure: ReturnType; + + beforeEach(() => { + // Mock BaseAccount + mockAccount = { + accountId: '0x1234567890123456789012345678901234567890', + network: 'base', + getSigner: vi.fn().mockResolvedValue({ + address: '0x1234567890123456789012345678901234567890', + signTypedData: vi.fn().mockResolvedValue('0xmockedsignature'), + }), + } as unknown as BaseAccount; + + // Mock fetch + mockFetch = vi.fn(); + + // Mock logger + mockLogger = new ConsoleLogger({ prefix: '[Test]', level: LogLevel.DEBUG }); + + // Mock callbacks + mockApprovePayment = vi.fn().mockResolvedValue(true); + mockOnPayment = vi.fn(); + mockOnPaymentFailure = vi.fn(); + }); + + it('should pass through normal requests without modification', async () => { + const mockResponse = new Response('Success', { status: 200 }); + mockFetch.mockResolvedValue(mockResponse); + + const wrappedFetch = wrapWithX402({ + account: mockAccount, + fetchFn: mockFetch, + logger: mockLogger, + }); + + const result = await wrappedFetch('https://example.com/api'); + + expect(result).toBe(mockResponse); + expect(mockFetch).toHaveBeenCalledWith('https://example.com/api', undefined); + expect(mockAccount.getSigner).not.toHaveBeenCalled(); + }); + + it('should handle 402 responses and retry with payment', async () => { + // First response: 402 with X402 challenge + const x402Challenge = { + version: 0, + created_at: Date.now(), + expires_at: Date.now() + 60000, + request_nonce: 'test-nonce', + chain_id: 8453, + currency: 'USDC', + amount: '1000000', + recipient: '0xrecipient', + memo: 'Test payment', + receipt_url: 'https://example.com/receipt', + accepts: [ + { + type: 'transferWithAuthorization', + required: ['signature', 'authorization'], + }, + ], + }; + + const first402Response = new Response('Payment Required', { + status: 402, + headers: { + 'X-402': btoa(JSON.stringify(x402Challenge)), + }, + }); + + // Second response: Success after payment + const successResponse = new Response('Success', { + status: 200, + headers: { + 'X-Payment-Response': btoa(JSON.stringify({ receipt: 'test-receipt' })), + }, + }); + + mockFetch + .mockResolvedValueOnce(first402Response) + .mockResolvedValueOnce(successResponse); + + const wrappedFetch = wrapWithX402({ + account: mockAccount, + fetchFn: mockFetch, + logger: mockLogger, + approvePayment: mockApprovePayment, + onPayment: mockOnPayment, + onPaymentFailure: mockOnPaymentFailure, + }); + + const result = await wrappedFetch('https://example.com/api', { + method: 'POST', + body: 'test-body', + }); + + // Should have gotten the success response + expect(result.status).toBe(200); + expect(await result.text()).toBe('Success'); + + // Should have called getSigner + expect(mockAccount.getSigner).toHaveBeenCalled(); + + // Should have called approve payment + expect(mockApprovePayment).toHaveBeenCalledWith( + expect.objectContaining({ + amount: '1000000', + currency: 'USDC', + recipient: '0xrecipient', + }) + ); + + // Should have called onPayment callback + expect(mockOnPayment).toHaveBeenCalledWith( + expect.objectContaining({ + payment: expect.objectContaining({ + amount: '1000000', + currency: 'USDC', + }), + }) + ); + + // Should have made two fetch calls + expect(mockFetch).toHaveBeenCalledTimes(2); + + // Second call should include X-Payment header + expect(mockFetch).toHaveBeenNthCalledWith(2, 'https://example.com/api', { + method: 'POST', + body: 'test-body', + headers: expect.objectContaining({ + 'X-Payment': expect.any(String), + }), + }); + }); + + it('should handle payment approval rejection', async () => { + const x402Challenge = { + version: 0, + created_at: Date.now(), + expires_at: Date.now() + 60000, + request_nonce: 'test-nonce', + chain_id: 8453, + currency: 'USDC', + amount: '1000000', + recipient: '0xrecipient', + accepts: [ + { + type: 'transferWithAuthorization', + required: ['signature', 'authorization'], + }, + ], + }; + + const response402 = new Response('Payment Required', { + status: 402, + headers: { + 'X-402': btoa(JSON.stringify(x402Challenge)), + }, + }); + + mockFetch.mockResolvedValue(response402); + mockApprovePayment.mockResolvedValue(false); + + const wrappedFetch = wrapWithX402({ + account: mockAccount, + fetchFn: mockFetch, + logger: mockLogger, + approvePayment: mockApprovePayment, + onPayment: mockOnPayment, + onPaymentFailure: mockOnPaymentFailure, + }); + + const result = await wrappedFetch('https://example.com/api'); + + // Should return the original 402 response + expect(result.status).toBe(402); + + // Should have called approve payment + expect(mockApprovePayment).toHaveBeenCalled(); + + // Should NOT have called onPayment + expect(mockOnPayment).not.toHaveBeenCalled(); + + // Should have called onPaymentFailure + expect(mockOnPaymentFailure).toHaveBeenCalledWith( + expect.objectContaining({ + error: expect.objectContaining({ + message: expect.stringContaining('User rejected payment'), + }), + }) + ); + + // Should only have made one fetch call + expect(mockFetch).toHaveBeenCalledTimes(1); + }); + + it('should handle missing X-402 header on 402 response', async () => { + const response402 = new Response('Payment Required', { + status: 402, + // No X-402 header + }); + + mockFetch.mockResolvedValue(response402); + + const wrappedFetch = wrapWithX402({ + account: mockAccount, + fetchFn: mockFetch, + logger: mockLogger, + }); + + const result = await wrappedFetch('https://example.com/api'); + + // Should return the original 402 response + expect(result.status).toBe(402); + + // Should not have tried to get signer + expect(mockAccount.getSigner).not.toHaveBeenCalled(); + + // Should only have made one fetch call + expect(mockFetch).toHaveBeenCalledTimes(1); + }); + + it('should handle x402 library errors', async () => { + const x402Challenge = { + version: 0, + created_at: Date.now(), + expires_at: Date.now() + 60000, + request_nonce: 'test-nonce', + chain_id: 8453, + currency: 'USDC', + amount: '1000000', + recipient: '0xrecipient', + accepts: [ + { + type: 'transferWithAuthorization', + required: ['signature', 'authorization'], + }, + ], + }; + + const response402 = new Response('Payment Required', { + status: 402, + headers: { + 'X-402': btoa(JSON.stringify(x402Challenge)), + }, + }); + + mockFetch.mockResolvedValue(response402); + + // Make getSigner throw an error + mockAccount.getSigner = vi.fn().mockRejectedValue(new Error('Signer error')); + + const wrappedFetch = wrapWithX402({ + account: mockAccount, + fetchFn: mockFetch, + logger: mockLogger, + approvePayment: mockApprovePayment, + onPayment: mockOnPayment, + onPaymentFailure: mockOnPaymentFailure, + }); + + const result = await wrappedFetch('https://example.com/api'); + + // Should return the original 402 response + expect(result.status).toBe(402); + + // Should have called onPaymentFailure + expect(mockOnPaymentFailure).toHaveBeenCalledWith( + expect.objectContaining({ + error: expect.objectContaining({ + message: expect.stringContaining('Signer error'), + }), + }) + ); + + // Should only have made one fetch call + expect(mockFetch).toHaveBeenCalledTimes(1); + }); + + it('should handle wrong network account', async () => { + // Account on wrong network + const wrongNetworkAccount = { + accountId: '0x1234567890123456789012345678901234567890', + network: 'solana', // Not base + getSigner: vi.fn(), + } as unknown as BaseAccount; + + const x402Challenge = { + version: 0, + created_at: Date.now(), + expires_at: Date.now() + 60000, + request_nonce: 'test-nonce', + chain_id: 8453, // Base mainnet + currency: 'USDC', + amount: '1000000', + recipient: '0xrecipient', + accepts: [ + { + type: 'transferWithAuthorization', + required: ['signature', 'authorization'], + }, + ], + }; + + const response402 = new Response('Payment Required', { + status: 402, + headers: { + 'X-402': btoa(JSON.stringify(x402Challenge)), + }, + }); + + mockFetch.mockResolvedValue(response402); + + const wrappedFetch = wrapWithX402({ + account: wrongNetworkAccount, + fetchFn: mockFetch, + logger: mockLogger, + onPaymentFailure: mockOnPaymentFailure, + }); + + const result = await wrappedFetch('https://example.com/api'); + + // Should return the original 402 response + expect(result.status).toBe(402); + + // Should not have tried to get signer + expect(wrongNetworkAccount.getSigner).not.toHaveBeenCalled(); + + // Should have called onPaymentFailure with network mismatch error + expect(mockOnPaymentFailure).toHaveBeenCalledWith( + expect.objectContaining({ + error: expect.objectContaining({ + message: expect.stringContaining('network'), + }), + }) + ); + }); +}); \ No newline at end of file diff --git a/packages/atxp-x402/src/x402Wrapper.ts b/packages/atxp-x402/src/x402Wrapper.ts index 6d860c91..3f68a5e2 100644 --- a/packages/atxp-x402/src/x402Wrapper.ts +++ b/packages/atxp-x402/src/x402Wrapper.ts @@ -31,10 +31,23 @@ export function wrapWithX402(config: ClientConfig): FetchLike { log.info('Received X402 payment challenge'); + // Parse the X402 payment requirements from response body + const responseBody = await response.text(); + let paymentChallenge: any; + + try { + paymentChallenge = JSON.parse(responseBody); + } catch (parseError) { + log.error(`Failed to parse X402 challenge: ${parseError}`); + // Return a new Response with the original body since we consumed it + return new Response(responseBody, { + status: response.status, + statusText: response.statusText, + headers: response.headers + }); + } + try { - // Parse the X402 payment requirements from response body - const responseBody = await response.text(); - const paymentChallenge = JSON.parse(responseBody); // Check if this is a valid X402 response if (!paymentChallenge.x402Version || !paymentChallenge.accepts || !Array.isArray(paymentChallenge.accepts)) { @@ -148,30 +161,30 @@ export function wrapWithX402(config: ClientConfig): FetchLike { // If there's an error processing the payment, call failure callback and return original response log.error(`Failed to handle X402 payment challenge: ${error}`); - // Try to recreate the response with the body we might have consumed - const responseBody = await response.text(); - const paymentChallenge = JSON.parse(responseBody); - if (onPaymentFailure && paymentChallenge?.accepts?.[0]) { const firstOption = paymentChallenge.accepts[0]; - const amount = Number(firstOption.maxAmountRequired) / (10 ** 6); + const amount = firstOption.maxAmountRequired ? Number(firstOption.maxAmountRequired) / (10 ** 6) : 0; const url = typeof input === 'string' ? input : input.toString(); await onPaymentFailure({ payment: { accountId: account.accountId, resourceUrl: url, resourceName: firstOption.description || url, - network: firstOption.network as Network, + network: (firstOption.network || account.network) as Network, currency: 'USDC', amount: new BigNumber(amount), - iss: firstOption.payTo + iss: firstOption.payTo || '' }, error: error as Error }); } - // Return the original response - return response; + // Return a new Response with the original body since we consumed it + return new Response(responseBody, { + status: response.status, + statusText: response.statusText, + headers: response.headers + }); } }; } From abd39827530fc1aa4f6be28b5d507227d8fe2741 Mon Sep 17 00:00:00 2001 From: bdj Date: Fri, 19 Sep 2025 08:30:13 -0700 Subject: [PATCH 37/61] No separate wrappers param --- packages/atxp-client/src/atxpClient.ts | 26 ++++++-------------- packages/atxp-client/src/atxpFetcher.ts | 32 ++++++++++++++++++++++++- packages/atxp-client/src/index.ts | 2 ++ packages/atxp-client/src/types.ts | 3 +++ packages/atxp-x402/src/x402Wrapper.ts | 13 +++++----- 5 files changed, 50 insertions(+), 26 deletions(-) diff --git a/packages/atxp-client/src/atxpClient.ts b/packages/atxp-client/src/atxpClient.ts index c3fff40e..3354b9cf 100644 --- a/packages/atxp-client/src/atxpClient.ts +++ b/packages/atxp-client/src/atxpClient.ts @@ -1,6 +1,6 @@ -import { ClientConfig } from "./types.js"; -import { MemoryOAuthDb, ConsoleLogger, DEFAULT_AUTHORIZATION_SERVER } from "@atxp/common"; -import { ATXPFetcher } from "./atxpFetcher.js"; +import { ClientConfig, FetchWrapper } from "./types.js"; +import { MemoryOAuthDb, ConsoleLogger, DEFAULT_AUTHORIZATION_SERVER, FetchLike } from "@atxp/common"; +import { wrapWithATXP } from "./atxpFetcher.js"; import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'; @@ -59,22 +59,10 @@ export function buildClientConfig(args: ClientArgs): ClientConfig { export function buildStreamableTransport(args: ClientArgs): StreamableHTTPClientTransport { const config = buildClientConfig(args); - const fetcher = new ATXPFetcher({ - accountId: args.account.accountId, - db: config.oAuthDb, - paymentMakers: args.account.paymentMakers, - fetchFn: config.fetchFn, - sideChannelFetch: config.oAuthChannelFetch, - allowInsecureRequests: config.allowHttp, - allowedAuthorizationServers: config.allowedAuthorizationServers, - approvePayment: config.approvePayment, - logger: config.logger, - onAuthorize: config.onAuthorize, - onAuthorizeFailure: config.onAuthorizeFailure, - onPayment: config.onPayment, - onPaymentFailure: config.onPaymentFailure - }); - const transport = new StreamableHTTPClientTransport(new URL(args.mcpServer), {fetch: fetcher.fetch}); + // Apply the ATXP wrapper to the fetch function + const wrappedFetch = wrapWithATXP(config); + + const transport = new StreamableHTTPClientTransport(new URL(args.mcpServer), {fetch: wrappedFetch}); return transport; } diff --git a/packages/atxp-client/src/atxpFetcher.ts b/packages/atxp-client/src/atxpFetcher.ts index 6b7275a2..7eb76a86 100644 --- a/packages/atxp-client/src/atxpFetcher.ts +++ b/packages/atxp-client/src/atxpFetcher.ts @@ -1,7 +1,7 @@ import { BigNumber } from 'bignumber.js'; import { OAuthAuthenticationRequiredError, OAuthClient } from './oAuth.js'; import { PAYMENT_REQUIRED_ERROR_CODE, paymentRequiredError, AccessToken, AuthorizationServerUrl, FetchLike, OAuthDb, PaymentRequestData, DEFAULT_AUTHORIZATION_SERVER, Logger, parsePaymentRequests, parseMcpMessages, ConsoleLogger, isSSEResponse } from '@atxp/common'; -import type { PaymentMaker, ProspectivePayment } from './types.js'; +import type { PaymentMaker, ProspectivePayment, ClientConfig, FetchWrapper } from './types.js'; import { InsufficientFundsError, PaymentNetworkError } from './types.js'; import { getIsReactNative, createReactNativeSafeFetch } from '@atxp/common'; import { McpError } from '@modelcontextprotocol/sdk/types.js'; @@ -24,6 +24,36 @@ export interface ATXPFetcherConfig { onPaymentFailure?: (args: { payment: ProspectivePayment, error: Error }) => Promise; } +/** + * Creates an ATXP fetch wrapper that handles OAuth authentication and payments. + * This follows the wrapper pattern for fetch functions. + * + * @param config - The client configuration + * @returns A wrapped fetch function that handles ATXP protocol + */ +export function wrapWithATXP(config: ClientConfig): FetchLike { + const fetcher = new ATXPFetcher({ + accountId: config.account.accountId, + db: config.oAuthDb, + paymentMakers: config.account.paymentMakers, + fetchFn: config.fetchFn, + sideChannelFetch: config.oAuthChannelFetch, + allowInsecureRequests: config.allowHttp, + allowedAuthorizationServers: config.allowedAuthorizationServers, + approvePayment: config.approvePayment, + logger: config.logger, + onAuthorize: config.onAuthorize, + onAuthorizeFailure: config.onAuthorizeFailure, + onPayment: config.onPayment, + onPaymentFailure: config.onPaymentFailure + }); + return fetcher.fetch; +} + +// Keep the old function for backward compatibility, but mark as deprecated +/** + * @deprecated Use wrapWithATXP instead + */ export function atxpFetch(config: ATXPFetcherConfig): FetchLike { const fetcher = new ATXPFetcher(config); return fetcher.fetch; diff --git a/packages/atxp-client/src/index.ts b/packages/atxp-client/src/index.ts index 607d7f78..a8fbc231 100644 --- a/packages/atxp-client/src/index.ts +++ b/packages/atxp-client/src/index.ts @@ -18,6 +18,7 @@ export { export { type ATXPFetcherConfig, atxpFetch, + wrapWithATXP, ATXPFetcher } from './atxpFetcher.js'; @@ -55,6 +56,7 @@ export { type Account, type ProspectivePayment, type ClientConfig, + type FetchWrapper, InsufficientFundsError, PaymentNetworkError, type PaymentMaker diff --git a/packages/atxp-client/src/types.ts b/packages/atxp-client/src/types.ts index eb54bc92..1696d1f5 100644 --- a/packages/atxp-client/src/types.ts +++ b/packages/atxp-client/src/types.ts @@ -24,6 +24,9 @@ export type ProspectivePayment = { iss: string; } +// Type for a fetch wrapper function that takes ClientConfig and returns wrapped fetch +export type FetchWrapper = (config: ClientConfig) => FetchLike; + export type ClientConfig = { mcpServer: string; account: Account; diff --git a/packages/atxp-x402/src/x402Wrapper.ts b/packages/atxp-x402/src/x402Wrapper.ts index 3f68a5e2..bf41b99e 100644 --- a/packages/atxp-x402/src/x402Wrapper.ts +++ b/packages/atxp-x402/src/x402Wrapper.ts @@ -1,17 +1,18 @@ -import { ClientConfig, ProspectivePayment } from '@atxp/client'; +import { ClientConfig, ProspectivePayment, FetchWrapper } from '@atxp/client'; import { FetchLike, Network } from '@atxp/common'; import { BigNumber } from 'bignumber.js'; import { createPaymentHeader, selectPaymentRequirements } from 'x402/client'; import { LocalAccount } from 'viem'; /** - * Wraps fetch with X402 payment support using a local signer - * This wrapper intercepts 402 responses and creates payments using the x402 library + * Creates an X402 payment wrapper for fetch. + * This wrapper intercepts 402 responses and creates payments using the x402 library. + * It follows the standard wrapper pattern - taking ClientConfig and returning a wrapped fetch. * * @param config - ClientConfig containing account, logger, and fetch function * @returns A wrapped fetch function that handles X402 payments */ -export function wrapWithX402(config: ClientConfig): FetchLike { +export const wrapWithX402: FetchWrapper = (config: ClientConfig): FetchLike => { const { account, logger, fetchFn = fetch, approvePayment, onPayment, onPaymentFailure } = config; const log = logger ?? console; @@ -170,7 +171,7 @@ export function wrapWithX402(config: ClientConfig): FetchLike { accountId: account.accountId, resourceUrl: url, resourceName: firstOption.description || url, - network: (firstOption.network || account.network) as Network, + network: (firstOption.network || 'base') as Network, currency: 'USDC', amount: new BigNumber(amount), iss: firstOption.payTo || '' @@ -187,4 +188,4 @@ export function wrapWithX402(config: ClientConfig): FetchLike { }); } }; -} +}; From 421523aa96a53e5bb637282d2c3340dff2d9a4d6 Mon Sep 17 00:00:00 2001 From: bdj Date: Fri, 19 Sep 2025 08:35:48 -0700 Subject: [PATCH 38/61] Example uses MCP --- examples/x402-server/package-lock.json | 549 ++++++++++++++++++++++++ examples/x402-server/package.json | 1 + examples/x402-server/src/server.ts | 125 +++++- examples/x402-server/src/test-client.ts | 171 +++++--- 4 files changed, 777 insertions(+), 69 deletions(-) diff --git a/examples/x402-server/package-lock.json b/examples/x402-server/package-lock.json index 1071dba0..d44e5b70 100644 --- a/examples/x402-server/package-lock.json +++ b/examples/x402-server/package-lock.json @@ -12,6 +12,7 @@ "@atxp/common": "file:../../packages/atxp-common", "@atxp/x402": "file:../../packages/atxp-x402", "@coinbase/x402": "^0.3.8", + "@modelcontextprotocol/sdk": "^1.18.1", "bignumber.js": "^9.1.2", "cors": "^2.8.5", "dotenv": "^16.0.3", @@ -1483,6 +1484,334 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/@modelcontextprotocol/sdk": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.18.1.tgz", + "integrity": "sha512-d//GE8/Yh7aC3e7p+kZG8JqqEAwwDUmAfvH1quogtbk+ksS6E0RR6toKKESPYYZVre0meqkJb27zb+dhqE9Sgw==", + "license": "MIT", + "dependencies": { + "ajv": "^6.12.6", + "content-type": "^1.0.5", + "cors": "^2.8.5", + "cross-spawn": "^7.0.5", + "eventsource": "^3.0.2", + "eventsource-parser": "^3.0.0", + "express": "^5.0.1", + "express-rate-limit": "^7.5.0", + "pkce-challenge": "^5.0.0", + "raw-body": "^3.0.0", + "zod": "^3.23.8", + "zod-to-json-schema": "^3.24.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/body-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/content-disposition": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/@modelcontextprotocol/sdk/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/@modelcontextprotocol/sdk/node_modules/express": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@modelcontextprotocol/sdk/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/@modelcontextprotocol/sdk/node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/raw-body": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.1.tgz", + "integrity": "sha512-9G8cA+tuMS75+6G/TzW8OtLzmBDMo8p1JRxN5AZ+LAp8uxGA8V8GZm4GQ4/N5QNQEnLmg6SS7wyuSmbKepiKqA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.7.0", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", + "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/@noble/ciphers": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.3.0.tgz", @@ -5630,6 +5959,22 @@ "node": ">= 8.0.0" } }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -6161,6 +6506,20 @@ "node-fetch": "^2.7.0" } }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/crossws": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/crossws/-/crossws-0.3.5.tgz", @@ -6806,6 +7165,27 @@ "node": ">=0.8.x" } }, + "node_modules/eventsource": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz", + "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==", + "license": "MIT", + "dependencies": { + "eventsource-parser": "^3.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/eventsource-parser": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz", + "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/express": { "version": "4.21.2", "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", @@ -6852,6 +7232,21 @@ "url": "https://opencollective.com/express" } }, + "node_modules/express-rate-limit": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.1.tgz", + "integrity": "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/express-rate-limit" + }, + "peerDependencies": { + "express": ">= 4.11" + } + }, "node_modules/extension-port-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/extension-port-stream/-/extension-port-stream-3.0.0.tgz", @@ -6879,6 +7274,12 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "license": "MIT" }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "license": "MIT" + }, "node_modules/fast-redact": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", @@ -7333,6 +7734,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, "node_modules/is-regex": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", @@ -7396,6 +7803,12 @@ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "license": "MIT" }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, "node_modules/isomorphic-ws": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", @@ -7499,6 +7912,12 @@ "integrity": "sha512-RJ9YYNCkhVDBuP4zN5BBtYAzEl03yq/jIIsyif0JY9qyJuQQZNeDK7anAPKKlyEtLSj2s8h6hNh2F8zO5q7ScA==", "license": "ISC" }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -8005,6 +8424,15 @@ "node": ">=8" } }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/path-to-regexp": { "version": "0.1.12", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", @@ -8070,6 +8498,15 @@ "integrity": "sha512-cK0pekc1Kjy5w9V2/n+8MkZwusa6EyyxfeQCB799CQRhRt/CqYKiWs5adeu8Shve2ZNffvfC/7J64A2PJo1W/Q==", "license": "MIT" }, + "node_modules/pkce-challenge": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz", + "integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==", + "license": "MIT", + "engines": { + "node": ">=16.20.0" + } + }, "node_modules/pngjs": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", @@ -8154,6 +8591,15 @@ "once": "^1.3.1" } }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/qrcode": { "version": "1.5.3", "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.3.tgz", @@ -8315,6 +8761,55 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/router/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/router/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/router/node_modules/path-to-regexp": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", + "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/rpc-websockets": { "version": "9.1.3", "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-9.1.3.tgz", @@ -8535,6 +9030,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/side-channel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", @@ -9032,6 +9548,15 @@ } } }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/use-sync-external-store": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz", @@ -9269,6 +9794,21 @@ "webidl-conversions": "^3.0.0" } }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/which-module": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", @@ -9446,6 +9986,15 @@ "url": "https://github.com/sponsors/colinhacks" } }, + "node_modules/zod-to-json-schema": { + "version": "3.24.6", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.6.tgz", + "integrity": "sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==", + "license": "ISC", + "peerDependencies": { + "zod": "^3.24.1" + } + }, "node_modules/zustand": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.3.tgz", diff --git a/examples/x402-server/package.json b/examples/x402-server/package.json index 87b4fc0c..fff46ab7 100644 --- a/examples/x402-server/package.json +++ b/examples/x402-server/package.json @@ -13,6 +13,7 @@ "@atxp/common": "file:../../packages/atxp-common", "@atxp/x402": "file:../../packages/atxp-x402", "@coinbase/x402": "^0.3.8", + "@modelcontextprotocol/sdk": "^1.18.1", "bignumber.js": "^9.1.2", "cors": "^2.8.5", "dotenv": "^16.0.3", diff --git a/examples/x402-server/src/server.ts b/examples/x402-server/src/server.ts index fd018431..cff2931e 100644 --- a/examples/x402-server/src/server.ts +++ b/examples/x402-server/src/server.ts @@ -1,4 +1,6 @@ import express from "express"; +import { Server } from "@modelcontextprotocol/sdk/server/index.js"; +import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js"; import { paymentMiddleware } from "x402-express"; import { facilitator } from "@coinbase/x402"; import dotenv from "dotenv"; @@ -25,11 +27,92 @@ const facilitatorConfig = process.env.CDP_API_KEY_ID && process.env.CDP_API_KEY_ ? facilitator // Use CDP facilitator for mainnet : { url: "https://x402.org/facilitator" } ; // Use public test facilitator -// Configure payment middleware +// Create MCP server +const mcpServer = new Server({ + name: "x402-example-server", + version: "1.0.0" +}, { + capabilities: { + tools: {} + } +}); + +// Add a tool that requires payment +mcpServer.setRequestHandler("tools/list", async () => { + return { + tools: [ + { + name: "get_premium_data", + description: "Get premium data (costs $0.01 USDC)", + inputSchema: { + type: "object", + properties: { + query: { + type: "string", + description: "The query to search for" + } + }, + required: ["query"] + } + }, + { + name: "calculate_cost", + description: "Calculate the cost of an operation (costs $0.005 USDC)", + inputSchema: { + type: "object", + properties: { + amount: { + type: "number", + description: "The amount to calculate cost for" + }, + rate: { + type: "number", + description: "The rate to apply" + } + }, + required: ["amount", "rate"] + } + } + ] + }; +}); + +// Handle tool calls +mcpServer.setRequestHandler("tools/call", async (request) => { + const { name, arguments: args } = request.params; + + switch (name) { + case "get_premium_data": + return { + content: [ + { + type: "text", + text: `Premium data for query "${args.query}": This is valuable information that costs $0.01 USDC. Results: ${Math.random() * 1000} matching records found.` + } + ] + }; + + case "calculate_cost": + const cost = args.amount * args.rate; + return { + content: [ + { + type: "text", + text: `Cost calculation: ${args.amount} * ${args.rate} = ${cost} (This calculation cost $0.005 USDC)` + } + ] + }; + + default: + throw new Error(`Unknown tool: ${name}`); + } +}); + +// Configure payment middleware for MCP endpoint app.use(paymentMiddleware( recipientAddress, { - "GET /api/resource": { + "POST /mcp": { price: "$0.01", network: network, }, @@ -37,19 +120,32 @@ app.use(paymentMiddleware( facilitatorConfig )); -// Protected endpoint - costs $0.01 USDC -app.get("/api/resource", (req, res) => { - res.json({ - success: true, - data: "This is protected content that costs $0.01 USDC", - timestamp: Date.now() - }); +// Create MCP transport and handle requests +const transport = new StreamableHTTPServerTransport(); + +// MCP endpoint +app.post("/mcp", express.json(), async (req, res) => { + try { + const result = await transport.handleRequest(req.body); + res.json(result); + } catch (error) { + console.error("MCP request error:", error); + res.status(500).json({ error: "Internal server error" }); + } +}); + +// Connect transport to server +transport.connect(mcpServer); + +// Health check endpoint (free) +app.get("/health", (req, res) => { + res.json({ status: "ok", server: "x402-mcp-example" }); }); const PORT = process.env.PORT || 3001; app.listen(PORT, () => { - console.log(`X402 Server (Coinbase SDK) running on http://localhost:${PORT}`); + console.log(`X402 MCP Server running on http://localhost:${PORT}`); console.log(`Recipient address: ${recipientAddress}`); console.log(`Network: ${network} (${isMainnet ? 'MAINNET - real money!' : 'testnet'})`); console.log(`Facilitator: ${process.env.CDP_API_KEY_ID ? 'CDP (mainnet)' : 'Public test facilitator'}`); @@ -58,8 +154,13 @@ app.listen(PORT, () => { console.log("\n⚠️ WARNING: Running on MAINNET - real USDC payments!"); } - console.log("\nProtected endpoints:"); - console.log(` GET /api/resource - $0.01 USDC`); + console.log("\nEndpoints:"); + console.log(` POST /mcp - MCP endpoint ($0.01 USDC per request)`); + console.log(` GET /health - Health check (free)`); + + console.log("\nAvailable MCP tools:"); + console.log(` - get_premium_data: Get premium data ($0.01 per request)`); + console.log(` - calculate_cost: Calculate costs ($0.01 per request)`); if (!process.env.ATXP_DESTINATION) { console.error("\n❌ ERROR: ATXP_DESTINATION environment variable is required!"); diff --git a/examples/x402-server/src/test-client.ts b/examples/x402-server/src/test-client.ts index 147044fd..ae59fa43 100644 --- a/examples/x402-server/src/test-client.ts +++ b/examples/x402-server/src/test-client.ts @@ -1,74 +1,131 @@ -import { BaseAccount } from '@atxp/client'; -import { wrapWithX402 } from '@atxp/x402'; +import { atxpClient, ATXPAccount, RemoteSigner, type FetchWrapper, type ClientConfig, wrapWithATXP, type FetchLike } from "@atxp/client"; +import { wrapWithX402 } from "@atxp/x402"; import { ConsoleLogger, LogLevel } from '@atxp/common'; -import dotenv from 'dotenv'; -import path from 'path'; +import dotenv from "dotenv"; +import path from "path"; import { fileURLToPath } from 'url'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); // Load .env from current directory first, then from repo root -dotenv.config(); // Load local .env if it exists -dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); // Also load from repo root +dotenv.config(); +dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); -async function testX402Client() { - // Check for required environment variables - if (!process.env.BASE_RPC || !process.env.BASE_PRIVATE_KEY) { - console.error('Missing BASE_RPC and/or BASE_PRIVATE_KEY'); - process.exit(1); - } +async function testMCPServer() { + const serverUrl = process.env.X402_SERVER_URL || "http://localhost:3001/mcp"; + const signerUrl = process.env.ATXP_REMOTE_SIGNER_URL || "http://localhost:3002"; + + console.log("Testing X402 MCP Server with ATXP Client"); + console.log(`Server URL: ${serverUrl}`); + console.log(`Remote Signer URL: ${signerUrl}`); + + try { + // Create a remote signer that delegates to accounts-x402 + const remoteSigner = new RemoteSigner(signerUrl); + + // Get account info from remote signer + const accountInfo = await remoteSigner.getAccountInfo(); + console.log(`Using account: ${accountInfo.accountId}`); + console.log(`Account address: ${accountInfo.address}`); + + // Create ATXP account with remote signer + const account = new ATXPAccount({ + accountId: accountInfo.accountId, + remoteSigner + }); + + // Create a logger + const logger = new ConsoleLogger({ prefix: '[X402 MCP Client]', level: LogLevel.DEBUG }); + + // Create base config + const config: ClientConfig = { + mcpServer: serverUrl, + account, + logger, + fetchFn: fetch as FetchLike, + oAuthChannelFetch: fetch as FetchLike, + oAuthDb: undefined as any, // Will be set by buildClientConfig + allowedAuthorizationServers: [], + allowHttp: true, // Allow HTTP for local testing + clientInfo: { + name: "x402-test-client", + version: "1.0.0" + }, + clientOptions: { + capabilities: {} + }, + approvePayment: async (payment) => { + console.log(`\n💰 Payment approval requested:`); + console.log(` Amount: ${payment.amount} ${payment.currency}`); + console.log(` To: ${payment.iss}`); + console.log(` Network: ${payment.network}`); + console.log(` Auto-approving payment...`); + return true; + }, + onAuthorize: async () => {}, + onAuthorizeFailure: async () => {}, + onPayment: async (args) => { + console.log(`✅ Payment successful for ${args.payment.amount} ${args.payment.currency}`); + }, + onPaymentFailure: async (args) => { + console.error(`❌ Payment failed:`, args.error.message); + } + }; - // Create account to verify we have the right credentials - const account = new BaseAccount( - process.env.BASE_RPC, - process.env.BASE_PRIVATE_KEY - ); - - // Create a logger with DEBUG level to see all messages - const logger = new ConsoleLogger({ prefix: '[X402 Client]', level: LogLevel.DEBUG }); - - // Log account info - console.log('Using RPC:', process.env.BASE_RPC); - console.log('Account address:', account.accountId); - console.log('Using wrapWithX402 (our custom implementation)'); - - // Wrap fetch with X402 support using our custom implementation - const x402Fetch = wrapWithX402({ - account, - logger, - fetchFn: fetch as any, - approvePayment: async (payment) => { - console.log(`Approving payment of ${payment.amount} ${payment.currency} to ${payment.iss}`); - return true; - }, - onPayment: async ({ payment }) => { - console.log(`Payment made: ${payment.amount} ${payment.currency}`); - }, - onPaymentFailure: async ({ payment, error }) => { - console.error(`Payment failed: ${error.message}`); + // Compose the wrappers manually + // First apply X402 wrapper, then ATXP wrapper + let wrappedFetch: FetchLike = config.fetchFn; + + // Apply X402 wrapper first (handles 402 payment challenges) + wrappedFetch = wrapWithX402({ ...config, fetchFn: wrappedFetch }); + + // Apply ATXP wrapper next (handles OAuth and ATXP payments) + wrappedFetch = wrapWithATXP({ ...config, fetchFn: wrappedFetch }); + + // Create client with the composed wrapped fetch + const client = await atxpClient({ + ...config, + fetchFn: wrappedFetch + }); + + console.log("\n📡 Connected to MCP server"); + + // List available tools + console.log("\n🔧 Listing available tools..."); + const toolsResult = await client.listTools(); + console.log(`Available tools:`); + for (const tool of toolsResult.tools) { + console.log(` - ${tool.name}: ${tool.description}`); } - }); - // Make a single request to the protected endpoint - const serverUrl = process.env.X402_SERVER_URL || 'http://localhost:3001'; - console.log('Making request to:', `${serverUrl}/api/resource`); + // Call the get_premium_data tool + console.log("\n📊 Calling get_premium_data tool..."); + const dataResult = await client.callTool("get_premium_data", { + query: "blockchain metrics" + }); + console.log("Result:", dataResult.content[0].text); + + // Call the calculate_cost tool + console.log("\n🧮 Calling calculate_cost tool..."); + const calcResult = await client.callTool("calculate_cost", { + amount: 100, + rate: 0.15 + }); + console.log("Result:", calcResult.content[0].text); - const response = await x402Fetch(`${serverUrl}/api/resource`); + console.log("\n✨ All tests completed successfully!"); - if (response.ok) { - const data = await response.json(); - console.log('Success:', data); + // Close the client + await client.close(); - // Try to decode payment response if available - const paymentResponseHeader = response.headers.get('x-payment-response'); - if (paymentResponseHeader) { - const paymentResponseJson = Buffer.from(paymentResponseHeader, 'base64').toString('utf-8'); - const paymentResponse = JSON.parse(paymentResponseJson); - console.log('Payment response:', paymentResponse); + } catch (error) { + console.error("\n❌ Error:", error); + if (error instanceof Error && error.message.includes("402")) { + console.error("Payment was required but failed. Check your account balance."); } - } else { - console.error('Failed:', response.status, response.statusText); + process.exit(1); } } -testX402Client().catch(console.error); \ No newline at end of file +// Run the test +testMCPServer().catch(console.error); \ No newline at end of file From 4689b5580b3128f5bb9599b749d1981d36eaa4f5 Mon Sep 17 00:00:00 2001 From: bdj Date: Fri, 19 Sep 2025 08:43:20 -0700 Subject: [PATCH 39/61] Better MCP impl for server --- examples/x402-server/src/server.ts | 171 ++++++++++++------------ examples/x402-server/src/test-client.ts | 6 +- packages/atxp-client/src/atxpClient.ts | 4 +- packages/atxp-client/src/atxpFetcher.ts | 79 +++++------ packages/atxp-client/src/index.ts | 5 +- 5 files changed, 122 insertions(+), 143 deletions(-) diff --git a/examples/x402-server/src/server.ts b/examples/x402-server/src/server.ts index cff2931e..db7b7263 100644 --- a/examples/x402-server/src/server.ts +++ b/examples/x402-server/src/server.ts @@ -1,6 +1,5 @@ import express from "express"; import { Server } from "@modelcontextprotocol/sdk/server/index.js"; -import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js"; import { paymentMiddleware } from "x402-express"; import { facilitator } from "@coinbase/x402"; import dotenv from "dotenv"; @@ -27,7 +26,7 @@ const facilitatorConfig = process.env.CDP_API_KEY_ID && process.env.CDP_API_KEY_ ? facilitator // Use CDP facilitator for mainnet : { url: "https://x402.org/facilitator" } ; // Use public test facilitator -// Create MCP server +// Create MCP server with tools const mcpServer = new Server({ name: "x402-example-server", version: "1.0.0" @@ -37,82 +36,69 @@ const mcpServer = new Server({ } }); -// Add a tool that requires payment -mcpServer.setRequestHandler("tools/list", async () => { - return { - tools: [ - { - name: "get_premium_data", - description: "Get premium data (costs $0.01 USDC)", - inputSchema: { - type: "object", - properties: { - query: { - type: "string", - description: "The query to search for" - } - }, - required: ["query"] - } - }, - { - name: "calculate_cost", - description: "Calculate the cost of an operation (costs $0.005 USDC)", - inputSchema: { - type: "object", - properties: { - amount: { - type: "number", - description: "The amount to calculate cost for" - }, - rate: { - type: "number", - description: "The rate to apply" - } - }, - required: ["amount", "rate"] - } +// Add tools that require payment +mcpServer.addTool({ + name: "get_premium_data", + description: "Get premium data (costs $0.01 USDC)", + inputSchema: { + type: "object", + properties: { + query: { + type: "string", + description: "The query to search for" } - ] - }; + }, + required: ["query"] + }, + handler: async (args: { query: string }) => { + return { + content: [ + { + type: "text", + text: `Premium data for query "${args.query}": This is valuable information that costs $0.01 USDC. Results: ${Math.floor(Math.random() * 1000)} matching records found.` + } + ] + }; + } }); -// Handle tool calls -mcpServer.setRequestHandler("tools/call", async (request) => { - const { name, arguments: args } = request.params; - - switch (name) { - case "get_premium_data": - return { - content: [ - { - type: "text", - text: `Premium data for query "${args.query}": This is valuable information that costs $0.01 USDC. Results: ${Math.random() * 1000} matching records found.` - } - ] - }; - - case "calculate_cost": - const cost = args.amount * args.rate; - return { - content: [ - { - type: "text", - text: `Cost calculation: ${args.amount} * ${args.rate} = ${cost} (This calculation cost $0.005 USDC)` - } - ] - }; - - default: - throw new Error(`Unknown tool: ${name}`); +mcpServer.addTool({ + name: "calculate_cost", + description: "Calculate the cost of an operation (costs $0.01 USDC)", + inputSchema: { + type: "object", + properties: { + amount: { + type: "number", + description: "The amount to calculate cost for" + }, + rate: { + type: "number", + description: "The rate to apply" + } + }, + required: ["amount", "rate"] + }, + handler: async (args: { amount: number; rate: number }) => { + const cost = args.amount * args.rate; + return { + content: [ + { + type: "text", + text: `Cost calculation: ${args.amount} * ${args.rate} = ${cost} (This calculation cost $0.01 USDC)` + } + ] + }; } }); -// Configure payment middleware for MCP endpoint +// Configure payment middleware for all MCP requests +// The middleware will intercept all requests and require payment app.use(paymentMiddleware( recipientAddress, { - "POST /mcp": { + // Require payment for all POST requests (MCP uses POST) + "POST /*": { price: "$0.01", network: network, }, @@ -120,28 +106,38 @@ app.use(paymentMiddleware( facilitatorConfig )); -// Create MCP transport and handle requests -const transport = new StreamableHTTPServerTransport(); +// Parse JSON bodies +app.use(express.json()); + +// Handle all requests - MCP SDK will handle the routing +app.use(async (req, res) => { + const url = new URL(req.url, `http://${req.headers.host}`); + + // Create a fetch-like request for the MCP SDK + const mcpRequest = { + method: req.method, + url: url.toString(), + headers: req.headers as Record, + body: req.body ? JSON.stringify(req.body) : undefined + }; -// MCP endpoint -app.post("/mcp", express.json(), async (req, res) => { try { - const result = await transport.handleRequest(req.body); - res.json(result); + // Let the MCP SDK handle the request + const handler = mcpServer.createHttpRequestHandler(); + const response = await handler(mcpRequest); + + // Send the response + res.status(response.statusCode || 200); + for (const [key, value] of Object.entries(response.headers || {})) { + res.setHeader(key, value); + } + res.send(response.body); } catch (error) { console.error("MCP request error:", error); res.status(500).json({ error: "Internal server error" }); } }); -// Connect transport to server -transport.connect(mcpServer); - -// Health check endpoint (free) -app.get("/health", (req, res) => { - res.json({ status: "ok", server: "x402-mcp-example" }); -}); - const PORT = process.env.PORT || 3001; app.listen(PORT, () => { @@ -154,13 +150,10 @@ app.listen(PORT, () => { console.log("\n⚠️ WARNING: Running on MAINNET - real USDC payments!"); } - console.log("\nEndpoints:"); - console.log(` POST /mcp - MCP endpoint ($0.01 USDC per request)`); - console.log(` GET /health - Health check (free)`); - + console.log("\nPayment required: $0.01 USDC per request"); console.log("\nAvailable MCP tools:"); - console.log(` - get_premium_data: Get premium data ($0.01 per request)`); - console.log(` - calculate_cost: Calculate costs ($0.01 per request)`); + console.log(` - get_premium_data: Get premium data`); + console.log(` - calculate_cost: Calculate costs`); if (!process.env.ATXP_DESTINATION) { console.error("\n❌ ERROR: ATXP_DESTINATION environment variable is required!"); diff --git a/examples/x402-server/src/test-client.ts b/examples/x402-server/src/test-client.ts index ae59fa43..cda9fe1c 100644 --- a/examples/x402-server/src/test-client.ts +++ b/examples/x402-server/src/test-client.ts @@ -1,4 +1,4 @@ -import { atxpClient, ATXPAccount, RemoteSigner, type FetchWrapper, type ClientConfig, wrapWithATXP, type FetchLike } from "@atxp/client"; +import { atxpClient, ATXPAccount, RemoteSigner, type FetchWrapper, type ClientConfig, atxpFetch, type FetchLike } from "@atxp/client"; import { wrapWithX402 } from "@atxp/x402"; import { ConsoleLogger, LogLevel } from '@atxp/common'; import dotenv from "dotenv"; @@ -12,7 +12,7 @@ dotenv.config(); dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); async function testMCPServer() { - const serverUrl = process.env.X402_SERVER_URL || "http://localhost:3001/mcp"; + const serverUrl = process.env.X402_SERVER_URL || "http://localhost:3001"; const signerUrl = process.env.ATXP_REMOTE_SIGNER_URL || "http://localhost:3002"; console.log("Testing X402 MCP Server with ATXP Client"); @@ -80,7 +80,7 @@ async function testMCPServer() { wrappedFetch = wrapWithX402({ ...config, fetchFn: wrappedFetch }); // Apply ATXP wrapper next (handles OAuth and ATXP payments) - wrappedFetch = wrapWithATXP({ ...config, fetchFn: wrappedFetch }); + wrappedFetch = atxpFetch({ ...config, fetchFn: wrappedFetch }); // Create client with the composed wrapped fetch const client = await atxpClient({ diff --git a/packages/atxp-client/src/atxpClient.ts b/packages/atxp-client/src/atxpClient.ts index 3354b9cf..9e620ec5 100644 --- a/packages/atxp-client/src/atxpClient.ts +++ b/packages/atxp-client/src/atxpClient.ts @@ -1,6 +1,6 @@ import { ClientConfig, FetchWrapper } from "./types.js"; import { MemoryOAuthDb, ConsoleLogger, DEFAULT_AUTHORIZATION_SERVER, FetchLike } from "@atxp/common"; -import { wrapWithATXP } from "./atxpFetcher.js"; +import { atxpFetch } from "./atxpFetcher.js"; import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'; @@ -60,7 +60,7 @@ export function buildStreamableTransport(args: ClientArgs): StreamableHTTPClient const config = buildClientConfig(args); // Apply the ATXP wrapper to the fetch function - const wrappedFetch = wrapWithATXP(config); + const wrappedFetch = atxpFetch(config); const transport = new StreamableHTTPClientTransport(new URL(args.mcpServer), {fetch: wrappedFetch}); return transport; diff --git a/packages/atxp-client/src/atxpFetcher.ts b/packages/atxp-client/src/atxpFetcher.ts index 7eb76a86..dba8dcb1 100644 --- a/packages/atxp-client/src/atxpFetcher.ts +++ b/packages/atxp-client/src/atxpFetcher.ts @@ -6,24 +6,6 @@ import { InsufficientFundsError, PaymentNetworkError } from './types.js'; import { getIsReactNative, createReactNativeSafeFetch } from '@atxp/common'; import { McpError } from '@modelcontextprotocol/sdk/types.js'; -export interface ATXPFetcherConfig { - // TODO: Take an Account instead of userId and paymentMakers - accountId: string; - db: OAuthDb; - paymentMakers: {[key: string]: PaymentMaker}; - fetchFn?: FetchLike; - sideChannelFetch?: FetchLike; - strict?: boolean; - allowInsecureRequests?: boolean; - allowedAuthorizationServers?: AuthorizationServerUrl[]; - approvePayment?: (payment: ProspectivePayment) => Promise; - logger?: Logger; - onAuthorize?: (args: { authorizationServer: AuthorizationServerUrl, userId: string }) => Promise; - onAuthorizeFailure?: (args: { authorizationServer: AuthorizationServerUrl, userId: string, error: Error }) => Promise; - onPayment?: (args: { payment: ProspectivePayment }) => Promise; - onPaymentFailure?: (args: { payment: ProspectivePayment, error: Error }) => Promise; -} - /** * Creates an ATXP fetch wrapper that handles OAuth authentication and payments. * This follows the wrapper pattern for fetch functions. @@ -31,7 +13,7 @@ export interface ATXPFetcherConfig { * @param config - The client configuration * @returns A wrapped fetch function that handles ATXP protocol */ -export function wrapWithATXP(config: ClientConfig): FetchLike { +export function atxpFetch(config: ClientConfig): FetchLike { const fetcher = new ATXPFetcher({ accountId: config.account.accountId, db: config.oAuthDb, @@ -50,16 +32,7 @@ export function wrapWithATXP(config: ClientConfig): FetchLike { return fetcher.fetch; } -// Keep the old function for backward compatibility, but mark as deprecated -/** - * @deprecated Use wrapWithATXP instead - */ -export function atxpFetch(config: ATXPFetcherConfig): FetchLike { - const fetcher = new ATXPFetcher(config); - return fetcher.fetch; -} - -export class ATXPFetcher { +class ATXPFetcher { protected oauthClient: OAuthClient; protected paymentMakers: Map; protected sideChannelFetch: FetchLike; @@ -72,22 +45,38 @@ export class ATXPFetcher { protected onAuthorizeFailure: (args: { authorizationServer: AuthorizationServerUrl, userId: string, error: Error }) => Promise; protected onPayment: (args: { payment: ProspectivePayment }) => Promise; protected onPaymentFailure: (args: { payment: ProspectivePayment, error: Error }) => Promise; - constructor({ - accountId, - db, - paymentMakers, - fetchFn = fetch, - sideChannelFetch = fetchFn, - strict = true, - allowInsecureRequests = process.env.NODE_ENV === 'development', - allowedAuthorizationServers = [DEFAULT_AUTHORIZATION_SERVER], - approvePayment = async (): Promise => true, - logger = new ConsoleLogger(), - onAuthorize = async () => {}, - onAuthorizeFailure = async () => {}, - onPayment = async () => {}, - onPaymentFailure = async () => {} - }: ATXPFetcherConfig) { + constructor(config: { + accountId: string; + db: OAuthDb; + paymentMakers: {[key: string]: PaymentMaker}; + fetchFn?: FetchLike; + sideChannelFetch?: FetchLike; + strict?: boolean; + allowInsecureRequests?: boolean; + allowedAuthorizationServers?: AuthorizationServerUrl[]; + approvePayment?: (payment: ProspectivePayment) => Promise; + logger?: Logger; + onAuthorize?: (args: { authorizationServer: AuthorizationServerUrl, userId: string }) => Promise; + onAuthorizeFailure?: (args: { authorizationServer: AuthorizationServerUrl, userId: string, error: Error }) => Promise; + onPayment?: (args: { payment: ProspectivePayment }) => Promise; + onPaymentFailure?: (args: { payment: ProspectivePayment, error: Error }) => Promise; + }) { + const { + accountId, + db, + paymentMakers, + fetchFn = fetch, + sideChannelFetch = fetchFn, + strict = true, + allowInsecureRequests = process.env.NODE_ENV === 'development', + allowedAuthorizationServers = [DEFAULT_AUTHORIZATION_SERVER], + approvePayment = async (): Promise => true, + logger = new ConsoleLogger(), + onAuthorize = async () => {}, + onAuthorizeFailure = async () => {}, + onPayment = async () => {}, + onPaymentFailure = async () => {} + } = config; // Use React Native safe fetch if in React Native environment const safeFetchFn = getIsReactNative() ? createReactNativeSafeFetch(fetchFn) : fetchFn; const safeSideChannelFetch = getIsReactNative() ? createReactNativeSafeFetch(sideChannelFetch) : sideChannelFetch; diff --git a/packages/atxp-client/src/index.ts b/packages/atxp-client/src/index.ts index a8fbc231..92154a94 100644 --- a/packages/atxp-client/src/index.ts +++ b/packages/atxp-client/src/index.ts @@ -16,10 +16,7 @@ export { // HTTP fetcher with ATXP support export { - type ATXPFetcherConfig, - atxpFetch, - wrapWithATXP, - ATXPFetcher + atxpFetch } from './atxpFetcher.js'; // Payment makers for different networks From 4fec4cd2bfdd0b13b53ca99d2fbf1f5367c5f48a Mon Sep 17 00:00:00 2001 From: bdj Date: Fri, 19 Sep 2025 08:43:39 -0700 Subject: [PATCH 40/61] Shorter test client --- examples/x402-server/src/test-client.ts | 145 ++++++------------------ 1 file changed, 37 insertions(+), 108 deletions(-) diff --git a/examples/x402-server/src/test-client.ts b/examples/x402-server/src/test-client.ts index cda9fe1c..f4e52e27 100644 --- a/examples/x402-server/src/test-client.ts +++ b/examples/x402-server/src/test-client.ts @@ -1,4 +1,4 @@ -import { atxpClient, ATXPAccount, RemoteSigner, type FetchWrapper, type ClientConfig, atxpFetch, type FetchLike } from "@atxp/client"; +import { atxpClient, ATXPAccount, RemoteSigner } from "@atxp/client"; import { wrapWithX402 } from "@atxp/x402"; import { ConsoleLogger, LogLevel } from '@atxp/common'; import dotenv from "dotenv"; @@ -7,7 +7,7 @@ import { fileURLToPath } from 'url'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); -// Load .env from current directory first, then from repo root +// Load environment variables dotenv.config(); dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); @@ -15,117 +15,46 @@ async function testMCPServer() { const serverUrl = process.env.X402_SERVER_URL || "http://localhost:3001"; const signerUrl = process.env.ATXP_REMOTE_SIGNER_URL || "http://localhost:3002"; - console.log("Testing X402 MCP Server with ATXP Client"); - console.log(`Server URL: ${serverUrl}`); - console.log(`Remote Signer URL: ${signerUrl}`); - - try { - // Create a remote signer that delegates to accounts-x402 - const remoteSigner = new RemoteSigner(signerUrl); - - // Get account info from remote signer - const accountInfo = await remoteSigner.getAccountInfo(); - console.log(`Using account: ${accountInfo.accountId}`); - console.log(`Account address: ${accountInfo.address}`); - - // Create ATXP account with remote signer - const account = new ATXPAccount({ - accountId: accountInfo.accountId, - remoteSigner - }); - - // Create a logger - const logger = new ConsoleLogger({ prefix: '[X402 MCP Client]', level: LogLevel.DEBUG }); - - // Create base config - const config: ClientConfig = { - mcpServer: serverUrl, - account, - logger, - fetchFn: fetch as FetchLike, - oAuthChannelFetch: fetch as FetchLike, - oAuthDb: undefined as any, // Will be set by buildClientConfig - allowedAuthorizationServers: [], - allowHttp: true, // Allow HTTP for local testing - clientInfo: { - name: "x402-test-client", - version: "1.0.0" - }, - clientOptions: { - capabilities: {} - }, - approvePayment: async (payment) => { - console.log(`\n💰 Payment approval requested:`); - console.log(` Amount: ${payment.amount} ${payment.currency}`); - console.log(` To: ${payment.iss}`); - console.log(` Network: ${payment.network}`); - console.log(` Auto-approving payment...`); - return true; - }, - onAuthorize: async () => {}, - onAuthorizeFailure: async () => {}, - onPayment: async (args) => { - console.log(`✅ Payment successful for ${args.payment.amount} ${args.payment.currency}`); - }, - onPaymentFailure: async (args) => { - console.error(`❌ Payment failed:`, args.error.message); - } - }; - - // Compose the wrappers manually - // First apply X402 wrapper, then ATXP wrapper - let wrappedFetch: FetchLike = config.fetchFn; - - // Apply X402 wrapper first (handles 402 payment challenges) - wrappedFetch = wrapWithX402({ ...config, fetchFn: wrappedFetch }); - - // Apply ATXP wrapper next (handles OAuth and ATXP payments) - wrappedFetch = atxpFetch({ ...config, fetchFn: wrappedFetch }); - - // Create client with the composed wrapped fetch - const client = await atxpClient({ - ...config, - fetchFn: wrappedFetch - }); - - console.log("\n📡 Connected to MCP server"); - - // List available tools - console.log("\n🔧 Listing available tools..."); - const toolsResult = await client.listTools(); - console.log(`Available tools:`); - for (const tool of toolsResult.tools) { - console.log(` - ${tool.name}: ${tool.description}`); + console.log("Testing X402 MCP Server"); + console.log(`Server: ${serverUrl}`); + console.log(`Signer: ${signerUrl}`); + + // Create account with remote signer + const remoteSigner = new RemoteSigner(signerUrl); + const accountInfo = await remoteSigner.getAccountInfo(); + const account = new ATXPAccount({ + accountId: accountInfo.accountId, + remoteSigner + }); + + console.log(`Account: ${accountInfo.accountId}`); + + // Create config + const config = { + mcpServer: serverUrl, + account, + logger: new ConsoleLogger({ prefix: '[X402]', level: LogLevel.INFO }), + approvePayment: async (payment: any) => { + console.log(`💰 Approving ${payment.amount} ${payment.currency} to ${payment.iss}`); + return true; } + }; - // Call the get_premium_data tool - console.log("\n📊 Calling get_premium_data tool..."); - const dataResult = await client.callTool("get_premium_data", { - query: "blockchain metrics" - }); - console.log("Result:", dataResult.content[0].text); - - // Call the calculate_cost tool - console.log("\n🧮 Calling calculate_cost tool..."); - const calcResult = await client.callTool("calculate_cost", { - amount: 100, - rate: 0.15 - }); - console.log("Result:", calcResult.content[0].text); + // Create client with X402 wrapper + const client = await atxpClient({ + ...config, + fetchFn: wrapWithX402(config) + }); - console.log("\n✨ All tests completed successfully!"); - - // Close the client + try { + // Call the tool + console.log("\n📊 Calling get_premium_data..."); + const result = await client.callTool("get_premium_data", { query: "blockchain metrics" }); + console.log(result.content[0].text); + console.log("\n✅ Success!"); + } finally { await client.close(); - - } catch (error) { - console.error("\n❌ Error:", error); - if (error instanceof Error && error.message.includes("402")) { - console.error("Payment was required but failed. Check your account balance."); - } - process.exit(1); } } -// Run the test testMCPServer().catch(console.error); \ No newline at end of file From d7c0262fafb9fdb2fa31e54c58042e77a2155260 Mon Sep 17 00:00:00 2001 From: bdj Date: Fri, 19 Sep 2025 08:43:54 -0700 Subject: [PATCH 41/61] Shorter server --- examples/x402-server/src/server.ts | 135 ++++++----------------------- 1 file changed, 27 insertions(+), 108 deletions(-) diff --git a/examples/x402-server/src/server.ts b/examples/x402-server/src/server.ts index db7b7263..633cee19 100644 --- a/examples/x402-server/src/server.ts +++ b/examples/x402-server/src/server.ts @@ -7,156 +7,75 @@ import path from "path"; import { fileURLToPath } from 'url'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); - -// Load .env from current directory first, then from repo root -dotenv.config(); // Load local .env if it exists -dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); // Also load from repo root +dotenv.config(); +dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); const app = express(); - -// Your wallet address to receive payments const recipientAddress = process.env.ATXP_DESTINATION! as `0x${string}`; +const network = process.env.CDP_API_KEY_ID ? "base" : "base-sepolia"; -// Determine network based on environment -const isMainnet = process.env.CDP_API_KEY_ID !== undefined; -const network = isMainnet ? "base" : "base-sepolia"; - -// Configure facilitator based on environment -const facilitatorConfig = process.env.CDP_API_KEY_ID && process.env.CDP_API_KEY_SECRET - ? facilitator // Use CDP facilitator for mainnet - : { url: "https://x402.org/facilitator" } ; // Use public test facilitator - -// Create MCP server with tools +// Create MCP server const mcpServer = new Server({ name: "x402-example-server", version: "1.0.0" }, { - capabilities: { - tools: {} - } + capabilities: { tools: {} } }); -// Add tools that require payment +// Add a tool that requires payment mcpServer.addTool({ name: "get_premium_data", description: "Get premium data (costs $0.01 USDC)", inputSchema: { type: "object", properties: { - query: { - type: "string", - description: "The query to search for" - } + query: { type: "string", description: "Search query" } }, required: ["query"] }, - handler: async (args: { query: string }) => { - return { - content: [ - { - type: "text", - text: `Premium data for query "${args.query}": This is valuable information that costs $0.01 USDC. Results: ${Math.floor(Math.random() * 1000)} matching records found.` - } - ] - }; - } -}); - -mcpServer.addTool({ - name: "calculate_cost", - description: "Calculate the cost of an operation (costs $0.01 USDC)", - inputSchema: { - type: "object", - properties: { - amount: { - type: "number", - description: "The amount to calculate cost for" - }, - rate: { - type: "number", - description: "The rate to apply" - } - }, - required: ["amount", "rate"] - }, - handler: async (args: { amount: number; rate: number }) => { - const cost = args.amount * args.rate; - return { - content: [ - { - type: "text", - text: `Cost calculation: ${args.amount} * ${args.rate} = ${cost} (This calculation cost $0.01 USDC)` - } - ] - }; - } + handler: async (args: { query: string }) => ({ + content: [{ + type: "text", + text: `Premium data for "${args.query}": ${Math.floor(Math.random() * 1000)} results found.` + }] + }) }); -// Configure payment middleware for all MCP requests -// The middleware will intercept all requests and require payment +// Add payment middleware app.use(paymentMiddleware( recipientAddress, - { - // Require payment for all POST requests (MCP uses POST) - "POST /*": { - price: "$0.01", - network: network, - }, - }, - facilitatorConfig + { "POST /*": { price: "$0.01", network } }, + process.env.CDP_API_KEY_ID ? facilitator : { url: "https://x402.org/facilitator" } )); -// Parse JSON bodies +// Handle MCP requests app.use(express.json()); - -// Handle all requests - MCP SDK will handle the routing app.use(async (req, res) => { - const url = new URL(req.url, `http://${req.headers.host}`); - - // Create a fetch-like request for the MCP SDK - const mcpRequest = { - method: req.method, - url: url.toString(), - headers: req.headers as Record, - body: req.body ? JSON.stringify(req.body) : undefined - }; - try { - // Let the MCP SDK handle the request const handler = mcpServer.createHttpRequestHandler(); - const response = await handler(mcpRequest); + const response = await handler({ + method: req.method, + url: `http://${req.headers.host}${req.url}`, + headers: req.headers as Record, + body: req.body ? JSON.stringify(req.body) : undefined + }); - // Send the response res.status(response.statusCode || 200); - for (const [key, value] of Object.entries(response.headers || {})) { - res.setHeader(key, value); - } + Object.entries(response.headers || {}).forEach(([k, v]) => res.setHeader(k, v)); res.send(response.body); } catch (error) { - console.error("MCP request error:", error); res.status(500).json({ error: "Internal server error" }); } }); const PORT = process.env.PORT || 3001; - app.listen(PORT, () => { console.log(`X402 MCP Server running on http://localhost:${PORT}`); - console.log(`Recipient address: ${recipientAddress}`); - console.log(`Network: ${network} (${isMainnet ? 'MAINNET - real money!' : 'testnet'})`); - console.log(`Facilitator: ${process.env.CDP_API_KEY_ID ? 'CDP (mainnet)' : 'Public test facilitator'}`); - - if (isMainnet) { - console.log("\n⚠️ WARNING: Running on MAINNET - real USDC payments!"); - } - - console.log("\nPayment required: $0.01 USDC per request"); - console.log("\nAvailable MCP tools:"); - console.log(` - get_premium_data: Get premium data`); - console.log(` - calculate_cost: Calculate costs`); + console.log(`Payment: $0.01 USDC per request on ${network}`); + console.log(`Tool: get_premium_data - Get premium data`); if (!process.env.ATXP_DESTINATION) { - console.error("\n❌ ERROR: ATXP_DESTINATION environment variable is required!"); + console.error("ERROR: ATXP_DESTINATION environment variable required!"); process.exit(1); } }); \ No newline at end of file From b924088b251c6cef351f3f369dd74eb85a27cdab Mon Sep 17 00:00:00 2001 From: bdj Date: Fri, 19 Sep 2025 09:04:41 -0700 Subject: [PATCH 42/61] Cleanup --- examples/x402-server/src/server.ts | 81 ------------- examples/{x402-server => x402}/.env.example | 0 examples/{x402-server => x402}/README.md | 0 .../{x402-server => x402}/package-lock.json | 3 +- examples/{x402-server => x402}/package.json | 5 +- examples/x402/src/server.ts | 111 ++++++++++++++++++ .../{x402-server => x402}/src/test-client.ts | 27 ++--- examples/{x402-server => x402}/tsconfig.json | 0 tsconfig.json | 4 +- 9 files changed, 129 insertions(+), 102 deletions(-) delete mode 100644 examples/x402-server/src/server.ts rename examples/{x402-server => x402}/.env.example (100%) rename examples/{x402-server => x402}/README.md (100%) rename examples/{x402-server => x402}/package-lock.json (99%) rename examples/{x402-server => x402}/package.json (90%) create mode 100644 examples/x402/src/server.ts rename examples/{x402-server => x402}/src/test-client.ts (64%) rename examples/{x402-server => x402}/tsconfig.json (100%) diff --git a/examples/x402-server/src/server.ts b/examples/x402-server/src/server.ts deleted file mode 100644 index 633cee19..00000000 --- a/examples/x402-server/src/server.ts +++ /dev/null @@ -1,81 +0,0 @@ -import express from "express"; -import { Server } from "@modelcontextprotocol/sdk/server/index.js"; -import { paymentMiddleware } from "x402-express"; -import { facilitator } from "@coinbase/x402"; -import dotenv from "dotenv"; -import path from "path"; -import { fileURLToPath } from 'url'; - -const __dirname = path.dirname(fileURLToPath(import.meta.url)); -dotenv.config(); -dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); - -const app = express(); -const recipientAddress = process.env.ATXP_DESTINATION! as `0x${string}`; -const network = process.env.CDP_API_KEY_ID ? "base" : "base-sepolia"; - -// Create MCP server -const mcpServer = new Server({ - name: "x402-example-server", - version: "1.0.0" -}, { - capabilities: { tools: {} } -}); - -// Add a tool that requires payment -mcpServer.addTool({ - name: "get_premium_data", - description: "Get premium data (costs $0.01 USDC)", - inputSchema: { - type: "object", - properties: { - query: { type: "string", description: "Search query" } - }, - required: ["query"] - }, - handler: async (args: { query: string }) => ({ - content: [{ - type: "text", - text: `Premium data for "${args.query}": ${Math.floor(Math.random() * 1000)} results found.` - }] - }) -}); - -// Add payment middleware -app.use(paymentMiddleware( - recipientAddress, - { "POST /*": { price: "$0.01", network } }, - process.env.CDP_API_KEY_ID ? facilitator : { url: "https://x402.org/facilitator" } -)); - -// Handle MCP requests -app.use(express.json()); -app.use(async (req, res) => { - try { - const handler = mcpServer.createHttpRequestHandler(); - const response = await handler({ - method: req.method, - url: `http://${req.headers.host}${req.url}`, - headers: req.headers as Record, - body: req.body ? JSON.stringify(req.body) : undefined - }); - - res.status(response.statusCode || 200); - Object.entries(response.headers || {}).forEach(([k, v]) => res.setHeader(k, v)); - res.send(response.body); - } catch (error) { - res.status(500).json({ error: "Internal server error" }); - } -}); - -const PORT = process.env.PORT || 3001; -app.listen(PORT, () => { - console.log(`X402 MCP Server running on http://localhost:${PORT}`); - console.log(`Payment: $0.01 USDC per request on ${network}`); - console.log(`Tool: get_premium_data - Get premium data`); - - if (!process.env.ATXP_DESTINATION) { - console.error("ERROR: ATXP_DESTINATION environment variable required!"); - process.exit(1); - } -}); \ No newline at end of file diff --git a/examples/x402-server/.env.example b/examples/x402/.env.example similarity index 100% rename from examples/x402-server/.env.example rename to examples/x402/.env.example diff --git a/examples/x402-server/README.md b/examples/x402/README.md similarity index 100% rename from examples/x402-server/README.md rename to examples/x402/README.md diff --git a/examples/x402-server/package-lock.json b/examples/x402/package-lock.json similarity index 99% rename from examples/x402-server/package-lock.json rename to examples/x402/package-lock.json index d44e5b70..eeb425b8 100644 --- a/examples/x402-server/package-lock.json +++ b/examples/x402/package-lock.json @@ -19,7 +19,8 @@ "express": "^4.18.2", "x402": "^0.6.1", "x402-express": "^0.6.1", - "x402-fetch": "^0.6.0" + "x402-fetch": "^0.6.0", + "zod": "^3.25.76" }, "devDependencies": { "@types/cors": "^2.8.13", diff --git a/examples/x402-server/package.json b/examples/x402/package.json similarity index 90% rename from examples/x402-server/package.json rename to examples/x402/package.json index fff46ab7..6aeca0ed 100644 --- a/examples/x402-server/package.json +++ b/examples/x402/package.json @@ -1,5 +1,5 @@ { - "name": "@atxp/x402-server-example", + "name": "@atxp/x402-example", "version": "1.0.0", "type": "module", "private": true, @@ -20,7 +20,8 @@ "express": "^4.18.2", "x402": "^0.6.1", "x402-express": "^0.6.1", - "x402-fetch": "^0.6.0" + "x402-fetch": "^0.6.0", + "zod": "^3.25.76" }, "devDependencies": { "@types/cors": "^2.8.13", diff --git a/examples/x402/src/server.ts b/examples/x402/src/server.ts new file mode 100644 index 00000000..fe577413 --- /dev/null +++ b/examples/x402/src/server.ts @@ -0,0 +1,111 @@ +#!/usr/bin/env node +import express, { Request, Response } from 'express'; +import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; +import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'; +import { paymentMiddleware } from 'x402-express'; +import { facilitator } from '@coinbase/x402'; +import { z } from 'zod'; +import dotenv from 'dotenv'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +dotenv.config(); +dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); + +const PORT = process.env.PORT || 3001; +const recipientAddress = process.env.ATXP_DESTINATION! as `0x${string}`; +const network = process.env.CDP_API_KEY_ID ? "base" : "base-sepolia"; + +// Create MCP server with a simple tool +function createMcpServer(): McpServer { + const server = new McpServer({ + name: 'x402-example-server', + version: '1.0.0', + }, { + capabilities: { tools: {} } + }); + + // Register a tool that will require X402 payment + server.tool( + 'get_data', + 'Get premium data (requires $0.01 USDC payment via X402)', + { + query: z.string().describe('Search query'), + }, + async ({ query }: { query: string }) => { + const results = Math.floor(Math.random() * 1000); + return { + content: [{ + type: 'text', + text: `Premium data for "${query}": ${results} results found.` + }] + }; + } + ); + + return server; +} + +// Main server setup +async function main() { + console.log('🚀 Starting X402 Example Server...'); + + if (!recipientAddress) { + console.error('❌ ATXP_DESTINATION environment variable is required!'); + process.exit(1); + } + + const app = express(); + + // Setup X402 payment middleware + app.use(paymentMiddleware( + recipientAddress, + { "POST /": { price: "$0.01", network } }, + process.env.CDP_API_KEY_ID ? facilitator : { url: "https://x402.org/facilitator" } + )); + + app.use(express.json()); + + // MCP endpoint + app.post('/', async (req: Request, res: Response) => { + const server = createMcpServer(); + + try { + const transport = new StreamableHTTPServerTransport({ + sessionIdGenerator: undefined, + enableJsonResponse: true + }); + + await server.connect(transport); + await transport.handleRequest(req, res, req.body); + + res.on('close', () => { + transport.close(); + server.close(); + }); + + } catch (error) { + console.error('❌ Error handling MCP request:', error); + + if (!res.headersSent) { + res.status(500).json({ + jsonrpc: '2.0', + error: { + code: -32603, + message: 'Internal server error', + }, + id: null, + }); + } + } + }); + + app.listen(PORT, () => { + console.log(`✅ X402 MCP Server running on http://localhost:${PORT}`); + console.log(`💰 Payment: $0.01 USDC per request on ${network}`); + console.log(`📍 Recipient: ${recipientAddress}`); + }); +} + +main().catch(console.error); \ No newline at end of file diff --git a/examples/x402-server/src/test-client.ts b/examples/x402/src/test-client.ts similarity index 64% rename from examples/x402-server/src/test-client.ts rename to examples/x402/src/test-client.ts index f4e52e27..cafe231e 100644 --- a/examples/x402-server/src/test-client.ts +++ b/examples/x402/src/test-client.ts @@ -1,3 +1,4 @@ +#!/usr/bin/env node import { atxpClient, ATXPAccount, RemoteSigner } from "@atxp/client"; import { wrapWithX402 } from "@atxp/x402"; import { ConsoleLogger, LogLevel } from '@atxp/common'; @@ -6,18 +7,15 @@ import path from "path"; import { fileURLToPath } from 'url'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); - -// Load environment variables dotenv.config(); dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); -async function testMCPServer() { +async function main() { const serverUrl = process.env.X402_SERVER_URL || "http://localhost:3001"; const signerUrl = process.env.ATXP_REMOTE_SIGNER_URL || "http://localhost:3002"; - console.log("Testing X402 MCP Server"); - console.log(`Server: ${serverUrl}`); - console.log(`Signer: ${signerUrl}`); + console.log("🚀 X402 MCP Client Example"); + console.log(`📡 Server: ${serverUrl}`); // Create account with remote signer const remoteSigner = new RemoteSigner(signerUrl); @@ -27,34 +25,31 @@ async function testMCPServer() { remoteSigner }); - console.log(`Account: ${accountInfo.accountId}`); - // Create config const config = { mcpServer: serverUrl, account, logger: new ConsoleLogger({ prefix: '[X402]', level: LogLevel.INFO }), - approvePayment: async (payment: any) => { - console.log(`💰 Approving ${payment.amount} ${payment.currency} to ${payment.iss}`); + approvePayment: async () => { + console.log(`💰 Auto-approving X402 payment...`); return true; } }; - // Create client with X402 wrapper + // Create client with X402 wrapper for payment support const client = await atxpClient({ ...config, fetchFn: wrapWithX402(config) }); try { - // Call the tool - console.log("\n📊 Calling get_premium_data..."); - const result = await client.callTool("get_premium_data", { query: "blockchain metrics" }); - console.log(result.content[0].text); + // Call the tool (will trigger X402 payment) + const result = await client.callTool("get_data", { query: "blockchain metrics" }); + console.log(`\n📊 Result: ${result.content[0].text}`); console.log("\n✅ Success!"); } finally { await client.close(); } } -testMCPServer().catch(console.error); \ No newline at end of file +main().catch(console.error); \ No newline at end of file diff --git a/examples/x402-server/tsconfig.json b/examples/x402/tsconfig.json similarity index 100% rename from examples/x402-server/tsconfig.json rename to examples/x402/tsconfig.json diff --git a/tsconfig.json b/tsconfig.json index 767d0a38..658e5e0a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -13,6 +13,6 @@ "declaration": false, "allowSyntheticDefaultImports": true }, - "include": [], - "exclude": ["node_modules", "dist"] + "include": ["src/dev/**/*.ts"], + "exclude": ["node_modules", "dist", "examples", "packages"] } From 1b8959492eda80b128fd765b24889097bea79f60 Mon Sep 17 00:00:00 2001 From: bdj Date: Fri, 19 Sep 2025 09:10:52 -0700 Subject: [PATCH 43/61] Working example --- examples/x402/src/server.ts | 12 ++++++------ examples/x402/src/test-client.ts | 23 ++++++++++------------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/examples/x402/src/server.ts b/examples/x402/src/server.ts index fe577413..3b1075eb 100644 --- a/examples/x402/src/server.ts +++ b/examples/x402/src/server.ts @@ -49,10 +49,10 @@ function createMcpServer(): McpServer { // Main server setup async function main() { - console.log('🚀 Starting X402 Example Server...'); + console.log('Starting X402 Example Server...'); if (!recipientAddress) { - console.error('❌ ATXP_DESTINATION environment variable is required!'); + console.error('ATXP_DESTINATION environment variable is required!'); process.exit(1); } @@ -86,7 +86,7 @@ async function main() { }); } catch (error) { - console.error('❌ Error handling MCP request:', error); + console.error('Error handling MCP request:', error); if (!res.headersSent) { res.status(500).json({ @@ -102,9 +102,9 @@ async function main() { }); app.listen(PORT, () => { - console.log(`✅ X402 MCP Server running on http://localhost:${PORT}`); - console.log(`💰 Payment: $0.01 USDC per request on ${network}`); - console.log(`📍 Recipient: ${recipientAddress}`); + console.log(`X402 MCP Server running on http://localhost:${PORT}`); + console.log(`Payment: $0.01 USDC per request on ${network}`); + console.log(`Recipient: ${recipientAddress}`); }); } diff --git a/examples/x402/src/test-client.ts b/examples/x402/src/test-client.ts index cafe231e..ba792c82 100644 --- a/examples/x402/src/test-client.ts +++ b/examples/x402/src/test-client.ts @@ -1,5 +1,5 @@ #!/usr/bin/env node -import { atxpClient, ATXPAccount, RemoteSigner } from "@atxp/client"; +import { atxpClient, ATXPAccount } from "@atxp/client"; import { wrapWithX402 } from "@atxp/x402"; import { ConsoleLogger, LogLevel } from '@atxp/common'; import dotenv from "dotenv"; @@ -13,17 +13,14 @@ dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); async function main() { const serverUrl = process.env.X402_SERVER_URL || "http://localhost:3001"; const signerUrl = process.env.ATXP_REMOTE_SIGNER_URL || "http://localhost:3002"; + const connectionToken = process.env.ATXP_CONNECTION_TOKEN || "test-token"; - console.log("🚀 X402 MCP Client Example"); - console.log(`📡 Server: ${serverUrl}`); + console.log("X402 MCP Client Example"); + console.log(`Server: ${serverUrl}`); - // Create account with remote signer - const remoteSigner = new RemoteSigner(signerUrl); - const accountInfo = await remoteSigner.getAccountInfo(); - const account = new ATXPAccount({ - accountId: accountInfo.accountId, - remoteSigner - }); + // Create account with connection string + const connectionString = `${signerUrl}?connection_token=${connectionToken}`; + const account = new ATXPAccount(connectionString); // Create config const config = { @@ -31,7 +28,7 @@ async function main() { account, logger: new ConsoleLogger({ prefix: '[X402]', level: LogLevel.INFO }), approvePayment: async () => { - console.log(`💰 Auto-approving X402 payment...`); + console.log(`Auto-approving X402 payment...`); return true; } }; @@ -45,8 +42,8 @@ async function main() { try { // Call the tool (will trigger X402 payment) const result = await client.callTool("get_data", { query: "blockchain metrics" }); - console.log(`\n📊 Result: ${result.content[0].text}`); - console.log("\n✅ Success!"); + console.log(`\nResult: ${result.content[0].text}`); + console.log("\nSuccess!"); } finally { await client.close(); } From 11fb1bb38286c1813b4b4073955907206ce1c339 Mon Sep 17 00:00:00 2001 From: bdj Date: Fri, 19 Sep 2025 09:14:50 -0700 Subject: [PATCH 44/61] Test locally --- examples/x402/src/test-client.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/x402/src/test-client.ts b/examples/x402/src/test-client.ts index ba792c82..c3716be6 100644 --- a/examples/x402/src/test-client.ts +++ b/examples/x402/src/test-client.ts @@ -1,5 +1,5 @@ #!/usr/bin/env node -import { atxpClient, ATXPAccount } from "@atxp/client"; +import { atxpClient, ATXPAccount, BaseAccount } from "@atxp/client"; import { wrapWithX402 } from "@atxp/x402"; import { ConsoleLogger, LogLevel } from '@atxp/common'; import dotenv from "dotenv"; @@ -20,7 +20,8 @@ async function main() { // Create account with connection string const connectionString = `${signerUrl}?connection_token=${connectionToken}`; - const account = new ATXPAccount(connectionString); + //const account = new ATXPAccount(connectionString); + const account = new BaseAccount(process.env.BASE_RPC!, process.env.BASE_PRIVATE_KEY! as `0x${string}`); // Create config const config = { From 4b177a5eac56fd2c2aeeea2a41c698965c41ae8c Mon Sep 17 00:00:00 2001 From: bdj Date: Fri, 19 Sep 2025 10:34:59 -0700 Subject: [PATCH 45/61] WIP --- examples/x402/package-lock.json | 4 +- examples/x402/src/server.ts | 72 +++++++++++++++++++++++---- examples/x402/src/test-client.ts | 4 +- packages/atxp-client/src/types.ts | 5 +- packages/atxp-x402/src/x402Wrapper.ts | 44 +++++++++++----- 5 files changed, 101 insertions(+), 28 deletions(-) diff --git a/examples/x402/package-lock.json b/examples/x402/package-lock.json index eeb425b8..b4d56bd8 100644 --- a/examples/x402/package-lock.json +++ b/examples/x402/package-lock.json @@ -1,11 +1,11 @@ { - "name": "@atxp/x402-server-example", + "name": "@atxp/x402-example", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "@atxp/x402-server-example", + "name": "@atxp/x402-example", "version": "1.0.0", "dependencies": { "@atxp/client": "file:../../packages/atxp-client", diff --git a/examples/x402/src/server.ts b/examples/x402/src/server.ts index 3b1075eb..795b54cc 100644 --- a/examples/x402/src/server.ts +++ b/examples/x402/src/server.ts @@ -58,17 +58,29 @@ async function main() { const app = express(); - // Setup X402 payment middleware - app.use(paymentMiddleware( + // Capture raw body as Buffer for all requests + // This ensures we can replay the body for both X402 and MCP processing + app.use(express.raw({ type: '*/*', limit: '10mb' })); + + // Setup X402 payment middleware for POST only + const x402Middleware = paymentMiddleware( recipientAddress, - { "POST /": { price: "$0.01", network } }, + { + //"POST /": { price: "$0.01", network } + }, process.env.CDP_API_KEY_ID ? facilitator : { url: "https://x402.org/facilitator" } - )); + ); + + // MCP endpoint - handle both GET and POST + const handleMcpRequest = async (req: Request, res: Response) => { + console.log('Received request with headers:', req.headers); + console.log('Accept header:', req.headers.accept); - app.use(express.json()); + // Don't process if payment was already handled (avoid double processing) + if (res.headersSent) { + return; + } - // MCP endpoint - app.post('/', async (req: Request, res: Response) => { const server = createMcpServer(); try { @@ -78,7 +90,20 @@ async function main() { }); await server.connect(transport); - await transport.handleRequest(req, res, req.body); + + // If we have a body, parse it and pass it to the transport + let parsedBody = undefined; + if (req.body && Buffer.isBuffer(req.body) && req.body.length > 0) { + try { + parsedBody = JSON.parse(req.body.toString()); + console.log('Parsed body:', JSON.stringify(parsedBody, null, 2)); + } catch (e) { + console.error('Failed to parse body:', e); + } + } + + // Pass the parsed body to the transport + await transport.handleRequest(req, res, parsedBody); res.on('close', () => { transport.close(); @@ -99,13 +124,40 @@ async function main() { }); } } - }); + }; + + // Apply X402 middleware and handle MCP requests + // The middleware will process payments, then pass control to the MCP handler + //app.get('/', x402Middleware, handleMcpRequest); + //app.post('/', x402Middleware, handleMcpRequest); + app.get('/', handleMcpRequest); + app.post('/', handleMcpRequest); - app.listen(PORT, () => { + const server = app.listen(PORT, () => { console.log(`X402 MCP Server running on http://localhost:${PORT}`); console.log(`Payment: $0.01 USDC per request on ${network}`); console.log(`Recipient: ${recipientAddress}`); }); + + // Graceful shutdown handling + const shutdown = () => { + console.log('\nShutting down server...'); + server.close(() => { + console.log('Server closed'); + process.exit(0); + }); + + // Force exit after 5 seconds if graceful shutdown fails + setTimeout(() => { + console.error('Forced shutdown after timeout'); + process.exit(1); + }, 5000); + }; + + // Handle termination signals + process.on('SIGINT', shutdown); // Ctrl-C + process.on('SIGTERM', shutdown); // Terminal close + process.on('SIGHUP', shutdown); // Terminal disconnect } main().catch(console.error); \ No newline at end of file diff --git a/examples/x402/src/test-client.ts b/examples/x402/src/test-client.ts index c3716be6..3ee1d65e 100644 --- a/examples/x402/src/test-client.ts +++ b/examples/x402/src/test-client.ts @@ -27,7 +27,7 @@ async function main() { const config = { mcpServer: serverUrl, account, - logger: new ConsoleLogger({ prefix: '[X402]', level: LogLevel.INFO }), + logger: new ConsoleLogger({ prefix: '[X402]', level: LogLevel.DEBUG }), approvePayment: async () => { console.log(`Auto-approving X402 payment...`); return true; @@ -37,7 +37,7 @@ async function main() { // Create client with X402 wrapper for payment support const client = await atxpClient({ ...config, - fetchFn: wrapWithX402(config) + //fetchFn: wrapWithX402(config) }); try { diff --git a/packages/atxp-client/src/types.ts b/packages/atxp-client/src/types.ts index 1696d1f5..435a43f8 100644 --- a/packages/atxp-client/src/types.ts +++ b/packages/atxp-client/src/types.ts @@ -24,8 +24,9 @@ export type ProspectivePayment = { iss: string; } -// Type for a fetch wrapper function that takes ClientConfig and returns wrapped fetch -export type FetchWrapper = (config: ClientConfig) => FetchLike; +// Type for a fetch wrapper function that takes ClientArgs and returns wrapped fetch +// ClientArgs is a partial ClientConfig with only required fields mandatory +export type FetchWrapper = (config: any) => FetchLike; // Using 'any' temporarily, will be replaced with ClientArgs when exported export type ClientConfig = { mcpServer: string; diff --git a/packages/atxp-x402/src/x402Wrapper.ts b/packages/atxp-x402/src/x402Wrapper.ts index bf41b99e..77ed7974 100644 --- a/packages/atxp-x402/src/x402Wrapper.ts +++ b/packages/atxp-x402/src/x402Wrapper.ts @@ -1,4 +1,4 @@ -import { ClientConfig, ProspectivePayment, FetchWrapper } from '@atxp/client'; +import { ClientArgs, ProspectivePayment, FetchWrapper } from '@atxp/client'; import { FetchLike, Network } from '@atxp/common'; import { BigNumber } from 'bignumber.js'; import { createPaymentHeader, selectPaymentRequirements } from 'x402/client'; @@ -9,10 +9,10 @@ import { LocalAccount } from 'viem'; * This wrapper intercepts 402 responses and creates payments using the x402 library. * It follows the standard wrapper pattern - taking ClientConfig and returning a wrapped fetch. * - * @param config - ClientConfig containing account, logger, and fetch function + * @param config - ClientArgs containing account, logger, and fetch function * @returns A wrapped fetch function that handles X402 payments */ -export const wrapWithX402: FetchWrapper = (config: ClientConfig): FetchLike => { +export const wrapWithX402: FetchWrapper = (config: ClientArgs): FetchLike => { const { account, logger, fetchFn = fetch, approvePayment, onPayment, onPaymentFailure } = config; const log = logger ?? console; @@ -22,7 +22,8 @@ export const wrapWithX402: FetchWrapper = (config: ClientConfig): FetchLike => { throw new Error('Account does not support getSigner, X402 payments will not work'); } - return async function x402FetchWrapper(input: string | URL, init?: RequestInit): Promise { + // Use arrow function to preserve context, matching atxpFetcher pattern + const x402FetchWrapper: FetchLike = async (input: string | URL, init?: RequestInit): Promise => { const response = await fetchFn(input, init); // Check if this is an X402 payment challenge @@ -125,18 +126,35 @@ export const wrapWithX402: FetchWrapper = (config: ClientConfig): FetchLike => { selectedPaymentRequirements ); - // Add the payment header and retry the request - const retryInit = { + // Add the payment header and retry the request, preserving ALL original headers + // This is crucial to maintain Accept and other headers + const originalHeaders = init?.headers; + let retryHeaders: Headers; + + // Always use Headers object to ensure proper header handling + if (originalHeaders instanceof Headers) { + // Clone the Headers object + retryHeaders = new Headers(originalHeaders); + } else if (originalHeaders) { + // Convert plain object to Headers + retryHeaders = new Headers(originalHeaders as HeadersInit); + } else { + // Start with empty headers + retryHeaders = new Headers(); + } + + // Add payment headers + retryHeaders.set('X-PAYMENT', paymentHeader); + retryHeaders.set('Access-Control-Expose-Headers', 'X-PAYMENT-RESPONSE'); + + // Create new init object with preserved headers + const retryInit: RequestInit = { ...init, - headers: { - ...(init?.headers || {}), - 'X-PAYMENT': paymentHeader, - // Request the payment response header - 'Access-Control-Expose-Headers': 'X-PAYMENT-RESPONSE' - } + headers: retryHeaders }; log.info('Retrying request with X-PAYMENT header'); + log.debug(`Retry headers: X-PAYMENT=${paymentHeader.substring(0, 20)}...`); const retryResponse = await fetchFn(input, retryInit); if (retryResponse.ok) { @@ -188,4 +206,6 @@ export const wrapWithX402: FetchWrapper = (config: ClientConfig): FetchLike => { }); } }; + + return x402FetchWrapper; }; From 7fc0593119a3c5f0249989f5cd3c174ad0d0220d Mon Sep 17 00:00:00 2001 From: bdj Date: Fri, 19 Sep 2025 10:44:46 -0700 Subject: [PATCH 46/61] Simpler server/test-client --- examples/x402/src/server.ts | 78 +++++++++++--------------------- examples/x402/src/test-client.ts | 19 ++++---- 2 files changed, 37 insertions(+), 60 deletions(-) diff --git a/examples/x402/src/server.ts b/examples/x402/src/server.ts index 795b54cc..1343888b 100644 --- a/examples/x402/src/server.ts +++ b/examples/x402/src/server.ts @@ -17,7 +17,7 @@ const PORT = process.env.PORT || 3001; const recipientAddress = process.env.ATXP_DESTINATION! as `0x${string}`; const network = process.env.CDP_API_KEY_ID ? "base" : "base-sepolia"; -// Create MCP server with a simple tool +// Create MCP server function createMcpServer(): McpServer { const server = new McpServer({ name: 'x402-example-server', @@ -26,10 +26,10 @@ function createMcpServer(): McpServer { capabilities: { tools: {} } }); - // Register a tool that will require X402 payment + // Register a simple tool server.tool( 'get_data', - 'Get premium data (requires $0.01 USDC payment via X402)', + 'Get premium data', { query: z.string().describe('Search query'), }, @@ -58,28 +58,21 @@ async function main() { const app = express(); - // Capture raw body as Buffer for all requests - // This ensures we can replay the body for both X402 and MCP processing - app.use(express.raw({ type: '*/*', limit: '10mb' })); + // IMPORTANT: Parse JSON before X402 middleware + app.use(express.json()); - // Setup X402 payment middleware for POST only - const x402Middleware = paymentMiddleware( + // Setup X402 payment middleware + /*app.use(paymentMiddleware( recipientAddress, { - //"POST /": { price: "$0.01", network } + "POST /": { price: "$0.01", network } }, process.env.CDP_API_KEY_ID ? facilitator : { url: "https://x402.org/facilitator" } - ); - - // MCP endpoint - handle both GET and POST - const handleMcpRequest = async (req: Request, res: Response) => { - console.log('Received request with headers:', req.headers); - console.log('Accept header:', req.headers.accept); + ));*/ - // Don't process if payment was already handled (avoid double processing) - if (res.headersSent) { - return; - } + // MCP endpoint handler + app.post('/', async (req: Request, res: Response) => { + console.log('Received POST request'); const server = createMcpServer(); @@ -91,19 +84,8 @@ async function main() { await server.connect(transport); - // If we have a body, parse it and pass it to the transport - let parsedBody = undefined; - if (req.body && Buffer.isBuffer(req.body) && req.body.length > 0) { - try { - parsedBody = JSON.parse(req.body.toString()); - console.log('Parsed body:', JSON.stringify(parsedBody, null, 2)); - } catch (e) { - console.error('Failed to parse body:', e); - } - } - - // Pass the parsed body to the transport - await transport.handleRequest(req, res, parsedBody); + // Pass the parsed body from express.json() + await transport.handleRequest(req, res, req.body); res.on('close', () => { transport.close(); @@ -124,14 +106,17 @@ async function main() { }); } } - }; + }); - // Apply X402 middleware and handle MCP requests - // The middleware will process payments, then pass control to the MCP handler - //app.get('/', x402Middleware, handleMcpRequest); - //app.post('/', x402Middleware, handleMcpRequest); - app.get('/', handleMcpRequest); - app.post('/', handleMcpRequest); + // Handle GET requests + app.get('/', async (req: Request, res: Response) => { + console.log('Received GET request'); + res.status(200).json({ + message: 'X402 MCP Server is running', + price: '$0.01 USDC per POST request', + network + }); + }); const server = app.listen(PORT, () => { console.log(`X402 MCP Server running on http://localhost:${PORT}`); @@ -140,24 +125,13 @@ async function main() { }); // Graceful shutdown handling - const shutdown = () => { + process.on('SIGINT', () => { console.log('\nShutting down server...'); server.close(() => { console.log('Server closed'); process.exit(0); }); - - // Force exit after 5 seconds if graceful shutdown fails - setTimeout(() => { - console.error('Forced shutdown after timeout'); - process.exit(1); - }, 5000); - }; - - // Handle termination signals - process.on('SIGINT', shutdown); // Ctrl-C - process.on('SIGTERM', shutdown); // Terminal close - process.on('SIGHUP', shutdown); // Terminal disconnect + }); } main().catch(console.error); \ No newline at end of file diff --git a/examples/x402/src/test-client.ts b/examples/x402/src/test-client.ts index 3ee1d65e..d5b2e094 100644 --- a/examples/x402/src/test-client.ts +++ b/examples/x402/src/test-client.ts @@ -1,5 +1,5 @@ #!/usr/bin/env node -import { atxpClient, ATXPAccount, BaseAccount } from "@atxp/client"; +import { atxpClient, BaseAccount } from "@atxp/client"; import { wrapWithX402 } from "@atxp/x402"; import { ConsoleLogger, LogLevel } from '@atxp/common'; import dotenv from "dotenv"; @@ -12,16 +12,15 @@ dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); async function main() { const serverUrl = process.env.X402_SERVER_URL || "http://localhost:3001"; - const signerUrl = process.env.ATXP_REMOTE_SIGNER_URL || "http://localhost:3002"; - const connectionToken = process.env.ATXP_CONNECTION_TOKEN || "test-token"; console.log("X402 MCP Client Example"); console.log(`Server: ${serverUrl}`); - // Create account with connection string - const connectionString = `${signerUrl}?connection_token=${connectionToken}`; - //const account = new ATXPAccount(connectionString); - const account = new BaseAccount(process.env.BASE_RPC!, process.env.BASE_PRIVATE_KEY! as `0x${string}`); + // Create account + const account = new BaseAccount( + process.env.BASE_RPC!, + process.env.BASE_PRIVATE_KEY! as `0x${string}` + ); // Create config const config = { @@ -41,10 +40,14 @@ async function main() { }); try { - // Call the tool (will trigger X402 payment) + // Call the tool - will trigger X402 payment + console.log("\nCalling tool 'get_data'..."); const result = await client.callTool("get_data", { query: "blockchain metrics" }); + console.log(`\nResult: ${result.content[0].text}`); console.log("\nSuccess!"); + } catch (error) { + console.error("Error:", error); } finally { await client.close(); } From 92cc99fb53c91c9559868bed5af152a9dd6ced18 Mon Sep 17 00:00:00 2001 From: bdj Date: Fri, 19 Sep 2025 11:04:14 -0700 Subject: [PATCH 47/61] dev:resource and dev:cli working --- package.json | 4 ++-- packages/atxp-client/src/atxpClient.ts | 6 ++---- packages/atxp-client/src/atxpFetcher.ts | 2 +- packages/atxp-client/src/index.ts | 2 +- packages/atxp-client/src/types.ts | 13 +++++++++---- packages/atxp-x402/src/x402Wrapper.ts | 25 +++++++++++++++++++------ src/dev/cli.ts | 2 +- src/dev/resource.ts | 13 +++++++------ 8 files changed, 42 insertions(+), 25 deletions(-) diff --git a/package.json b/package.json index 05d9e7f2..50c50507 100644 --- a/package.json +++ b/package.json @@ -37,8 +37,8 @@ "test": "npm run test --workspaces --if-present", "test:integration": "npm run test:integration --workspaces --if-present", "test:package-managers": "npm run test:package-managers -w packages/atxp-common", - "dev:resource": "npm run build && npm run build:dev && node dist/resource.js", - "dev:cli": "npm run build && npm run build:dev && node dist/cli.js", + "dev:resource": "npm run build:dev && node dist/resource.js", + "dev:cli": "npm run build:dev && node dist/cli.js", "size:report": "node scripts/bundle-size-ci.js --stdout", "size:ci": "node scripts/bundle-size-ci.js", "validate:packages": "node scripts/validate-packages.js", diff --git a/packages/atxp-client/src/atxpClient.ts b/packages/atxp-client/src/atxpClient.ts index 9e620ec5..e9753d07 100644 --- a/packages/atxp-client/src/atxpClient.ts +++ b/packages/atxp-client/src/atxpClient.ts @@ -1,13 +1,11 @@ -import { ClientConfig, FetchWrapper } from "./types.js"; -import { MemoryOAuthDb, ConsoleLogger, DEFAULT_AUTHORIZATION_SERVER, FetchLike } from "@atxp/common"; +import { ClientConfig, ClientArgs } from "./types.js"; +import { MemoryOAuthDb, ConsoleLogger, DEFAULT_AUTHORIZATION_SERVER } from "@atxp/common"; import { atxpFetch } from "./atxpFetcher.js"; import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'; type RequiredClientConfigFields = 'mcpServer' | 'account'; -type RequiredClientConfig = Pick; type OptionalClientConfig = Omit; -export type ClientArgs = RequiredClientConfig & Partial; type BuildableClientConfigFields = 'oAuthDb' | 'logger'; // Detect if we're in a browser environment and bind fetch appropriately diff --git a/packages/atxp-client/src/atxpFetcher.ts b/packages/atxp-client/src/atxpFetcher.ts index dba8dcb1..624cbe05 100644 --- a/packages/atxp-client/src/atxpFetcher.ts +++ b/packages/atxp-client/src/atxpFetcher.ts @@ -1,7 +1,7 @@ import { BigNumber } from 'bignumber.js'; import { OAuthAuthenticationRequiredError, OAuthClient } from './oAuth.js'; import { PAYMENT_REQUIRED_ERROR_CODE, paymentRequiredError, AccessToken, AuthorizationServerUrl, FetchLike, OAuthDb, PaymentRequestData, DEFAULT_AUTHORIZATION_SERVER, Logger, parsePaymentRequests, parseMcpMessages, ConsoleLogger, isSSEResponse } from '@atxp/common'; -import type { PaymentMaker, ProspectivePayment, ClientConfig, FetchWrapper } from './types.js'; +import type { PaymentMaker, ProspectivePayment, ClientConfig } from './types.js'; import { InsufficientFundsError, PaymentNetworkError } from './types.js'; import { getIsReactNative, createReactNativeSafeFetch } from '@atxp/common'; import { McpError } from '@modelcontextprotocol/sdk/types.js'; diff --git a/packages/atxp-client/src/index.ts b/packages/atxp-client/src/index.ts index 92154a94..f906dab1 100644 --- a/packages/atxp-client/src/index.ts +++ b/packages/atxp-client/src/index.ts @@ -1,6 +1,5 @@ // Main client functionality export { - type ClientArgs, DEFAULT_CLIENT_CONFIG, buildClientConfig, buildStreamableTransport, @@ -53,6 +52,7 @@ export { type Account, type ProspectivePayment, type ClientConfig, + type ClientArgs, type FetchWrapper, InsufficientFundsError, PaymentNetworkError, diff --git a/packages/atxp-client/src/types.ts b/packages/atxp-client/src/types.ts index 435a43f8..f68a5756 100644 --- a/packages/atxp-client/src/types.ts +++ b/packages/atxp-client/src/types.ts @@ -24,10 +24,6 @@ export type ProspectivePayment = { iss: string; } -// Type for a fetch wrapper function that takes ClientArgs and returns wrapped fetch -// ClientArgs is a partial ClientConfig with only required fields mandatory -export type FetchWrapper = (config: any) => FetchLike; // Using 'any' temporarily, will be replaced with ClientArgs when exported - export type ClientConfig = { mcpServer: string; account: Account; @@ -46,6 +42,15 @@ export type ClientConfig = { onPaymentFailure: (args: { payment: ProspectivePayment, error: Error }) => Promise; } +// ClientArgs for creating clients - required fields plus optional overrides +type RequiredClientConfigFields = 'mcpServer' | 'account'; +type RequiredClientConfig = Pick; +type OptionalClientConfig = Omit; +export type ClientArgs = RequiredClientConfig & Partial; + +// Type for a fetch wrapper function that takes ClientArgs and returns wrapped fetch +export type FetchWrapper = (config: ClientArgs) => FetchLike; + export class InsufficientFundsError extends Error { constructor( public readonly currency: Currency, diff --git a/packages/atxp-x402/src/x402Wrapper.ts b/packages/atxp-x402/src/x402Wrapper.ts index 77ed7974..046d1329 100644 --- a/packages/atxp-x402/src/x402Wrapper.ts +++ b/packages/atxp-x402/src/x402Wrapper.ts @@ -1,9 +1,19 @@ -import { ClientArgs, ProspectivePayment, FetchWrapper } from '@atxp/client'; +import { ProspectivePayment, FetchWrapper, ClientArgs } from '@atxp/client'; import { FetchLike, Network } from '@atxp/common'; import { BigNumber } from 'bignumber.js'; import { createPaymentHeader, selectPaymentRequirements } from 'x402/client'; import { LocalAccount } from 'viem'; +// Type guard for X402 challenge +interface X402Challenge { + x402Version?: unknown; + accepts?: unknown; +} + +function isX402Challenge(obj: unknown): obj is X402Challenge { + return typeof obj === 'object' && obj !== null; +} + /** * Creates an X402 payment wrapper for fetch. * This wrapper intercepts 402 responses and creates payments using the x402 library. @@ -35,7 +45,7 @@ export const wrapWithX402: FetchWrapper = (config: ClientArgs): FetchLike => { // Parse the X402 payment requirements from response body const responseBody = await response.text(); - let paymentChallenge: any; + let paymentChallenge: unknown; try { paymentChallenge = JSON.parse(responseBody); @@ -52,7 +62,10 @@ export const wrapWithX402: FetchWrapper = (config: ClientArgs): FetchLike => { try { // Check if this is a valid X402 response - if (!paymentChallenge.x402Version || !paymentChallenge.accepts || !Array.isArray(paymentChallenge.accepts)) { + if (!isX402Challenge(paymentChallenge) || + !paymentChallenge.x402Version || + !paymentChallenge.accepts || + !Array.isArray(paymentChallenge.accepts)) { log.debug('Received 402 response without valid X402 format'); // Return a new Response with the original body since we consumed it return new Response(responseBody, { @@ -122,7 +135,7 @@ export const wrapWithX402: FetchWrapper = (config: ClientArgs): FetchLike => { log.debug('Creating X402 payment header with signer'); const paymentHeader = await createPaymentHeader( signer, - paymentChallenge.x402Version, + paymentChallenge.x402Version as number, selectedPaymentRequirements ); @@ -180,8 +193,8 @@ export const wrapWithX402: FetchWrapper = (config: ClientArgs): FetchLike => { // If there's an error processing the payment, call failure callback and return original response log.error(`Failed to handle X402 payment challenge: ${error}`); - if (onPaymentFailure && paymentChallenge?.accepts?.[0]) { - const firstOption = paymentChallenge.accepts[0]; + if (onPaymentFailure && isX402Challenge(paymentChallenge) && paymentChallenge.accepts && Array.isArray(paymentChallenge.accepts) && paymentChallenge.accepts[0]) { + const firstOption = paymentChallenge.accepts[0] as any; const amount = firstOption.maxAmountRequired ? Number(firstOption.maxAmountRequired) / (10 ** 6) : 0; const url = typeof input === 'string' ? input : input.toString(); await onPaymentFailure({ diff --git a/src/dev/cli.ts b/src/dev/cli.ts index 120397b1..35658c7b 100644 --- a/src/dev/cli.ts +++ b/src/dev/cli.ts @@ -1,5 +1,5 @@ /* eslint-disable no-console */ -import { atxpClient, ATXPAccount } from '@atxp/client'; +import { atxpClient, ATXPAccount, BaseAccount } from '@atxp/client'; import { ConsoleLogger, LogLevel } from '@atxp/common'; import 'dotenv/config'; diff --git a/src/dev/resource.ts b/src/dev/resource.ts index 0a37e766..d467b547 100644 --- a/src/dev/resource.ts +++ b/src/dev/resource.ts @@ -5,7 +5,8 @@ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/ import { z } from 'zod'; import { CallToolResult } from '@modelcontextprotocol/sdk/types.js'; import { BigNumber } from 'bignumber.js'; -import { atxpServer, requirePayment } from '@atxp/server'; +import { requirePayment, ChainPaymentDestination } from '@atxp/server'; +import { atxpExpress } from '@atxp/express'; import { ConsoleLogger, LogLevel } from '@atxp/common'; import 'dotenv/config'; @@ -44,11 +45,11 @@ const getServer = () => { const app = express(); app.use(express.json()); -const destination = process.env.ATXP_DESTINATION!; -console.log('Starting MCP server with destination', destination); -app.use(atxpServer({ - destination, - network: 'base', +const destinationAddress = process.env.ATXP_DESTINATION!; +const destination = new ChainPaymentDestination(destinationAddress, 'base'); +console.log('Starting MCP server with destination', destinationAddress); +app.use(atxpExpress({ + paymentDestination: destination, resource: `http://localhost:${PORT}`, //server: 'http://localhost:3010', server: 'https://auth.atxp.ai', From 477cdc262bdea95af4de0e33f3a0f51689b1b646 Mon Sep 17 00:00:00 2001 From: bdj Date: Fri, 19 Sep 2025 11:21:20 -0700 Subject: [PATCH 48/61] Fixed x402 example from src/dev --- examples/x402/src/server.ts | 219 +++++++++++++++---------------- examples/x402/src/test-client.ts | 45 ++----- 2 files changed, 119 insertions(+), 145 deletions(-) diff --git a/examples/x402/src/server.ts b/examples/x402/src/server.ts index 1343888b..f147cb4c 100644 --- a/examples/x402/src/server.ts +++ b/examples/x402/src/server.ts @@ -1,45 +1,40 @@ -#!/usr/bin/env node +/* eslint-disable no-console */ import express, { Request, Response } from 'express'; import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'; -import { paymentMiddleware } from 'x402-express'; -import { facilitator } from '@coinbase/x402'; import { z } from 'zod'; -import dotenv from 'dotenv'; -import path from 'path'; -import { fileURLToPath } from 'url'; +import { CallToolResult } from '@modelcontextprotocol/sdk/types.js'; +import { BigNumber } from 'bignumber.js'; +import { requirePayment, ChainPaymentDestination } from '@atxp/server'; +import { atxpExpress } from '@atxp/express'; +import { ConsoleLogger, LogLevel } from '@atxp/common'; +import 'dotenv/config'; -const __dirname = path.dirname(fileURLToPath(import.meta.url)); -dotenv.config(); -dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); +const PORT = 3001; -const PORT = process.env.PORT || 3001; -const recipientAddress = process.env.ATXP_DESTINATION! as `0x${string}`; -const network = process.env.CDP_API_KEY_ID ? "base" : "base-sepolia"; - -// Create MCP server -function createMcpServer(): McpServer { +const getServer = () => { + // Create an MCP server with implementation details const server = new McpServer({ - name: 'x402-example-server', + name: 'stateless-streamable-http-server', version: '1.0.0', - }, { - capabilities: { tools: {} } - }); + }, { capabilities: { logging: {} } }); - // Register a simple tool + // Register a tool specifically for testing resumability server.tool( - 'get_data', - 'Get premium data', + 'secure-data', + 'Secure data', { - query: z.string().describe('Search query'), + message: z.string().optional().describe('Message to secure'), }, - async ({ query }: { query: string }) => { - const results = Math.floor(Math.random() * 1000); + async ({ message }: { message?: string }): Promise => { + // await requirePayment({price: BigNumber(0.01)}); // Will be enabled later return { - content: [{ - type: 'text', - text: `Premium data for "${query}": ${results} results found.` - }] + content: [ + { + type: 'text', + text: `Secure data: ${message || 'No message provided'}`, + } + ], }; } ); @@ -47,91 +42,89 @@ function createMcpServer(): McpServer { return server; } -// Main server setup -async function main() { - console.log('Starting X402 Example Server...'); - - if (!recipientAddress) { - console.error('ATXP_DESTINATION environment variable is required!'); - process.exit(1); - } - - const app = express(); - - // IMPORTANT: Parse JSON before X402 middleware - app.use(express.json()); - - // Setup X402 payment middleware - /*app.use(paymentMiddleware( - recipientAddress, - { - "POST /": { price: "$0.01", network } - }, - process.env.CDP_API_KEY_ID ? facilitator : { url: "https://x402.org/facilitator" } - ));*/ - - // MCP endpoint handler - app.post('/', async (req: Request, res: Response) => { - console.log('Received POST request'); - - const server = createMcpServer(); - - try { - const transport = new StreamableHTTPServerTransport({ - sessionIdGenerator: undefined, - enableJsonResponse: true - }); - - await server.connect(transport); - - // Pass the parsed body from express.json() - await transport.handleRequest(req, res, req.body); - - res.on('close', () => { - transport.close(); - server.close(); +const app = express(); +app.use(express.json()); + +const destinationAddress = process.env.ATXP_DESTINATION!; +const destination = new ChainPaymentDestination(destinationAddress, 'base'); +console.log('Starting MCP server with destination', destinationAddress); +app.use(atxpExpress({ + paymentDestination: destination, + resource: `http://localhost:${PORT}`, + //server: 'http://localhost:3010', + server: 'https://auth.atxp.ai', + mountPath: '/', + payeeName: 'ATXP Client Example Resource Server', + allowHttp: true, + logger: new ConsoleLogger({level: LogLevel.DEBUG}) +})); + + +app.post('/', async (req: Request, res: Response) => { + const server = getServer(); + try { + const transport: StreamableHTTPServerTransport = new StreamableHTTPServerTransport({ + sessionIdGenerator: undefined, + enableJsonResponse: true + }); + await server.connect(transport); + await transport.handleRequest(req, res, req.body); + res.on('close', () => { + console.log('Request closed'); + transport.close(); + server.close(); + }); + } catch (error) { + console.error('Error handling MCP request:', error); + if (!res.headersSent) { + res.status(500).json({ + jsonrpc: '2.0', + error: { + code: -32603, + message: 'Internal server error', + }, + id: null, }); - - } catch (error) { - console.error('Error handling MCP request:', error); - - if (!res.headersSent) { - res.status(500).json({ - jsonrpc: '2.0', - error: { - code: -32603, - message: 'Internal server error', - }, - id: null, - }); - } } - }); - - // Handle GET requests - app.get('/', async (req: Request, res: Response) => { - console.log('Received GET request'); - res.status(200).json({ - message: 'X402 MCP Server is running', - price: '$0.01 USDC per POST request', - network - }); - }); - - const server = app.listen(PORT, () => { - console.log(`X402 MCP Server running on http://localhost:${PORT}`); - console.log(`Payment: $0.01 USDC per request on ${network}`); - console.log(`Recipient: ${recipientAddress}`); - }); + } +}); + +app.get('/', async (req: Request, res: Response) => { + console.log('Received GET MCP request'); + res.writeHead(405).end(JSON.stringify({ + jsonrpc: "2.0", + error: { + code: -32000, + message: "Method not allowed." + }, + id: null + })); +}); + +app.delete('/', async (req: Request, res: Response) => { + console.log('Received DELETE MCP request'); + res.writeHead(405).end(JSON.stringify({ + jsonrpc: "2.0", + error: { + code: -32000, + message: "Method not allowed." + }, + id: null + })); +}); - // Graceful shutdown handling - process.on('SIGINT', () => { - console.log('\nShutting down server...'); - server.close(() => { - console.log('Server closed'); - process.exit(0); - }); - }); -} -main().catch(console.error); \ No newline at end of file +// Start the server +app.listen(PORT, (error) => { + if (error) { + console.error('Failed to start server:', error); + process.exit(1); + } + console.log(`MCP Stateless Streamable HTTP Server listening on port ${PORT}`); +}); + +// Handle server shutdown +process.on('SIGINT', async () => { + console.log('Shutting down server...'); + process.exit(0); +}); \ No newline at end of file diff --git a/examples/x402/src/test-client.ts b/examples/x402/src/test-client.ts index d5b2e094..2cbcab71 100644 --- a/examples/x402/src/test-client.ts +++ b/examples/x402/src/test-client.ts @@ -13,44 +13,25 @@ dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); async function main() { const serverUrl = process.env.X402_SERVER_URL || "http://localhost:3001"; - console.log("X402 MCP Client Example"); + console.log("X402 Test Client (without payments)"); console.log(`Server: ${serverUrl}`); - // Create account - const account = new BaseAccount( - process.env.BASE_RPC!, - process.env.BASE_PRIVATE_KEY! as `0x${string}` - ); - - // Create config - const config = { + //const account = new ATXPAccount(process.env.ATXP_CONNECTION_STRING!); + const account = new BaseAccount(process.env.BASE_RPC!, process.env.BASE_PRIVATE_KEY! as `0x${string}`); + const mcpClient = await atxpClient({ mcpServer: serverUrl, account, - logger: new ConsoleLogger({ prefix: '[X402]', level: LogLevel.DEBUG }), - approvePayment: async () => { - console.log(`Auto-approving X402 payment...`); - return true; - } - }; - - // Create client with X402 wrapper for payment support - const client = await atxpClient({ - ...config, - //fetchFn: wrapWithX402(config) + allowedAuthorizationServers: ['http://localhost:3010', 'https://auth.atxp.ai', 'https://atxp-accounts-staging.onrender.com/'], + allowHttp: true, + logger: new ConsoleLogger({level: LogLevel.DEBUG}) }); + const res = await mcpClient.callTool({ + name: "secure-data", + arguments: { message: "blockchain metrics" } + }); + + console.log('Result:', res); - try { - // Call the tool - will trigger X402 payment - console.log("\nCalling tool 'get_data'..."); - const result = await client.callTool("get_data", { query: "blockchain metrics" }); - - console.log(`\nResult: ${result.content[0].text}`); - console.log("\nSuccess!"); - } catch (error) { - console.error("Error:", error); - } finally { - await client.close(); - } } main().catch(console.error); \ No newline at end of file From 981ebe9cf1c91b34ccba0db9f0bbb31aa05e7340 Mon Sep 17 00:00:00 2001 From: bdj Date: Fri, 19 Sep 2025 11:26:14 -0700 Subject: [PATCH 49/61] Manually fix test-client --- examples/x402/src/server.ts | 23 ++++++++--------------- examples/x402/src/test-client.ts | 14 +++++++++----- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/examples/x402/src/server.ts b/examples/x402/src/server.ts index f147cb4c..f79bee87 100644 --- a/examples/x402/src/server.ts +++ b/examples/x402/src/server.ts @@ -4,11 +4,14 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'; import { z } from 'zod'; import { CallToolResult } from '@modelcontextprotocol/sdk/types.js'; -import { BigNumber } from 'bignumber.js'; -import { requirePayment, ChainPaymentDestination } from '@atxp/server'; -import { atxpExpress } from '@atxp/express'; -import { ConsoleLogger, LogLevel } from '@atxp/common'; -import 'dotenv/config'; +import { ChainPaymentDestination } from '@atxp/server'; +import dotenv from "dotenv"; +import path from "path"; +import { fileURLToPath } from 'url'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +dotenv.config(); +dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); const PORT = 3001; @@ -48,16 +51,6 @@ app.use(express.json()); const destinationAddress = process.env.ATXP_DESTINATION!; const destination = new ChainPaymentDestination(destinationAddress, 'base'); console.log('Starting MCP server with destination', destinationAddress); -app.use(atxpExpress({ - paymentDestination: destination, - resource: `http://localhost:${PORT}`, - //server: 'http://localhost:3010', - server: 'https://auth.atxp.ai', - mountPath: '/', - payeeName: 'ATXP Client Example Resource Server', - allowHttp: true, - logger: new ConsoleLogger({level: LogLevel.DEBUG}) -})); app.post('/', async (req: Request, res: Response) => { diff --git a/examples/x402/src/test-client.ts b/examples/x402/src/test-client.ts index 2cbcab71..42de91e3 100644 --- a/examples/x402/src/test-client.ts +++ b/examples/x402/src/test-client.ts @@ -18,12 +18,16 @@ async function main() { //const account = new ATXPAccount(process.env.ATXP_CONNECTION_STRING!); const account = new BaseAccount(process.env.BASE_RPC!, process.env.BASE_PRIVATE_KEY! as `0x${string}`); - const mcpClient = await atxpClient({ + const config = { + account, + logger: new ConsoleLogger({level: LogLevel.DEBUG}), mcpServer: serverUrl, - account, - allowedAuthorizationServers: ['http://localhost:3010', 'https://auth.atxp.ai', 'https://atxp-accounts-staging.onrender.com/'], - allowHttp: true, - logger: new ConsoleLogger({level: LogLevel.DEBUG}) + allowHttp: true + }; + const mcpClient = await atxpClient({ + ...config, + fetchFn: wrapWithX402(config) + }); const res = await mcpClient.callTool({ name: "secure-data", From 1009f33739140358d740cfca3ab2c023ce58bbf1 Mon Sep 17 00:00:00 2001 From: bdj Date: Fri, 19 Sep 2025 11:35:06 -0700 Subject: [PATCH 50/61] Fix example --- examples/x402/src/server.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/examples/x402/src/server.ts b/examples/x402/src/server.ts index f79bee87..08a1fa1d 100644 --- a/examples/x402/src/server.ts +++ b/examples/x402/src/server.ts @@ -4,7 +4,8 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'; import { z } from 'zod'; import { CallToolResult } from '@modelcontextprotocol/sdk/types.js'; -import { ChainPaymentDestination } from '@atxp/server'; +import { paymentMiddleware } from 'x402-express'; +import { facilitator } from '@coinbase/x402'; import dotenv from "dotenv"; import path from "path"; import { fileURLToPath } from 'url'; @@ -30,7 +31,7 @@ const getServer = () => { message: z.string().optional().describe('Message to secure'), }, async ({ message }: { message?: string }): Promise => { - // await requirePayment({price: BigNumber(0.01)}); // Will be enabled later + // X402 payment will be enforced by middleware return { content: [ { @@ -49,9 +50,16 @@ const app = express(); app.use(express.json()); const destinationAddress = process.env.ATXP_DESTINATION!; -const destination = new ChainPaymentDestination(destinationAddress, 'base'); +const network = 'base'; console.log('Starting MCP server with destination', destinationAddress); +// Add X402 payment middleware +app.use(paymentMiddleware( + destinationAddress, + { "POST /*": { price: "$0.01", network } }, + process.env.CDP_API_KEY_ID ? facilitator : { url: "https://x402.org/facilitator" } +)); + app.post('/', async (req: Request, res: Response) => { const server = getServer(); From 0f5a846ddfe51503b1d83bcd1db7053757849012 Mon Sep 17 00:00:00 2001 From: bdj Date: Fri, 19 Sep 2025 11:42:09 -0700 Subject: [PATCH 51/61] Cleanup, lint --- examples/x402/.env.example | 26 ------ examples/x402/README.md | 110 -------------------------- packages/atxp-x402/src/x402Wrapper.ts | 2 +- 3 files changed, 1 insertion(+), 137 deletions(-) delete mode 100644 examples/x402/.env.example delete mode 100644 examples/x402/README.md diff --git a/examples/x402/.env.example b/examples/x402/.env.example deleted file mode 100644 index 110a2629..00000000 --- a/examples/x402/.env.example +++ /dev/null @@ -1,26 +0,0 @@ -# Required: Your wallet address to receive payments (must start with 0x) -ATXP_DESTINATION=0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb8 - -# Network Configuration -# Options: "mainnet" (uses CDP facilitator) or leave empty for testnet -NETWORK= - -# Coinbase Developer Platform (CDP) API Keys (ONLY needed for mainnet) -# Get these from https://portal.cdp.coinbase.com/ -# Leave empty to use the public test facilitator on Base Sepolia -CDP_API_KEY_ID= -CDP_API_KEY_SECRET= - -# Base network RPC URL (for the test client) -# You can get one from https://www.alchemy.com/ or https://www.infura.io/ -BASE_RPC_URL=https://base-mainnet.g.alchemy.com/v2/your-api-key - -# Private key for the Base account (without 0x prefix) - for test client -# WARNING: Never commit real private keys to version control -BASE_PRIVATE_KEY=your_private_key_here - -# Optional: Server port (defaults to 3001) -PORT=3001 - -# Optional: X402 server URL for test client (defaults to http://localhost:3001) -X402_SERVER_URL=http://localhost:3001 \ No newline at end of file diff --git a/examples/x402/README.md b/examples/x402/README.md deleted file mode 100644 index 765f0f13..00000000 --- a/examples/x402/README.md +++ /dev/null @@ -1,110 +0,0 @@ -# X402 Server Example - -This example demonstrates X402 payment protocol with ATXP SDK. You can test it immediately using the **public test facilitator** - no API keys required! - -## Quick Start (Testnet - No API Keys!) - -### 1. Install and Configure -```bash -npm install -cp .env.example .env -# Edit .env - set your RECIPIENT_ADDRESS -``` - -### 2. Get Test USDC -Get free test USDC on Base Sepolia from: -- [Circle USDC Faucet](https://faucet.circle.com/) (recommended) -- Or any Base Sepolia faucet for ETH - -### 3. Run Server -```bash -npm run dev -``` - -The server automatically uses the **public test facilitator** at `https://x402.org/facilitator` - no login or API keys needed! - -### 4. Test Client -```bash -# In another terminal -npm run test-client -``` - -## Configuration Options - -### Testnet Mode (Default - No API Keys!) -```env -NETWORK=base-sepolia -RECIPIENT_ADDRESS=0xYourWalletAddress -# No CDP keys needed! Uses public facilitator -``` - -### Production Mode (Real Money) -```env -NETWORK=base -CDP_API_KEY_ID=your_key_id # Get from cdp.coinbase.com -CDP_API_KEY_SECRET=your_key_secret # Get from cdp.coinbase.com -RECIPIENT_ADDRESS=0xYourWalletAddress -``` - -## How It Works - -1. Server uses X402 middleware to protect endpoints -2. Client requests protected resource -3. Server returns 402 Payment Required -4. Client signs payment and retries -5. Facilitator verifies and settles on blockchain -6. Server returns protected resource - -## Facilitator Options - -| Mode | Network | Facilitator | API Keys | Real Money | -|------|---------|------------|----------|------------| -| **Test** (default) | Base Sepolia | `https://x402.org/facilitator` | ❌ None | ❌ Test USDC | -| Production | Base Mainnet | Coinbase CDP | ✅ Required | ✅ Real USDC | - -## Server Code - -The entire X402 integration is just one middleware line: - -```typescript -app.use(paymentMiddleware( - recipientAddress, - { '/api/resource': { price: '$0.01', network: 'base-sepolia' } }, - { url: 'https://x402.org/facilitator' } // Public test facilitator -)); -``` - -## Client Code - -The ATXP SDK handles X402 automatically: - -```typescript -import { wrapWithX402 } from '@atxp/x402'; - -const x402Fetch = wrapWithX402({ account, fetchFn: fetch }); -const response = await x402Fetch('http://localhost:3001/api/resource'); -``` - -## Cost Structure - -- **Testnet**: Free (test USDC) -- **Mainnet**: Resource price + ~$0.001 gas (Base has very low fees) - -## Troubleshooting - -### "No payment maker found" -Ensure your account is configured for the correct network (base-sepolia for testnet). - -### "Insufficient balance" -Get test USDC from the Circle faucet for Base Sepolia. - -### View Transactions -- **Testnet**: [Base Sepolia Explorer](https://sepolia.basescan.org) -- **Mainnet**: [BaseScan](https://basescan.org) - -## Resources - -- [X402 Protocol](https://github.com/coinbase/x402) -- [Circle USDC Faucet](https://faucet.circle.com/) -- [Base Sepolia Info](https://docs.base.org/network-information) -- [ATXP Documentation](https://docs.atxp.ai/) \ No newline at end of file diff --git a/packages/atxp-x402/src/x402Wrapper.ts b/packages/atxp-x402/src/x402Wrapper.ts index 046d1329..494d4094 100644 --- a/packages/atxp-x402/src/x402Wrapper.ts +++ b/packages/atxp-x402/src/x402Wrapper.ts @@ -194,7 +194,7 @@ export const wrapWithX402: FetchWrapper = (config: ClientArgs): FetchLike => { log.error(`Failed to handle X402 payment challenge: ${error}`); if (onPaymentFailure && isX402Challenge(paymentChallenge) && paymentChallenge.accepts && Array.isArray(paymentChallenge.accepts) && paymentChallenge.accepts[0]) { - const firstOption = paymentChallenge.accepts[0] as any; + const firstOption = paymentChallenge.accepts[0] as { maxAmountRequired?: string | number; description?: string; network?: string; payTo?: string }; const amount = firstOption.maxAmountRequired ? Number(firstOption.maxAmountRequired) / (10 ** 6) : 0; const url = typeof input === 'string' ? input : input.toString(); await onPaymentFailure({ From 37f34ff822854bdc807c5f1c439abbcf448a1790 Mon Sep 17 00:00:00 2001 From: bdj Date: Fri, 19 Sep 2025 11:50:17 -0700 Subject: [PATCH 52/61] Fix tests --- packages/atxp-x402/src/x402Wrapper.test.ts | 149 ++++++++++----------- 1 file changed, 68 insertions(+), 81 deletions(-) diff --git a/packages/atxp-x402/src/x402Wrapper.test.ts b/packages/atxp-x402/src/x402Wrapper.test.ts index d0b27cde..49a4b387 100644 --- a/packages/atxp-x402/src/x402Wrapper.test.ts +++ b/packages/atxp-x402/src/x402Wrapper.test.ts @@ -1,8 +1,16 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { describe, it, expect, vi, beforeEach, Mock } from 'vitest'; import { wrapWithX402 } from './x402Wrapper.js'; import { BaseAccount } from '@atxp/client'; import { ConsoleLogger, LogLevel } from '@atxp/common'; +vi.mock('x402/client', () => ({ + createPaymentHeader: vi.fn().mockResolvedValue('mocked-payment-header'), + selectPaymentRequirements: vi.fn((accepts, network) => { + // Return the first accept that matches the network, or null + return accepts.find((a: any) => a.network === network) || null; + }) +})); + describe('wrapWithX402', () => { let mockAccount: BaseAccount; let mockFetch: ReturnType; @@ -19,6 +27,13 @@ describe('wrapWithX402', () => { getSigner: vi.fn().mockResolvedValue({ address: '0x1234567890123456789012345678901234567890', signTypedData: vi.fn().mockResolvedValue('0xmockedsignature'), + account: { + address: '0x1234567890123456789012345678901234567890', + }, + chain: { + id: 8453, + }, + transport: {}, }), } as unknown as BaseAccount; @@ -52,30 +67,24 @@ describe('wrapWithX402', () => { }); it('should handle 402 responses and retry with payment', async () => { - // First response: 402 with X402 challenge + // First response: 402 with X402 challenge in JSON body const x402Challenge = { - version: 0, - created_at: Date.now(), - expires_at: Date.now() + 60000, - request_nonce: 'test-nonce', - chain_id: 8453, - currency: 'USDC', - amount: '1000000', - recipient: '0xrecipient', - memo: 'Test payment', - receipt_url: 'https://example.com/receipt', + x402Version: 1, accepts: [ { - type: 'transferWithAuthorization', - required: ['signature', 'authorization'], + network: 'base', + scheme: 'exact', + payTo: '0xrecipient', + maxAmountRequired: '1000000', + description: 'Test payment', }, ], }; - const first402Response = new Response('Payment Required', { + const first402Response = new Response(JSON.stringify(x402Challenge), { status: 402, headers: { - 'X-402': btoa(JSON.stringify(x402Challenge)), + 'Content-Type': 'application/json', }, }); @@ -83,7 +92,7 @@ describe('wrapWithX402', () => { const successResponse = new Response('Success', { status: 200, headers: { - 'X-Payment-Response': btoa(JSON.stringify({ receipt: 'test-receipt' })), + 'X-PAYMENT-RESPONSE': JSON.stringify({ receipt: 'test-receipt' }), }, }); @@ -115,9 +124,9 @@ describe('wrapWithX402', () => { // Should have called approve payment expect(mockApprovePayment).toHaveBeenCalledWith( expect.objectContaining({ - amount: '1000000', + amount: expect.objectContaining({ toNumber: expect.any(Function) }), currency: 'USDC', - recipient: '0xrecipient', + iss: '0xrecipient', }) ); @@ -125,7 +134,7 @@ describe('wrapWithX402', () => { expect(mockOnPayment).toHaveBeenCalledWith( expect.objectContaining({ payment: expect.objectContaining({ - amount: '1000000', + amount: expect.objectContaining({ toNumber: expect.any(Function) }), currency: 'USDC', }), }) @@ -134,38 +143,32 @@ describe('wrapWithX402', () => { // Should have made two fetch calls expect(mockFetch).toHaveBeenCalledTimes(2); - // Second call should include X-Payment header + // Second call should include X-PAYMENT header expect(mockFetch).toHaveBeenNthCalledWith(2, 'https://example.com/api', { method: 'POST', body: 'test-body', - headers: expect.objectContaining({ - 'X-Payment': expect.any(String), - }), + headers: expect.any(Headers), }); }); it('should handle payment approval rejection', async () => { const x402Challenge = { - version: 0, - created_at: Date.now(), - expires_at: Date.now() + 60000, - request_nonce: 'test-nonce', - chain_id: 8453, - currency: 'USDC', - amount: '1000000', - recipient: '0xrecipient', + x402Version: 1, accepts: [ { - type: 'transferWithAuthorization', - required: ['signature', 'authorization'], + network: 'base', + scheme: 'exact', + payTo: '0xrecipient', + maxAmountRequired: '1000000', + description: 'Test payment', }, ], }; - const response402 = new Response('Payment Required', { + const response402 = new Response(JSON.stringify(x402Challenge), { status: 402, headers: { - 'X-402': btoa(JSON.stringify(x402Challenge)), + 'Content-Type': 'application/json', }, }); @@ -196,7 +199,7 @@ describe('wrapWithX402', () => { expect(mockOnPaymentFailure).toHaveBeenCalledWith( expect.objectContaining({ error: expect.objectContaining({ - message: expect.stringContaining('User rejected payment'), + message: expect.stringContaining('Payment not approved'), }), }) ); @@ -205,10 +208,10 @@ describe('wrapWithX402', () => { expect(mockFetch).toHaveBeenCalledTimes(1); }); - it('should handle missing X-402 header on 402 response', async () => { + it('should handle missing X402 JSON body on 402 response', async () => { const response402 = new Response('Payment Required', { status: 402, - // No X-402 header + // No JSON body with x402Version }); mockFetch.mockResolvedValue(response402); @@ -233,26 +236,22 @@ describe('wrapWithX402', () => { it('should handle x402 library errors', async () => { const x402Challenge = { - version: 0, - created_at: Date.now(), - expires_at: Date.now() + 60000, - request_nonce: 'test-nonce', - chain_id: 8453, - currency: 'USDC', - amount: '1000000', - recipient: '0xrecipient', + x402Version: 1, accepts: [ { - type: 'transferWithAuthorization', - required: ['signature', 'authorization'], + network: 'base', + scheme: 'exact', + payTo: '0xrecipient', + maxAmountRequired: '1000000', + description: 'Test payment', }, ], }; - const response402 = new Response('Payment Required', { + const response402 = new Response(JSON.stringify(x402Challenge), { status: 402, headers: { - 'X-402': btoa(JSON.stringify(x402Challenge)), + 'Content-Type': 'application/json', }, }); @@ -288,42 +287,36 @@ describe('wrapWithX402', () => { expect(mockFetch).toHaveBeenCalledTimes(1); }); - it('should handle wrong network account', async () => { - // Account on wrong network - const wrongNetworkAccount = { - accountId: '0x1234567890123456789012345678901234567890', - network: 'solana', // Not base - getSigner: vi.fn(), - } as unknown as BaseAccount; + it('should handle no suitable payment option', async () => { + // Mock selectPaymentRequirements to return null for unsupported network + const { selectPaymentRequirements } = await import('x402/client'); + (selectPaymentRequirements as Mock).mockReturnValueOnce(null); + // X402 challenge with unsupported network const x402Challenge = { - version: 0, - created_at: Date.now(), - expires_at: Date.now() + 60000, - request_nonce: 'test-nonce', - chain_id: 8453, // Base mainnet - currency: 'USDC', - amount: '1000000', - recipient: '0xrecipient', + x402Version: 1, accepts: [ { - type: 'transferWithAuthorization', - required: ['signature', 'authorization'], + network: 'ethereum', // Not base + scheme: 'exact', + payTo: '0xrecipient', + maxAmountRequired: '1000000', + description: 'Test payment', }, ], }; - const response402 = new Response('Payment Required', { + const response402 = new Response(JSON.stringify(x402Challenge), { status: 402, headers: { - 'X-402': btoa(JSON.stringify(x402Challenge)), + 'Content-Type': 'application/json', }, }); mockFetch.mockResolvedValue(response402); const wrappedFetch = wrapWithX402({ - account: wrongNetworkAccount, + account: mockAccount, fetchFn: mockFetch, logger: mockLogger, onPaymentFailure: mockOnPaymentFailure, @@ -334,16 +327,10 @@ describe('wrapWithX402', () => { // Should return the original 402 response expect(result.status).toBe(402); - // Should not have tried to get signer - expect(wrongNetworkAccount.getSigner).not.toHaveBeenCalled(); + // Should not have tried to get signer since no suitable payment option + expect(mockAccount.getSigner).not.toHaveBeenCalled(); - // Should have called onPaymentFailure with network mismatch error - expect(mockOnPaymentFailure).toHaveBeenCalledWith( - expect.objectContaining({ - error: expect.objectContaining({ - message: expect.stringContaining('network'), - }), - }) - ); + // Should not have called onPaymentFailure (just returns original 402) + expect(mockOnPaymentFailure).not.toHaveBeenCalled(); }); }); \ No newline at end of file From ddb2cd682be3e5c5f4656aaf226d0effa720b3ab Mon Sep 17 00:00:00 2001 From: bdj Date: Fri, 19 Sep 2025 11:54:30 -0700 Subject: [PATCH 53/61] Re-export class to fix tests --- packages/atxp-client/src/atxpFetcher.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/atxp-client/src/atxpFetcher.ts b/packages/atxp-client/src/atxpFetcher.ts index 624cbe05..6c99b3b0 100644 --- a/packages/atxp-client/src/atxpFetcher.ts +++ b/packages/atxp-client/src/atxpFetcher.ts @@ -32,7 +32,7 @@ export function atxpFetch(config: ClientConfig): FetchLike { return fetcher.fetch; } -class ATXPFetcher { +export class ATXPFetcher { protected oauthClient: OAuthClient; protected paymentMakers: Map; protected sideChannelFetch: FetchLike; From a0edf4a0fafe788f2064c3e94a7bd4a82d2ed2a2 Mon Sep 17 00:00:00 2001 From: bdj Date: Fri, 19 Sep 2025 14:36:20 -0700 Subject: [PATCH 54/61] atxpLocalAccount --- examples/x402/src/test-client.ts | 6 +- packages/atxp-client/src/atxpAccount.ts | 28 +---- packages/atxp-client/src/atxpLocalAccount.ts | 124 +++++++++++++++++++ packages/atxp-client/src/index.ts | 4 +- packages/atxp-client/src/remoteSigner.ts | 75 ----------- packages/atxp-x402/src/x402Wrapper.ts | 33 ++++- 6 files changed, 166 insertions(+), 104 deletions(-) create mode 100644 packages/atxp-client/src/atxpLocalAccount.ts delete mode 100644 packages/atxp-client/src/remoteSigner.ts diff --git a/examples/x402/src/test-client.ts b/examples/x402/src/test-client.ts index 42de91e3..923dc291 100644 --- a/examples/x402/src/test-client.ts +++ b/examples/x402/src/test-client.ts @@ -1,5 +1,5 @@ #!/usr/bin/env node -import { atxpClient, BaseAccount } from "@atxp/client"; +import { atxpClient, ATXPAccount } from "@atxp/client"; import { wrapWithX402 } from "@atxp/x402"; import { ConsoleLogger, LogLevel } from '@atxp/common'; import dotenv from "dotenv"; @@ -16,8 +16,8 @@ async function main() { console.log("X402 Test Client (without payments)"); console.log(`Server: ${serverUrl}`); - //const account = new ATXPAccount(process.env.ATXP_CONNECTION_STRING!); - const account = new BaseAccount(process.env.BASE_RPC!, process.env.BASE_PRIVATE_KEY! as `0x${string}`); + const account = new ATXPAccount(process.env.ATXP_CONNECTION_STRING!); + //const account = new BaseAccount(process.env.BASE_RPC!, process.env.BASE_PRIVATE_KEY! as `0x${string}`); const config = { account, logger: new ConsoleLogger({level: LogLevel.DEBUG}), diff --git a/packages/atxp-client/src/atxpAccount.ts b/packages/atxp-client/src/atxpAccount.ts index 86cda909..8d212ea1 100644 --- a/packages/atxp-client/src/atxpAccount.ts +++ b/packages/atxp-client/src/atxpAccount.ts @@ -2,7 +2,7 @@ import type { Account, PaymentMaker } from './types.js'; import type { FetchLike, Network, Currency } from '@atxp/common' import BigNumber from 'bignumber.js'; import { LocalAccount } from 'viem'; -import { RemoteSigner } from './remoteSigner.js'; +import { ATXPLocalAccount } from './atxpLocalAccount.js'; function toBasicAuth(token: string): string { // Basic auth is base64("username:password"), password is blank @@ -87,9 +87,9 @@ class ATXPHttpPaymentMaker implements PaymentMaker { export class ATXPAccount implements Account { accountId: string; paymentMakers: { [key: string]: PaymentMaker }; - private origin: string; - private token: string; - private fetchFn: FetchLike; + origin: string; + token: string; + fetchFn: FetchLike; constructor(connectionString: string, opts?: { fetchFn?: FetchLike; network?: Network }) { const { origin, token } = parseConnectionString(connectionString); @@ -109,26 +109,8 @@ export class ATXPAccount implements Account { } - /** - * Get a signer that can be used with the x402 library - * This uses RemoteSigner to delegate signing to the accounts-x402 server - */ async getSigner(): Promise { - // Get the wallet address from the destination endpoint - const response = await this.fetchFn(`${this.origin}/destination`, { - headers: { - 'Authorization': toBasicAuth(this.token) - } - }); - - if (!response.ok) { - throw new Error(`ATXPAccount: Failed to get wallet address: ${response.status} ${response.statusText}`); - } - - const { destination } = await response.json() as { destination: string }; - - return new RemoteSigner( - destination as `0x${string}`, + return ATXPLocalAccount.create( this.origin, this.token, this.fetchFn diff --git a/packages/atxp-client/src/atxpLocalAccount.ts b/packages/atxp-client/src/atxpLocalAccount.ts new file mode 100644 index 00000000..203a8aa2 --- /dev/null +++ b/packages/atxp-client/src/atxpLocalAccount.ts @@ -0,0 +1,124 @@ +import { Hex, Address, LocalAccount, SignableMessage, TypedData, TransactionSerializable } from 'viem'; +import { FetchLike } from '@atxp/common'; + +function toBasicAuth(token: string): string { + // Basic auth is base64("username:password"), password is blank + const b64 = Buffer.from(`${token}:`).toString('base64'); + return `Basic ${b64}`; +} + +/** + * ATXP implementation of viem's LocalAccount interface. + * Delegates signing operations to the accounts-x402 API. + * Includes properties needed by x402 library for wallet client compatibility. + */ +export class ATXPLocalAccount implements LocalAccount { + public readonly type = 'local' as const; + + // Properties needed by x402 library's isSignerWallet check + public readonly account: LocalAccount; + public readonly chain: { id: number }; + public readonly transport: {}; + + constructor( + public readonly address: Address, + private origin: string, + private token: string, + private fetchFn: FetchLike = fetch as FetchLike + ) { + // x402 library expects these properties for wallet client compatibility + this.account = this; // Self-reference for x402's isSignerWallet check + this.chain = { id: 8453 }; // Base mainnet - could make this configurable + this.transport = {}; // Empty transport object for x402 compatibility + } + + /** + * Fetch the wallet address from the /address endpoint + */ + static async create( + origin: string, + token: string, + fetchFn: FetchLike = fetch as FetchLike + ): Promise { + // The /address endpoint uses Basic auth like other authenticated endpoints + const response = await fetchFn(`${origin}/address`, { + method: 'GET', + headers: { + 'Authorization': toBasicAuth(token) + } + }); + + if (!response.ok) { + const errorText = await response.text(); + throw new Error(`Failed to fetch destination address: ${response.status} ${response.statusText} ${errorText}`); + } + + const data = await response.json() as { address?: string; chainType?: string }; + const address = data.address; + if (!address) { + throw new Error('Address endpoint did not return an address'); + } + + // Check that the account is an Ethereum account (required for X402/EVM operations) + if (!data.chainType) { + throw new Error('Address endpoint did not return a chainType'); + } + if (data.chainType !== 'ethereum') { + throw new Error(`ATXPLocalAccount requires an Ethereum account, but got ${data.chainType} account`); + } + + return new ATXPLocalAccount(address as Address, origin, token, fetchFn); + } + + /** + * Sign a typed data structure using EIP-712 + * This is what x402 library will call for EIP-3009 authorization + */ + async signTypedData< + const TTypedData extends TypedData | { [key: string]: unknown } + >(typedData: TTypedData): Promise { + const response = await this.fetchFn(`${this.origin}/sign-typed-data`, { + method: 'POST', + headers: { + 'Authorization': toBasicAuth(this.token), + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + typedData + }) + }); + + if (!response.ok) { + const errorText = await response.text(); + throw new Error(`Failed to sign typed data: ${response.status} ${response.statusText} ${errorText}`); + } + + const result = await response.json(); + return result.signature as Hex; + } + + /** + * Sign a message - required by LocalAccount interface but not used for X402 + */ + async signMessage(_: { message: SignableMessage }): Promise { + throw new Error('Message signing not implemented for ATXP local account'); + } + + /** + * Sign a transaction - required by LocalAccount interface but not used for X402 + */ + async signTransaction(_transaction: TransactionSerializable, _args?: unknown): Promise { + throw new Error('Transaction signing not implemented for ATXP local account'); + } + + /** + * Get public key - required by LocalAccount interface + */ + readonly publicKey = '0x0000000000000000000000000000000000000000000000000000000000000000' as Hex; + + /** + * Source - required by LocalAccount interface (set to 'custom') + */ + readonly source = 'custom' as const; +} + diff --git a/packages/atxp-client/src/index.ts b/packages/atxp-client/src/index.ts index f906dab1..8dc91d77 100644 --- a/packages/atxp-client/src/index.ts +++ b/packages/atxp-client/src/index.ts @@ -60,5 +60,5 @@ export { } from './types.js'; export { - RemoteSigner -} from './remoteSigner.js'; + ATXPLocalAccount +} from './atxpLocalAccount.js'; diff --git a/packages/atxp-client/src/remoteSigner.ts b/packages/atxp-client/src/remoteSigner.ts deleted file mode 100644 index 5d654e79..00000000 --- a/packages/atxp-client/src/remoteSigner.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { Hex, Address, LocalAccount, SignableMessage, TypedData, TransactionSerializable } from 'viem'; -import { FetchLike } from '@atxp/common'; - -function toBasicAuth(token: string): string { - // Basic auth is base64("username:password"), password is blank - const b64 = Buffer.from(`${token}:`).toString('base64'); - return `Basic ${b64}`; -} - -/** - * Creates a remote signer that delegates signing operations to the accounts-x402 API. - * This implements the LocalAccount interface from viem to be compatible with x402-fetch. - */ -export class RemoteSigner implements LocalAccount { - public readonly type = 'local' as const; - - constructor( - public readonly address: Address, - private origin: string, - private token: string, - private fetchFn: FetchLike = fetch as FetchLike - ) {} - - /** - * Sign a typed data structure using EIP-712 - * This is what x402 library will call for EIP-3009 authorization - */ - async signTypedData< - const TTypedData extends TypedData | { [key: string]: unknown } - >(typedData: TTypedData): Promise { - const response = await this.fetchFn(`${this.origin}/sign-typed-data`, { - method: 'POST', - headers: { - 'Authorization': toBasicAuth(this.token), - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - typedData - }) - }); - - if (!response.ok) { - const errorText = await response.text(); - throw new Error(`Failed to sign typed data: ${response.status} ${response.statusText} ${errorText}`); - } - - const result = await response.json(); - return result.signature as Hex; - } - - /** - * Sign a message - required by LocalAccount interface but not used for X402 - */ - async signMessage(_: { message: SignableMessage }): Promise { - throw new Error('Message signing not implemented for remote signer'); - } - - /** - * Sign a transaction - required by LocalAccount interface but not used for X402 - */ - async signTransaction(_transaction: TransactionSerializable, _args?: unknown): Promise { - throw new Error('Transaction signing not implemented for remote signer'); - } - - /** - * Get public key - required by LocalAccount interface - */ - readonly publicKey = '0x0000000000000000000000000000000000000000000000000000000000000000' as Hex; - - /** - * Source - required by LocalAccount interface (set to 'custom') - */ - readonly source = 'custom' as const; -} - diff --git a/packages/atxp-x402/src/x402Wrapper.ts b/packages/atxp-x402/src/x402Wrapper.ts index 494d4094..afa3c029 100644 --- a/packages/atxp-x402/src/x402Wrapper.ts +++ b/packages/atxp-x402/src/x402Wrapper.ts @@ -129,7 +129,38 @@ export const wrapWithX402: FetchWrapper = (config: ClientArgs): FetchLike => { // Get the signer from the account log.debug('Getting signer from account'); - const signer: LocalAccount = await accountWithSigner.getSigner!(); + const signer = await accountWithSigner.getSigner!(); + + // Log the address we're paying from + log.info(`X402 payment will be made from address: ${signer.address}`); + + // If using ATXPAccount, ensure we have enough on-chain USDC by converting IOUs if needed + const atxpAccount = account as { origin?: string; token?: string; fetchFn?: FetchLike }; + if (atxpAccount.origin && atxpAccount.token) { + log.debug('Ensuring sufficient on-chain USDC for X402 payment'); + + // Call /ensure-currency to convert IOUs to USDC if needed + const ensureResponse = await (atxpAccount.fetchFn || fetchFn)(`${atxpAccount.origin}/ensure-currency`, { + method: 'POST', + headers: { + 'Authorization': `Basic ${Buffer.from(`${atxpAccount.token}:`).toString('base64')}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + amount: amountInUsdc.toString(), + currency: 'USDC' + }) + }); + + if (!ensureResponse.ok) { + const errorText = await ensureResponse.text(); + log.error(`Failed to ensure currency: ${errorText}`); + throw new Error(`Failed to ensure sufficient USDC: ${errorText}`); + } + + const ensureResult = await ensureResponse.json() as { message?: string; balance?: { usdc: string; iou: string } }; + log.info(`Currency ensured: ${ensureResult.message}, USDC: ${ensureResult.balance?.usdc}, IOU: ${ensureResult.balance?.iou}`); + } // Create the X402 payment header using the x402 library log.debug('Creating X402 payment header with signer'); From 7d8abe4c725d93acaf88bd16a9abd97f3e4c6aa2 Mon Sep 17 00:00:00 2001 From: bdj Date: Fri, 19 Sep 2025 15:06:41 -0700 Subject: [PATCH 55/61] Pass chainType to ensure-currency --- packages/atxp-x402/src/x402Wrapper.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/atxp-x402/src/x402Wrapper.ts b/packages/atxp-x402/src/x402Wrapper.ts index afa3c029..8c6bf3cd 100644 --- a/packages/atxp-x402/src/x402Wrapper.ts +++ b/packages/atxp-x402/src/x402Wrapper.ts @@ -148,7 +148,8 @@ export const wrapWithX402: FetchWrapper = (config: ClientArgs): FetchLike => { }, body: JSON.stringify({ amount: amountInUsdc.toString(), - currency: 'USDC' + currency: 'USDC', + chainType: 'ethereum' // X402 only works with Ethereum/Base }) }); From 566d9dc38396ac78af7852cec0bfc65013e00e70 Mon Sep 17 00:00:00 2001 From: bdj Date: Fri, 19 Sep 2025 15:10:57 -0700 Subject: [PATCH 56/61] Lint --- packages/atxp-client/src/atxpLocalAccount.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/atxp-client/src/atxpLocalAccount.ts b/packages/atxp-client/src/atxpLocalAccount.ts index 203a8aa2..78752e2e 100644 --- a/packages/atxp-client/src/atxpLocalAccount.ts +++ b/packages/atxp-client/src/atxpLocalAccount.ts @@ -18,7 +18,7 @@ export class ATXPLocalAccount implements LocalAccount { // Properties needed by x402 library's isSignerWallet check public readonly account: LocalAccount; public readonly chain: { id: number }; - public readonly transport: {}; + public readonly transport: object; constructor( public readonly address: Address, From 0e2e28e73f407cb58b23fe12855cfb8aba3f2f7c Mon Sep 17 00:00:00 2001 From: bdj Date: Fri, 19 Sep 2025 18:06:14 -0700 Subject: [PATCH 57/61] typecheck/lint/test --- package-lock.json | 87 +++++++++++++++++---------- packages/atxp-x402/package.json | 6 +- packages/atxp-x402/src/x402Wrapper.ts | 2 +- 3 files changed, 58 insertions(+), 37 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4d2dc172..471cad46 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6262,6 +6262,7 @@ }, "node_modules/@solana/buffer-layout": { "version": "4.0.1", + "dev": true, "license": "MIT", "dependencies": { "buffer": "~6.0.3" @@ -6272,6 +6273,7 @@ }, "node_modules/@solana/buffer-layout-utils": { "version": "0.2.0", + "dev": true, "license": "Apache-2.0", "dependencies": { "@solana/buffer-layout": "^4.0.0", @@ -6285,6 +6287,7 @@ }, "node_modules/@solana/codecs": { "version": "2.0.0-rc.1", + "dev": true, "license": "MIT", "dependencies": { "@solana/codecs-core": "2.0.0-rc.1", @@ -6299,6 +6302,7 @@ }, "node_modules/@solana/codecs-core": { "version": "2.0.0-rc.1", + "dev": true, "license": "MIT", "dependencies": { "@solana/errors": "2.0.0-rc.1" @@ -6309,6 +6313,7 @@ }, "node_modules/@solana/codecs-data-structures": { "version": "2.0.0-rc.1", + "dev": true, "license": "MIT", "dependencies": { "@solana/codecs-core": "2.0.0-rc.1", @@ -6321,6 +6326,7 @@ }, "node_modules/@solana/codecs-numbers": { "version": "2.0.0-rc.1", + "dev": true, "license": "MIT", "dependencies": { "@solana/codecs-core": "2.0.0-rc.1", @@ -6332,6 +6338,7 @@ }, "node_modules/@solana/codecs-strings": { "version": "2.0.0-rc.1", + "dev": true, "license": "MIT", "dependencies": { "@solana/codecs-core": "2.0.0-rc.1", @@ -6345,6 +6352,7 @@ }, "node_modules/@solana/errors": { "version": "2.0.0-rc.1", + "dev": true, "license": "MIT", "dependencies": { "chalk": "^5.3.0", @@ -6670,6 +6678,7 @@ }, "node_modules/@solana/options": { "version": "2.0.0-rc.1", + "dev": true, "license": "MIT", "dependencies": { "@solana/codecs-core": "2.0.0-rc.1", @@ -6684,6 +6693,7 @@ }, "node_modules/@solana/pay": { "version": "0.2.6", + "dev": true, "license": "Apache-2.0", "dependencies": { "@solana/qr-code-styling": "^1.6.0", @@ -6748,6 +6758,7 @@ }, "node_modules/@solana/qr-code-styling": { "version": "1.6.0", + "dev": true, "license": "MIT", "dependencies": { "qrcode-generator": "^1.4.3" @@ -7318,6 +7329,7 @@ }, "node_modules/@solana/spl-token": { "version": "0.4.13", + "dev": true, "license": "Apache-2.0", "dependencies": { "@solana/buffer-layout": "^4.0.0", @@ -7335,6 +7347,7 @@ }, "node_modules/@solana/spl-token-group": { "version": "0.0.7", + "dev": true, "license": "Apache-2.0", "dependencies": { "@solana/codecs": "2.0.0-rc.1" @@ -7348,6 +7361,7 @@ }, "node_modules/@solana/spl-token-metadata": { "version": "0.1.6", + "dev": true, "license": "Apache-2.0", "dependencies": { "@solana/codecs": "2.0.0-rc.1" @@ -7812,6 +7826,7 @@ }, "node_modules/@solana/web3.js": { "version": "1.98.2", + "dev": true, "license": "MIT", "dependencies": { "@babel/runtime": "^7.25.0", @@ -7833,6 +7848,7 @@ }, "node_modules/@solana/web3.js/node_modules/@solana/codecs-core": { "version": "2.1.0", + "dev": true, "license": "MIT", "dependencies": { "@solana/errors": "2.1.0" @@ -7846,6 +7862,7 @@ }, "node_modules/@solana/web3.js/node_modules/@solana/codecs-numbers": { "version": "2.1.0", + "dev": true, "license": "MIT", "dependencies": { "@solana/codecs-core": "2.1.0", @@ -7860,6 +7877,7 @@ }, "node_modules/@solana/web3.js/node_modules/@solana/errors": { "version": "2.1.0", + "dev": true, "license": "MIT", "dependencies": { "chalk": "^5.3.0", @@ -7877,6 +7895,7 @@ }, "node_modules/@solana/web3.js/node_modules/base-x": { "version": "3.0.11", + "dev": true, "license": "MIT", "dependencies": { "safe-buffer": "^5.0.1" @@ -7884,6 +7903,7 @@ }, "node_modules/@solana/web3.js/node_modules/bs58": { "version": "4.0.1", + "dev": true, "license": "MIT", "dependencies": { "base-x": "^3.0.2" @@ -7891,6 +7911,7 @@ }, "node_modules/@solana/web3.js/node_modules/commander": { "version": "13.1.0", + "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -7903,6 +7924,7 @@ }, "node_modules/@swc/helpers": { "version": "0.5.17", + "dev": true, "license": "Apache-2.0", "dependencies": { "tslib": "^2.8.0" @@ -7996,6 +8018,7 @@ }, "node_modules/@types/connect": { "version": "3.4.38", + "dev": true, "license": "MIT", "dependencies": { "@types/node": "*" @@ -8188,10 +8211,12 @@ }, "node_modules/@types/uuid": { "version": "8.3.4", + "dev": true, "license": "MIT" }, "node_modules/@types/ws": { "version": "7.4.7", + "dev": true, "license": "MIT", "dependencies": { "@types/node": "*" @@ -9323,6 +9348,7 @@ }, "node_modules/agentkeepalive": { "version": "4.6.0", + "dev": true, "license": "MIT", "dependencies": { "humanize-ms": "^1.2.1" @@ -9982,6 +10008,7 @@ }, "node_modules/bigint-buffer": { "version": "1.1.5", + "dev": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { @@ -10060,6 +10087,7 @@ }, "node_modules/borsh": { "version": "0.7.0", + "dev": true, "license": "Apache-2.0", "dependencies": { "bn.js": "^5.2.0", @@ -10069,6 +10097,7 @@ }, "node_modules/borsh/node_modules/base-x": { "version": "3.0.11", + "dev": true, "license": "MIT", "dependencies": { "safe-buffer": "^5.0.1" @@ -10076,6 +10105,7 @@ }, "node_modules/borsh/node_modules/bs58": { "version": "4.0.1", + "dev": true, "license": "MIT", "dependencies": { "base-x": "^3.0.2" @@ -11070,6 +11100,7 @@ }, "node_modules/delay": { "version": "5.0.0", + "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -11493,10 +11524,12 @@ }, "node_modules/es6-promise": { "version": "4.2.8", + "dev": true, "license": "MIT" }, "node_modules/es6-promisify": { "version": "5.0.0", + "dev": true, "license": "MIT", "dependencies": { "es6-promise": "^4.0.3" @@ -12502,6 +12535,7 @@ }, "node_modules/eyes": { "version": "0.1.8", + "dev": true, "engines": { "node": "> 0.1.90" } @@ -12558,6 +12592,7 @@ }, "node_modules/fast-stable-stringify": { "version": "1.0.0", + "dev": true, "license": "MIT" }, "node_modules/fastestsmallesttextencoderdecoder": { @@ -13238,6 +13273,7 @@ }, "node_modules/humanize-ms": { "version": "1.2.1", + "dev": true, "license": "MIT", "dependencies": { "ms": "^2.0.0" @@ -13834,6 +13870,7 @@ }, "node_modules/isomorphic-ws": { "version": "4.0.1", + "dev": true, "license": "MIT", "peerDependencies": { "ws": "*" @@ -13946,6 +13983,7 @@ }, "node_modules/jayson": { "version": "4.2.0", + "dev": true, "license": "MIT", "dependencies": { "@types/connect": "^3.4.33", @@ -13970,10 +14008,12 @@ }, "node_modules/jayson/node_modules/@types/node": { "version": "12.20.55", + "dev": true, "license": "MIT" }, "node_modules/jayson/node_modules/commander": { "version": "2.20.3", + "dev": true, "license": "MIT" }, "node_modules/jest-environment-node": { @@ -14443,6 +14483,7 @@ }, "node_modules/json-stringify-safe": { "version": "5.0.1", + "dev": true, "license": "ISC" }, "node_modules/json5": { @@ -16488,6 +16529,7 @@ }, "node_modules/qrcode-generator": { "version": "1.4.4", + "dev": true, "license": "MIT" }, "node_modules/qrcode-terminal": { @@ -16761,6 +16803,7 @@ }, "node_modules/react-native-url-polyfill": { "version": "2.0.0", + "dev": true, "license": "MIT", "dependencies": { "whatwg-url-without-unicode": "8.0.0-3" @@ -17285,6 +17328,7 @@ }, "node_modules/rpc-websockets": { "version": "9.1.1", + "dev": true, "license": "LGPL-3.0-only", "dependencies": { "@swc/helpers": "^0.5.11", @@ -17306,6 +17350,7 @@ }, "node_modules/rpc-websockets/node_modules/@types/ws": { "version": "8.18.1", + "dev": true, "license": "MIT", "dependencies": { "@types/node": "*" @@ -17313,6 +17358,7 @@ }, "node_modules/rpc-websockets/node_modules/ws": { "version": "8.18.2", + "dev": true, "license": "MIT", "engines": { "node": ">=10.0.0" @@ -17949,10 +17995,12 @@ }, "node_modules/stream-chain": { "version": "2.2.5", + "dev": true, "license": "BSD-3-Clause" }, "node_modules/stream-json": { "version": "1.9.1", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "stream-chain": "^2.2.5" @@ -18213,6 +18261,7 @@ }, "node_modules/superstruct": { "version": "2.0.2", + "dev": true, "license": "MIT", "engines": { "node": ">=14.0.0" @@ -18407,7 +18456,8 @@ } }, "node_modules/text-encoding-utf-8": { - "version": "1.0.2" + "version": "1.0.2", + "dev": true }, "node_modules/thenify": { "version": "3.3.1", @@ -20205,11 +20255,11 @@ }, "packages/atxp-x402": { "name": "@atxp/x402", - "version": "0.4.0", + "version": "0.5.1", "license": "MIT", "dependencies": { - "@atxp/client": "0.4.0", - "@atxp/common": "0.4.0", + "@atxp/client": "0.5.1", + "@atxp/common": "0.5.1", "bignumber.js": "^9.1.2", "viem": "^2.21.54", "x402": "^0.6.1" @@ -20222,35 +20272,6 @@ "typescript": "^5.7.3", "vitest": "^3.0.9" } - }, - "packages/atxp-x402/node_modules/@atxp/client": { - "version": "0.4.0", - "license": "MIT", - "dependencies": { - "@atxp/common": "0.4.0", - "@modelcontextprotocol/sdk": "^1.15.0", - "bignumber.js": "^9.3.0", - "oauth4webapi": "^3.5.0" - }, - "peerDependencies": { - "@solana/pay": "^0.2.5", - "@solana/web3.js": "^1.98.1", - "bs58": "^6.0.0", - "expo-crypto": ">=14.0.0", - "react-native-url-polyfill": "^2.0.0", - "viem": "^2.34.0" - } - }, - "packages/atxp-x402/node_modules/@atxp/common": { - "version": "0.4.0", - "license": "MIT", - "dependencies": { - "bignumber.js": "^9.3.0", - "jose": "^6.0.11", - "oauth4webapi": "^3.5.0", - "tweetnacl": "^1.0.3", - "tweetnacl-util": "^0.15.1" - } } } } diff --git a/packages/atxp-x402/package.json b/packages/atxp-x402/package.json index 2f3abcbf..ee67c744 100644 --- a/packages/atxp-x402/package.json +++ b/packages/atxp-x402/package.json @@ -1,6 +1,6 @@ { "name": "@atxp/x402", - "version": "0.4.0", + "version": "0.5.1", "description": "ATXP X402 - X402 protocol integration for ATXP SDK", "license": "MIT", "repository": { @@ -33,8 +33,8 @@ "pack:dry": "npm pack --dry-run" }, "dependencies": { - "@atxp/client": "0.4.0", - "@atxp/common": "0.4.0", + "@atxp/client": "0.5.1", + "@atxp/common": "0.5.1", "bignumber.js": "^9.1.2", "viem": "^2.21.54", "x402": "^0.6.1" diff --git a/packages/atxp-x402/src/x402Wrapper.ts b/packages/atxp-x402/src/x402Wrapper.ts index 8c6bf3cd..3133b4d3 100644 --- a/packages/atxp-x402/src/x402Wrapper.ts +++ b/packages/atxp-x402/src/x402Wrapper.ts @@ -1,4 +1,4 @@ -import { ProspectivePayment, FetchWrapper, ClientArgs } from '@atxp/client'; +import { ProspectivePayment, type FetchWrapper, type ClientArgs } from '@atxp/client'; import { FetchLike, Network } from '@atxp/common'; import { BigNumber } from 'bignumber.js'; import { createPaymentHeader, selectPaymentRequirements } from 'x402/client'; From 290f9bb202444682114c030c877b582d270f2361 Mon Sep 17 00:00:00 2001 From: bdj Date: Fri, 19 Sep 2025 18:15:07 -0700 Subject: [PATCH 58/61] Cleanup --- packages/atxp-client/src/atxpAccount.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/atxp-client/src/atxpAccount.ts b/packages/atxp-client/src/atxpAccount.ts index 8d212ea1..cc591844 100644 --- a/packages/atxp-client/src/atxpAccount.ts +++ b/packages/atxp-client/src/atxpAccount.ts @@ -31,7 +31,6 @@ class ATXPHttpPaymentMaker implements PaymentMaker { this.fetchFn = fetchFn; } - async makePayment(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise { // Make a regular payment via the /pay endpoint const response = await this.fetchFn(`${this.origin}/pay`, { @@ -108,7 +107,6 @@ export class ATXPAccount implements Account { }; } - async getSigner(): Promise { return ATXPLocalAccount.create( this.origin, From 237acafcdd27eb76afefb7d3a6b16ef33908d238 Mon Sep 17 00:00:00 2001 From: bdj Date: Fri, 19 Sep 2025 18:42:06 -0700 Subject: [PATCH 59/61] Log transaction hash --- packages/atxp-x402/src/x402Wrapper.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/atxp-x402/src/x402Wrapper.ts b/packages/atxp-x402/src/x402Wrapper.ts index 3133b4d3..be760dbb 100644 --- a/packages/atxp-x402/src/x402Wrapper.ts +++ b/packages/atxp-x402/src/x402Wrapper.ts @@ -159,8 +159,14 @@ export const wrapWithX402: FetchWrapper = (config: ClientArgs): FetchLike => { throw new Error(`Failed to ensure sufficient USDC: ${errorText}`); } - const ensureResult = await ensureResponse.json() as { message?: string; balance?: { usdc: string; iou: string } }; + const ensureResult = await ensureResponse.json() as { message?: string; balance?: { usdc: string; iou: string }; txHash?: string }; log.info(`Currency ensured: ${ensureResult.message}, USDC: ${ensureResult.balance?.usdc}, IOU: ${ensureResult.balance?.iou}`); + + // If a transaction hash was returned (meaning funds were moved to EOA), log it + if (ensureResult.txHash) { + log.info(`USDC moved to EOA for X402 payment - Transaction hash: ${ensureResult.txHash}`); + log.info(`View on Basescan: https://basescan.org/tx/${ensureResult.txHash}`); + } } // Create the X402 payment header using the x402 library From f4a58d2ced878d3566e82e963f4200b7970d1666 Mon Sep 17 00:00:00 2001 From: bdj Date: Fri, 19 Sep 2025 22:48:11 -0700 Subject: [PATCH 60/61] Cleanup; only allow ATXPAccount for X402wrapper --- examples/x402/src/test-client.ts | 1 - packages/atxp-x402/src/x402Wrapper.ts | 7 ++++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/x402/src/test-client.ts b/examples/x402/src/test-client.ts index 923dc291..faf2d31f 100644 --- a/examples/x402/src/test-client.ts +++ b/examples/x402/src/test-client.ts @@ -17,7 +17,6 @@ async function main() { console.log(`Server: ${serverUrl}`); const account = new ATXPAccount(process.env.ATXP_CONNECTION_STRING!); - //const account = new BaseAccount(process.env.BASE_RPC!, process.env.BASE_PRIVATE_KEY! as `0x${string}`); const config = { account, logger: new ConsoleLogger({level: LogLevel.DEBUG}), diff --git a/packages/atxp-x402/src/x402Wrapper.ts b/packages/atxp-x402/src/x402Wrapper.ts index be760dbb..baf6e0cb 100644 --- a/packages/atxp-x402/src/x402Wrapper.ts +++ b/packages/atxp-x402/src/x402Wrapper.ts @@ -1,4 +1,4 @@ -import { ProspectivePayment, type FetchWrapper, type ClientArgs } from '@atxp/client'; +import { ProspectivePayment, type FetchWrapper, type ClientArgs, ATXPAccount } from '@atxp/client'; import { FetchLike, Network } from '@atxp/common'; import { BigNumber } from 'bignumber.js'; import { createPaymentHeader, selectPaymentRequirements } from 'x402/client'; @@ -26,6 +26,11 @@ export const wrapWithX402: FetchWrapper = (config: ClientArgs): FetchLike => { const { account, logger, fetchFn = fetch, approvePayment, onPayment, onPaymentFailure } = config; const log = logger ?? console; + // Check if account is an ATXPAccount - X402 support requires ATXPAccount + if (!(account instanceof ATXPAccount)) { + throw new Error('Only ATXPAccount is supported for X402 payments'); + } + // Check if account has getSigner method const accountWithSigner = account as { getSigner?: () => Promise }; if (!accountWithSigner.getSigner) { From 2cb9122ff40d42637b881103240226a4e8e725e5 Mon Sep 17 00:00:00 2001 From: bdj Date: Fri, 19 Sep 2025 22:51:16 -0700 Subject: [PATCH 61/61] Update tests --- packages/atxp-x402/src/x402Wrapper.test.ts | 58 +++++++++++++++------- 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/packages/atxp-x402/src/x402Wrapper.test.ts b/packages/atxp-x402/src/x402Wrapper.test.ts index 49a4b387..3de63530 100644 --- a/packages/atxp-x402/src/x402Wrapper.test.ts +++ b/packages/atxp-x402/src/x402Wrapper.test.ts @@ -1,6 +1,6 @@ import { describe, it, expect, vi, beforeEach, Mock } from 'vitest'; import { wrapWithX402 } from './x402Wrapper.js'; -import { BaseAccount } from '@atxp/client'; +import { ATXPAccount } from '@atxp/client'; import { ConsoleLogger, LogLevel } from '@atxp/common'; vi.mock('x402/client', () => ({ @@ -12,7 +12,7 @@ vi.mock('x402/client', () => ({ })); describe('wrapWithX402', () => { - let mockAccount: BaseAccount; + let mockAccount: ATXPAccount; let mockFetch: ReturnType; let mockLogger: ConsoleLogger; let mockApprovePayment: ReturnType; @@ -20,22 +20,29 @@ describe('wrapWithX402', () => { let mockOnPaymentFailure: ReturnType; beforeEach(() => { - // Mock BaseAccount - mockAccount = { - accountId: '0x1234567890123456789012345678901234567890', - network: 'base', - getSigner: vi.fn().mockResolvedValue({ + // Create a mock ATXPAccount instance using the proper connection string format + mockAccount = new ATXPAccount('https://test.com?connection_token=test-token'); + + // Override the fetchFn to mock the ensure-currency call + mockAccount.fetchFn = vi.fn().mockResolvedValue( + new Response(JSON.stringify({ + message: 'Currency ensured', + balance: { usdc: '100', iou: '0' } + }), { status: 200 }) + ); + + // Override the getSigner method + mockAccount.getSigner = vi.fn().mockResolvedValue({ + address: '0x1234567890123456789012345678901234567890', + signTypedData: vi.fn().mockResolvedValue('0xmockedsignature'), + account: { address: '0x1234567890123456789012345678901234567890', - signTypedData: vi.fn().mockResolvedValue('0xmockedsignature'), - account: { - address: '0x1234567890123456789012345678901234567890', - }, - chain: { - id: 8453, - }, - transport: {}, - }), - } as unknown as BaseAccount; + }, + chain: { + id: 8453, + }, + transport: {}, + }); // Mock fetch mockFetch = vi.fn(); @@ -49,6 +56,23 @@ describe('wrapWithX402', () => { mockOnPaymentFailure = vi.fn(); }); + it('should throw an error if account is not an ATXPAccount', () => { + // Create a non-ATXPAccount object + const nonATXPAccount = { + accountId: '0x1234567890123456789012345678901234567890', + network: 'base', + getSigner: vi.fn(), + }; + + expect(() => { + wrapWithX402({ + account: nonATXPAccount as any, + fetchFn: mockFetch, + logger: mockLogger, + }); + }).toThrow('Only ATXPAccount is supported for X402 payments'); + }); + it('should pass through normal requests without modification', async () => { const mockResponse = new Response('Success', { status: 200 }); mockFetch.mockResolvedValue(mockResponse);