@warppay402/sdk 1.0.6 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -11,9 +11,12 @@ npm install @warppay402/sdk
11
11
  ```typescript
12
12
  import { WarpPayClient } from "@warppay402/sdk";
13
13
 
14
- // Initialize with your AI agent's Base wallet private key
14
+ import { WarpPayClient } from "@warppay402/sdk";
15
+
16
+ // Initialize with Base EVM, Solana L1, or both
15
17
  const client = new WarpPayClient({
16
- privateKey: process.env.CUSTOMER_PRIVATE_KEY as `0x${string}`,
18
+ privateKey: process.env.CUSTOMER_BASE_KEY as `0x${string}`,
19
+ solanaPrivateKey: process.env.CUSTOMER_SOLANA_KEY,
17
20
  });
18
21
 
19
22
  async function main() {
@@ -70,8 +73,10 @@ const tools = createWarpPayLangChainTools(client);
70
73
  ```
71
74
  ## 🌐 API Gateway & Specs
72
75
 
73
- Gateway: https://api.warppay402.com
76
+ MCP Gateway Endpoint: https://api.warppay402.com/mcp
74
77
 
75
78
  MCP Manifest: https://api.warppay402.com/.well-known/mcp.json
76
79
 
80
+ REST Gateway Base: https://api.warppay402.com
81
+
77
82
  OpenAPI Spec: https://api.warppay402.com/openapi.json
package/dist/index.d.ts CHANGED
@@ -1,77 +1,27 @@
1
1
  export interface WarpPayConfig {
2
- /** Base Mainnet private key of the agent's wallet funding the micro-payments */
3
- privateKey: `0x${string}`;
2
+ /** Base Mainnet private key of the agent's wallet funding micro-payments */
3
+ privateKey?: `0x${string}`;
4
+ /** Solana Mainnet base58 private key funding micro-payments */
5
+ solanaPrivateKey?: string;
4
6
  /** Custom gateway URL (Defaults to https://api.warppay402.com) */
5
7
  baseUrl?: string;
6
- }
7
- export interface ScrapeResponse {
8
- success: boolean;
9
- title: string;
10
- markdown: string;
11
- truncated: boolean;
12
- }
13
- export interface BaseAnalyticsResponse {
14
- success: boolean;
15
- network: string;
16
- address: string;
17
- ethBalance: string;
18
- nonce: number;
19
- timestamp: string;
20
- }
21
- export interface PdfExtractorResponse {
22
- success: boolean;
23
- pages: number;
24
- info: Record<string, any>;
25
- textPreview: string;
26
- }
27
- export interface BrowserScrapeResponse {
28
- success: boolean;
29
- url: string;
30
- content: string;
31
- }
32
- export interface ScreenshotResponse {
33
- success: boolean;
34
- url: string;
35
- screenshotUrl?: string;
36
- base64?: string;
37
- }
38
- export interface ExtractJsonResponse {
39
- success: boolean;
40
- url: string;
41
- schema: any;
42
- extractedData: Record<string, any>;
8
+ /** Custom Solana RPC URL */
9
+ solanaRpcUrl?: string;
43
10
  }
44
11
  export declare class WarpPayClient {
45
12
  private baseUrl;
46
- private account;
13
+ private account?;
14
+ private solanaKeypair?;
15
+ private solanaConnection;
47
16
  constructor(config: WarpPayConfig);
48
17
  /**
49
- * Internal helper handling the initial HTTP request, 402 Payment Required challenge,
50
- * EIP-712 signing, and automated retry with x402 payment authorization headers.
18
+ * Handles multi-chain HTTP 402 Payment Required challenges dynamically.
51
19
  */
52
20
  private executePaidRequest;
53
- /**
54
- * Scrapes any Web URL into clean Markdown for AI context ($0.01 USDC on Base)
55
- */
56
- scrapeWeb(url: string): Promise<ScrapeResponse>;
57
- /**
58
- * Fetches Base Mainnet balance and transaction stats for any 0x wallet ($0.02 USDC on Base)
59
- */
60
- getBaseAnalytics(address: string): Promise<BaseAnalyticsResponse>;
61
- /**
62
- * Downloads and extracts text preview from a public PDF URL ($0.05 USDC on Base)
63
- */
64
- extractPdf(pdfUrl: string): Promise<PdfExtractorResponse>;
65
- /**
66
- * Executes JS-rendering browser scraper via proxy workers ($0.05 USDC on Base)
67
- */
68
- browserScrape(url: string): Promise<BrowserScrapeResponse>;
69
- /**
70
- * Renders target URL and returns full-page screenshot data ($0.10 USDC on Base)
71
- */
72
- renderScreenshot(url: string): Promise<ScreenshotResponse>;
73
- /**
74
- * Extracts structured JSON schema data from web pages ($0.15 USDC on Base)
75
- */
76
- extractJson(url: string, schema?: object): Promise<ExtractJsonResponse>;
21
+ scrapeWeb(url: string): Promise<any>;
22
+ getBaseAnalytics(address: string): Promise<any>;
23
+ extractPdf(pdfUrl: string): Promise<any>;
24
+ browserScrape(url: string): Promise<any>;
25
+ renderScreenshot(url: string): Promise<any>;
26
+ extractJson(url: string, schema?: object): Promise<any>;
77
27
  }
package/dist/index.js CHANGED
@@ -7,92 +7,144 @@ exports.WarpPayClient = void 0;
7
7
  const node_crypto_1 = __importDefault(require("node:crypto"));
8
8
  const node_buffer_1 = require("node:buffer");
9
9
  const accounts_1 = require("viem/accounts");
10
+ const web3_js_1 = require("@solana/web3.js");
11
+ const spl_token_1 = require("@solana/spl-token");
12
+ const bs58_1 = __importDefault(require("bs58"));
10
13
  class WarpPayClient {
11
14
  baseUrl;
12
15
  account;
16
+ solanaKeypair;
17
+ solanaConnection;
13
18
  constructor(config) {
14
19
  this.baseUrl = (config.baseUrl || "https://api.warppay402.com").replace(/\/$/, "");
15
- const rawKey = config.privateKey.trim();
16
- const formattedKey = (rawKey.startsWith("0x") ? rawKey : `0x${rawKey}`);
17
- this.account = (0, accounts_1.privateKeyToAccount)(formattedKey);
20
+ this.solanaConnection = new web3_js_1.Connection(config.solanaRpcUrl || "https://api.mainnet-beta.solana.com", "confirmed");
21
+ // EVM Account Setup
22
+ if (config.privateKey) {
23
+ const rawKey = config.privateKey.trim();
24
+ const formattedKey = (rawKey.startsWith("0x") ? rawKey : `0x${rawKey}`);
25
+ this.account = (0, accounts_1.privateKeyToAccount)(formattedKey);
26
+ }
27
+ // Solana Account Setup
28
+ if (config.solanaPrivateKey) {
29
+ const decodedSecret = bs58_1.default.decode(config.solanaPrivateKey.trim());
30
+ this.solanaKeypair = web3_js_1.Keypair.fromSecretKey(decodedSecret);
31
+ }
32
+ if (!this.account && !this.solanaKeypair) {
33
+ throw new Error("WarpPayClient requires either a Base privateKey or a solanaPrivateKey.");
34
+ }
18
35
  }
19
36
  /**
20
- * Internal helper handling the initial HTTP request, 402 Payment Required challenge,
21
- * EIP-712 signing, and automated retry with x402 payment authorization headers.
37
+ * Handles multi-chain HTTP 402 Payment Required challenges dynamically.
22
38
  */
23
39
  async executePaidRequest(endpoint, payload) {
24
40
  const url = `${this.baseUrl}${endpoint}`;
25
- // 1. Initial Request
41
+ // 1. Initial Request Probe
26
42
  let response = await fetch(url, {
27
43
  method: "POST",
28
44
  headers: { "Content-Type": "application/json" },
29
45
  body: JSON.stringify(payload),
30
46
  });
31
- // 2. Handle x402 V2 Payment Challenge if HTTP 402 returned
47
+ // 2. Multi-Chain Settlement Challenge Response
32
48
  if (response.status === 402) {
33
49
  const challenge = await response.json();
34
- const req = challenge.x402?.accepts?.[0] || challenge.accepts?.[0] || {};
35
- const payTo = (req.payToAddress || req.payTo || "0x0000000000000000000000000000000000000000");
36
- const assetContract = (req.asset || req.usdcAddress || "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913");
37
- const value = BigInt(req.maxAmountRequired || req.amount || "10000");
38
- const domain = {
39
- name: req.extra?.name || "USD Coin",
40
- version: req.extra?.version || "2",
41
- chainId: 8453,
42
- verifyingContract: assetContract,
43
- };
44
- const types = {
45
- TransferWithAuthorization: [
46
- { name: "from", type: "address" },
47
- { name: "to", type: "address" },
48
- { name: "value", type: "uint256" },
49
- { name: "validAfter", type: "uint256" },
50
- { name: "validBefore", type: "uint256" },
51
- { name: "nonce", type: "bytes32" },
52
- ],
53
- };
54
- const now = Math.floor(Date.now() / 1000);
55
- const nonce = `0x${node_crypto_1.default.randomBytes(32).toString("hex")}`;
56
- const message = {
57
- from: this.account.address,
58
- to: payTo,
59
- value,
60
- validAfter: BigInt(0),
61
- validBefore: BigInt(now + 3600),
62
- nonce,
63
- };
64
- // Sign typed EIP-712 USDC TransferWithAuthorization data
65
- const signature = await this.account.signTypedData({
66
- domain,
67
- types,
68
- primaryType: "TransferWithAuthorization",
69
- message,
70
- });
71
- const paymentPayload = {
72
- x402Version: 2,
73
- scheme: req.scheme || "exact",
74
- network: req.network || "eip155:8453",
75
- payload: {
76
- authorization: {
77
- from: this.account.address,
78
- to: payTo,
79
- value: value.toString(),
80
- validAfter: "0",
81
- validBefore: (now + 3600).toString(),
82
- nonce,
50
+ const accepts = challenge.x402?.accepts || challenge.accepts || [];
51
+ // Check for Solana offer if solanaKeypair is available
52
+ const solanaReq = accepts.find((a) => a.network?.includes("solana"));
53
+ const evmReq = accepts.find((a) => a.network?.includes("eip155"));
54
+ let paymentPayload;
55
+ if (solanaReq && this.solanaKeypair) {
56
+ // Execute Solana L1 SPL-USDC Transaction Authorization
57
+ const payToPubkey = new web3_js_1.PublicKey(solanaReq.payTo);
58
+ const usdcMint = new web3_js_1.PublicKey(solanaReq.asset || "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
59
+ const amountUnits = BigInt(solanaReq.amount || solanaReq.maxAmountRequired || "10000"); // $0.01 USDC
60
+ const senderPubkey = this.solanaKeypair.publicKey;
61
+ const senderAta = await (0, spl_token_1.getAssociatedTokenAddress)(usdcMint, senderPubkey);
62
+ const recipientAta = await (0, spl_token_1.getAssociatedTokenAddress)(usdcMint, payToPubkey);
63
+ const tx = new web3_js_1.Transaction();
64
+ tx.feePayer = senderPubkey;
65
+ tx.recentBlockhash = (await this.solanaConnection.getLatestBlockhash()).blockhash;
66
+ // Idempotently create recipient ATA if required
67
+ tx.add((0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(senderPubkey, recipientAta, payToPubkey, usdcMint));
68
+ // Append SPL-USDC Transfer instruction
69
+ tx.add((0, spl_token_1.createTransferInstruction)(senderAta, recipientAta, senderPubkey, amountUnits));
70
+ tx.sign(this.solanaKeypair);
71
+ const serializedTx = node_buffer_1.Buffer.from(tx.serialize()).toString("base64");
72
+ paymentPayload = {
73
+ x402Version: 2,
74
+ scheme: solanaReq.scheme || "exact",
75
+ network: solanaReq.network || "solana:5eykt4wA89m8E5b9B5658p445VTc28",
76
+ signature: serializedTx,
77
+ paymentPayload: {
78
+ signature: serializedTx,
79
+ network: solanaReq.network
80
+ }
81
+ };
82
+ }
83
+ else if (evmReq && this.account) {
84
+ // EVM EIP-712 Base Path
85
+ const payTo = (evmReq.payToAddress || evmReq.payTo);
86
+ const assetContract = (evmReq.asset || evmReq.usdcAddress);
87
+ const value = BigInt(evmReq.maxAmountRequired || evmReq.amount || "10000");
88
+ const domain = {
89
+ name: evmReq.extra?.name || "USD Coin",
90
+ version: evmReq.extra?.version || "2",
91
+ chainId: 8453,
92
+ verifyingContract: assetContract,
93
+ };
94
+ const types = {
95
+ TransferWithAuthorization: [
96
+ { name: "from", type: "address" },
97
+ { name: "to", type: "address" },
98
+ { name: "value", type: "uint256" },
99
+ { name: "validAfter", type: "uint256" },
100
+ { name: "validBefore", type: "uint256" },
101
+ { name: "nonce", type: "bytes32" },
102
+ ],
103
+ };
104
+ const now = Math.floor(Date.now() / 1000);
105
+ const nonce = `0x${node_crypto_1.default.randomBytes(32).toString("hex")}`;
106
+ const message = {
107
+ from: this.account.address,
108
+ to: payTo,
109
+ value,
110
+ validAfter: BigInt(0),
111
+ validBefore: BigInt(now + 3600),
112
+ nonce,
113
+ };
114
+ const signature = await this.account.signTypedData({
115
+ domain,
116
+ types,
117
+ primaryType: "TransferWithAuthorization",
118
+ message,
119
+ });
120
+ paymentPayload = {
121
+ x402Version: 2,
122
+ scheme: evmReq.scheme || "exact",
123
+ network: evmReq.network || "eip155:8453",
124
+ payload: {
125
+ authorization: {
126
+ from: this.account.address,
127
+ to: payTo,
128
+ value: value.toString(),
129
+ validAfter: "0",
130
+ validBefore: (now + 3600).toString(),
131
+ nonce,
132
+ },
133
+ signature,
83
134
  },
84
- signature,
85
- },
86
- };
135
+ };
136
+ }
137
+ else {
138
+ throw new Error("No matching private key configured for returned 402 networks.");
139
+ }
87
140
  const encodedPayload = node_buffer_1.Buffer.from(JSON.stringify(paymentPayload)).toString("base64");
88
- // Retry request with signed x402 headers
141
+ // Resubmit request with signed x402 headers
89
142
  response = await fetch(url, {
90
143
  method: "POST",
91
144
  headers: {
92
145
  "Content-Type": "application/json",
93
146
  "X-PAYMENT": encodedPayload,
94
147
  "PAYMENT-SIGNATURE": encodedPayload,
95
- "X-PAYMENT-SIGNATURE": signature,
96
148
  },
97
149
  body: JSON.stringify(payload),
98
150
  });
@@ -103,39 +155,21 @@ class WarpPayClient {
103
155
  }
104
156
  return (await response.json());
105
157
  }
106
- /**
107
- * Scrapes any Web URL into clean Markdown for AI context ($0.01 USDC on Base)
108
- */
109
158
  async scrapeWeb(url) {
110
159
  return this.executePaidRequest("/api/v1/tools/web-scraper", { url });
111
160
  }
112
- /**
113
- * Fetches Base Mainnet balance and transaction stats for any 0x wallet ($0.02 USDC on Base)
114
- */
115
161
  async getBaseAnalytics(address) {
116
162
  return this.executePaidRequest("/api/v1/tools/base-analytics", { address });
117
163
  }
118
- /**
119
- * Downloads and extracts text preview from a public PDF URL ($0.05 USDC on Base)
120
- */
121
164
  async extractPdf(pdfUrl) {
122
165
  return this.executePaidRequest("/api/v1/tools/pdf-extractor", { pdfUrl });
123
166
  }
124
- /**
125
- * Executes JS-rendering browser scraper via proxy workers ($0.05 USDC on Base)
126
- */
127
167
  async browserScrape(url) {
128
168
  return this.executePaidRequest("/api/v1/tools/browser-scraper", { url });
129
169
  }
130
- /**
131
- * Renders target URL and returns full-page screenshot data ($0.10 USDC on Base)
132
- */
133
170
  async renderScreenshot(url) {
134
171
  return this.executePaidRequest("/api/v1/tools/render-screenshot", { url });
135
172
  }
136
- /**
137
- * Extracts structured JSON schema data from web pages ($0.15 USDC on Base)
138
- */
139
173
  async extractJson(url, schema) {
140
174
  return this.executePaidRequest("/api/v1/tools/extract-json", { url, schema });
141
175
  }
@@ -7,7 +7,7 @@ export declare function createWarpPayLangChainTools(client: WarpPayClient): ({
7
7
  description: string;
8
8
  func: ({ url }: {
9
9
  url: string;
10
- }) => Promise<string>;
10
+ }) => Promise<any>;
11
11
  } | {
12
12
  name: string;
13
13
  description: string;
@@ -19,5 +19,5 @@ export declare function createWarpPayLangChainTools(client: WarpPayClient): ({
19
19
  description: string;
20
20
  func: ({ pdfUrl }: {
21
21
  pdfUrl: string;
22
- }) => Promise<string>;
22
+ }) => Promise<any>;
23
23
  })[];
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "warppay402-sdk",
3
3
  "name": "warppay402-sdk",
4
- "version": "1.0.4",
5
- "description": "Official TypeScript SDK for WarpPay402 pay-per-use AI tools on Base Mainnet"
4
+ "version": "1.1.1",
5
+ "description": "Official WarpPay402 TypeScript SDK: Enabling seamless pay-per-use AI tools across both Base Mainnet and Solana."
6
6
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@warppay402/sdk",
3
- "version": "1.0.6",
4
- "description": "Official TypeScript SDK for WarpPay402 pay-per-use AI tools on Base Mainnet",
3
+ "version": "1.1.1",
4
+ "description": "Official WarpPay402 TypeScript SDK: Enabling seamless pay-per-use AI tools across both Base Mainnet and Solana.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "scripts": {
@@ -24,7 +24,10 @@
24
24
  "langchain"
25
25
  ],
26
26
  "dependencies": {
27
+ "@solana/spl-token": "^0.4.15",
28
+ "@solana/web3.js": "^1.98.4",
27
29
  "@warppay402/server": "^1.0.0",
30
+ "bs58": "^6.0.0",
28
31
  "viem": "^2.0.0"
29
32
  },
30
33
  "devDependencies": {
package/src/index.ts CHANGED
@@ -1,157 +1,194 @@
1
1
  import crypto from "node:crypto";
2
2
  import { Buffer } from "node:buffer";
3
3
  import { privateKeyToAccount } from "viem/accounts";
4
+ import { Keypair, Connection, Transaction, PublicKey } from "@solana/web3.js";
5
+ import {
6
+ getAssociatedTokenAddress,
7
+ createTransferInstruction,
8
+ createAssociatedTokenAccountIdempotentInstruction
9
+ } from "@solana/spl-token";
10
+ import bs58 from "bs58";
4
11
 
5
12
  export interface WarpPayConfig {
6
- /** Base Mainnet private key of the agent's wallet funding the micro-payments */
7
- privateKey: `0x${string}`;
13
+ /** Base Mainnet private key of the agent's wallet funding micro-payments */
14
+ privateKey?: `0x${string}`;
15
+ /** Solana Mainnet base58 private key funding micro-payments */
16
+ solanaPrivateKey?: string;
8
17
  /** Custom gateway URL (Defaults to https://api.warppay402.com) */
9
18
  baseUrl?: string;
10
- }
11
-
12
- export interface ScrapeResponse {
13
- success: boolean;
14
- title: string;
15
- markdown: string;
16
- truncated: boolean;
17
- }
18
-
19
- export interface BaseAnalyticsResponse {
20
- success: boolean;
21
- network: string;
22
- address: string;
23
- ethBalance: string;
24
- nonce: number;
25
- timestamp: string;
26
- }
27
-
28
- export interface PdfExtractorResponse {
29
- success: boolean;
30
- pages: number;
31
- info: Record<string, any>;
32
- textPreview: string;
33
- }
34
-
35
- export interface BrowserScrapeResponse {
36
- success: boolean;
37
- url: string;
38
- content: string;
39
- }
40
-
41
- export interface ScreenshotResponse {
42
- success: boolean;
43
- url: string;
44
- screenshotUrl?: string;
45
- base64?: string;
46
- }
47
-
48
- export interface ExtractJsonResponse {
49
- success: boolean;
50
- url: string;
51
- schema: any;
52
- extractedData: Record<string, any>;
19
+ /** Custom Solana RPC URL */
20
+ solanaRpcUrl?: string;
53
21
  }
54
22
 
55
23
  export class WarpPayClient {
56
24
  private baseUrl: string;
57
- private account;
25
+ private account?: ReturnType<typeof privateKeyToAccount>;
26
+ private solanaKeypair?: Keypair;
27
+ private solanaConnection: Connection;
58
28
 
59
29
  constructor(config: WarpPayConfig) {
60
30
  this.baseUrl = (config.baseUrl || "https://api.warppay402.com").replace(/\/$/, "");
61
-
62
- const rawKey = config.privateKey.trim();
63
- const formattedKey = (rawKey.startsWith("0x") ? rawKey : `0x${rawKey}`) as `0x${string}`;
64
- this.account = privateKeyToAccount(formattedKey);
31
+ this.solanaConnection = new Connection(
32
+ config.solanaRpcUrl || "https://api.mainnet-beta.solana.com",
33
+ "confirmed"
34
+ );
35
+
36
+ // EVM Account Setup
37
+ if (config.privateKey) {
38
+ const rawKey = config.privateKey.trim();
39
+ const formattedKey = (rawKey.startsWith("0x") ? rawKey : `0x${rawKey}`) as `0x${string}`;
40
+ this.account = privateKeyToAccount(formattedKey);
41
+ }
42
+
43
+ // Solana Account Setup
44
+ if (config.solanaPrivateKey) {
45
+ const decodedSecret = bs58.decode(config.solanaPrivateKey.trim());
46
+ this.solanaKeypair = Keypair.fromSecretKey(decodedSecret);
47
+ }
48
+
49
+ if (!this.account && !this.solanaKeypair) {
50
+ throw new Error("WarpPayClient requires either a Base privateKey or a solanaPrivateKey.");
51
+ }
65
52
  }
66
53
 
67
54
  /**
68
- * Internal helper handling the initial HTTP request, 402 Payment Required challenge,
69
- * EIP-712 signing, and automated retry with x402 payment authorization headers.
55
+ * Handles multi-chain HTTP 402 Payment Required challenges dynamically.
70
56
  */
71
57
  private async executePaidRequest<T>(endpoint: string, payload: Record<string, any>): Promise<T> {
72
58
  const url = `${this.baseUrl}${endpoint}`;
73
59
 
74
- // 1. Initial Request
60
+ // 1. Initial Request Probe
75
61
  let response = await fetch(url, {
76
62
  method: "POST",
77
63
  headers: { "Content-Type": "application/json" },
78
64
  body: JSON.stringify(payload),
79
65
  });
80
66
 
81
- // 2. Handle x402 V2 Payment Challenge if HTTP 402 returned
67
+ // 2. Multi-Chain Settlement Challenge Response
82
68
  if (response.status === 402) {
83
69
  const challenge = await response.json();
84
-
85
- const req = challenge.x402?.accepts?.[0] || challenge.accepts?.[0] || {};
86
- const payTo = (req.payToAddress || req.payTo || "0x0000000000000000000000000000000000000000") as `0x${string}`;
87
- const assetContract = (req.asset || req.usdcAddress || "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913") as `0x${string}`;
88
- const value = BigInt(req.maxAmountRequired || req.amount || "10000");
89
-
90
- const domain = {
91
- name: req.extra?.name || "USD Coin",
92
- version: req.extra?.version || "2",
93
- chainId: 8453,
94
- verifyingContract: assetContract,
95
- };
96
-
97
- const types = {
98
- TransferWithAuthorization: [
99
- { name: "from", type: "address" },
100
- { name: "to", type: "address" },
101
- { name: "value", type: "uint256" },
102
- { name: "validAfter", type: "uint256" },
103
- { name: "validBefore", type: "uint256" },
104
- { name: "nonce", type: "bytes32" },
105
- ],
106
- };
107
-
108
- const now = Math.floor(Date.now() / 1000);
109
- const nonce = `0x${crypto.randomBytes(32).toString("hex")}` as `0x${string}`;
110
-
111
- const message = {
112
- from: this.account.address,
113
- to: payTo,
114
- value,
115
- validAfter: BigInt(0),
116
- validBefore: BigInt(now + 3600),
117
- nonce,
118
- };
119
-
120
- // Sign typed EIP-712 USDC TransferWithAuthorization data
121
- const signature = await this.account.signTypedData({
122
- domain,
123
- types,
124
- primaryType: "TransferWithAuthorization",
125
- message,
126
- });
127
-
128
- const paymentPayload = {
129
- x402Version: 2,
130
- scheme: req.scheme || "exact",
131
- network: req.network || "eip155:8453",
132
- payload: {
133
- authorization: {
134
- from: this.account.address,
135
- to: payTo,
136
- value: value.toString(),
137
- validAfter: "0",
138
- validBefore: (now + 3600).toString(),
139
- nonce,
70
+ const accepts: Array<any> = challenge.x402?.accepts || challenge.accepts || [];
71
+
72
+ // Check for Solana offer if solanaKeypair is available
73
+ const solanaReq = accepts.find((a) => a.network?.includes("solana"));
74
+ const evmReq = accepts.find((a) => a.network?.includes("eip155"));
75
+
76
+ let paymentPayload: any;
77
+
78
+ if (solanaReq && this.solanaKeypair) {
79
+ // Execute Solana L1 SPL-USDC Transaction Authorization
80
+ const payToPubkey = new PublicKey(solanaReq.payTo);
81
+ const usdcMint = new PublicKey(solanaReq.asset || "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
82
+ const amountUnits = BigInt(solanaReq.amount || solanaReq.maxAmountRequired || "10000"); // $0.01 USDC
83
+
84
+ const senderPubkey = this.solanaKeypair.publicKey;
85
+ const senderAta = await getAssociatedTokenAddress(usdcMint, senderPubkey);
86
+ const recipientAta = await getAssociatedTokenAddress(usdcMint, payToPubkey);
87
+
88
+ const tx = new Transaction();
89
+ tx.feePayer = senderPubkey;
90
+ tx.recentBlockhash = (await this.solanaConnection.getLatestBlockhash()).blockhash;
91
+
92
+ // Idempotently create recipient ATA if required
93
+ tx.add(
94
+ createAssociatedTokenAccountIdempotentInstruction(
95
+ senderPubkey,
96
+ recipientAta,
97
+ payToPubkey,
98
+ usdcMint
99
+ )
100
+ );
101
+
102
+ // Append SPL-USDC Transfer instruction
103
+ tx.add(
104
+ createTransferInstruction(senderAta, recipientAta, senderPubkey, amountUnits)
105
+ );
106
+
107
+ tx.sign(this.solanaKeypair);
108
+ const serializedTx = Buffer.from(tx.serialize()).toString("base64");
109
+
110
+ paymentPayload = {
111
+ x402Version: 2,
112
+ scheme: solanaReq.scheme || "exact",
113
+ network: solanaReq.network || "solana:5eykt4wA89m8E5b9B5658p445VTc28",
114
+ signature: serializedTx,
115
+ paymentPayload: {
116
+ signature: serializedTx,
117
+ network: solanaReq.network
118
+ }
119
+ };
120
+ } else if (evmReq && this.account) {
121
+ // EVM EIP-712 Base Path
122
+ const payTo = (evmReq.payToAddress || evmReq.payTo) as `0x${string}`;
123
+ const assetContract = (evmReq.asset || evmReq.usdcAddress) as `0x${string}`;
124
+ const value = BigInt(evmReq.maxAmountRequired || evmReq.amount || "10000");
125
+
126
+ const domain = {
127
+ name: evmReq.extra?.name || "USD Coin",
128
+ version: evmReq.extra?.version || "2",
129
+ chainId: 8453,
130
+ verifyingContract: assetContract,
131
+ };
132
+
133
+ const types = {
134
+ TransferWithAuthorization: [
135
+ { name: "from", type: "address" },
136
+ { name: "to", type: "address" },
137
+ { name: "value", type: "uint256" },
138
+ { name: "validAfter", type: "uint256" },
139
+ { name: "validBefore", type: "uint256" },
140
+ { name: "nonce", type: "bytes32" },
141
+ ],
142
+ };
143
+
144
+ const now = Math.floor(Date.now() / 1000);
145
+ const nonce = `0x${crypto.randomBytes(32).toString("hex")}` as `0x${string}`;
146
+
147
+ const message = {
148
+ from: this.account.address,
149
+ to: payTo,
150
+ value,
151
+ validAfter: BigInt(0),
152
+ validBefore: BigInt(now + 3600),
153
+ nonce,
154
+ };
155
+
156
+ const signature = await this.account.signTypedData({
157
+ domain,
158
+ types,
159
+ primaryType: "TransferWithAuthorization",
160
+ message,
161
+ });
162
+
163
+ paymentPayload = {
164
+ x402Version: 2,
165
+ scheme: evmReq.scheme || "exact",
166
+ network: evmReq.network || "eip155:8453",
167
+ payload: {
168
+ authorization: {
169
+ from: this.account.address,
170
+ to: payTo,
171
+ value: value.toString(),
172
+ validAfter: "0",
173
+ validBefore: (now + 3600).toString(),
174
+ nonce,
175
+ },
176
+ signature,
140
177
  },
141
- signature,
142
- },
143
- };
178
+ };
179
+ } else {
180
+ throw new Error("No matching private key configured for returned 402 networks.");
181
+ }
144
182
 
145
183
  const encodedPayload = Buffer.from(JSON.stringify(paymentPayload)).toString("base64");
146
184
 
147
- // Retry request with signed x402 headers
185
+ // Resubmit request with signed x402 headers
148
186
  response = await fetch(url, {
149
187
  method: "POST",
150
188
  headers: {
151
189
  "Content-Type": "application/json",
152
190
  "X-PAYMENT": encodedPayload,
153
191
  "PAYMENT-SIGNATURE": encodedPayload,
154
- "X-PAYMENT-SIGNATURE": signature,
155
192
  },
156
193
  body: JSON.stringify(payload),
157
194
  });
@@ -165,45 +202,27 @@ export class WarpPayClient {
165
202
  return (await response.json()) as T;
166
203
  }
167
204
 
168
- /**
169
- * Scrapes any Web URL into clean Markdown for AI context ($0.01 USDC on Base)
170
- */
171
- public async scrapeWeb(url: string): Promise<ScrapeResponse> {
172
- return this.executePaidRequest<ScrapeResponse>("/api/v1/tools/web-scraper", { url });
205
+ public async scrapeWeb(url: string): Promise<any> {
206
+ return this.executePaidRequest("/api/v1/tools/web-scraper", { url });
173
207
  }
174
208
 
175
- /**
176
- * Fetches Base Mainnet balance and transaction stats for any 0x wallet ($0.02 USDC on Base)
177
- */
178
- public async getBaseAnalytics(address: string): Promise<BaseAnalyticsResponse> {
179
- return this.executePaidRequest<BaseAnalyticsResponse>("/api/v1/tools/base-analytics", { address });
209
+ public async getBaseAnalytics(address: string): Promise<any> {
210
+ return this.executePaidRequest("/api/v1/tools/base-analytics", { address });
180
211
  }
181
212
 
182
- /**
183
- * Downloads and extracts text preview from a public PDF URL ($0.05 USDC on Base)
184
- */
185
- public async extractPdf(pdfUrl: string): Promise<PdfExtractorResponse> {
186
- return this.executePaidRequest<PdfExtractorResponse>("/api/v1/tools/pdf-extractor", { pdfUrl });
213
+ public async extractPdf(pdfUrl: string): Promise<any> {
214
+ return this.executePaidRequest("/api/v1/tools/pdf-extractor", { pdfUrl });
187
215
  }
188
216
 
189
- /**
190
- * Executes JS-rendering browser scraper via proxy workers ($0.05 USDC on Base)
191
- */
192
- public async browserScrape(url: string): Promise<BrowserScrapeResponse> {
193
- return this.executePaidRequest<BrowserScrapeResponse>("/api/v1/tools/browser-scraper", { url });
217
+ public async browserScrape(url: string): Promise<any> {
218
+ return this.executePaidRequest("/api/v1/tools/browser-scraper", { url });
194
219
  }
195
220
 
196
- /**
197
- * Renders target URL and returns full-page screenshot data ($0.10 USDC on Base)
198
- */
199
- public async renderScreenshot(url: string): Promise<ScreenshotResponse> {
200
- return this.executePaidRequest<ScreenshotResponse>("/api/v1/tools/render-screenshot", { url });
221
+ public async renderScreenshot(url: string): Promise<any> {
222
+ return this.executePaidRequest("/api/v1/tools/render-screenshot", { url });
201
223
  }
202
224
 
203
- /**
204
- * Extracts structured JSON schema data from web pages ($0.15 USDC on Base)
205
- */
206
- public async extractJson(url: string, schema?: object): Promise<ExtractJsonResponse> {
207
- return this.executePaidRequest<ExtractJsonResponse>("/api/v1/tools/extract-json", { url, schema });
225
+ public async extractJson(url: string, schema?: object): Promise<any> {
226
+ return this.executePaidRequest("/api/v1/tools/extract-json", { url, schema });
208
227
  }
209
228
  }
package/tsconfig.json CHANGED
@@ -8,7 +8,8 @@
8
8
  "rootDir": "./src",
9
9
  "strict": true,
10
10
  "esModuleInterop": true,
11
- "skipLibCheck": true
11
+ "skipLibCheck": true,
12
+ "types": ["node"]
12
13
  },
13
14
  "include": ["src/**/*"]
14
15
  }