@warppay402/sdk 1.0.5 → 1.1.0

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() {
package/dist/index.d.ts CHANGED
@@ -1,48 +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;
8
+ /** Custom Solana RPC URL */
9
+ solanaRpcUrl?: string;
26
10
  }
27
11
  export declare class WarpPayClient {
28
12
  private baseUrl;
29
- private account;
13
+ private account?;
14
+ private solanaKeypair?;
15
+ private solanaConnection;
30
16
  constructor(config: WarpPayConfig);
31
17
  /**
32
- * Internal helper handling the initial HTTP request, 402 Payment Required challenge,
33
- * EIP-712 signing, and automated retry with x402 payment authorization headers.
18
+ * Handles multi-chain HTTP 402 Payment Required challenges dynamically.
34
19
  */
35
20
  private executePaidRequest;
36
- /**
37
- * Scrapes any Web URL into clean Markdown for AI context ($0.01 USDC on Base)
38
- */
39
- scrapeWeb(url: string): Promise<ScrapeResponse>;
40
- /**
41
- * Fetches Base Mainnet balance and transaction stats for any 0x wallet ($0.02 USDC on Base)
42
- */
43
- getBaseAnalytics(address: string): Promise<BaseAnalyticsResponse>;
44
- /**
45
- * Downloads and extracts text preview from a public PDF URL ($0.05 USDC on Base)
46
- */
47
- extractPdf(pdfUrl: string): Promise<PdfExtractorResponse>;
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>;
48
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,23 +155,23 @@ 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
  }
167
+ async browserScrape(url) {
168
+ return this.executePaidRequest("/api/v1/tools/browser-scraper", { url });
169
+ }
170
+ async renderScreenshot(url) {
171
+ return this.executePaidRequest("/api/v1/tools/render-screenshot", { url });
172
+ }
173
+ async extractJson(url, schema) {
174
+ return this.executePaidRequest("/api/v1/tools/extract-json", { url, schema });
175
+ }
124
176
  }
125
177
  exports.WarpPayClient = WarpPayClient;
@@ -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
  })[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@warppay402/sdk",
3
- "version": "1.0.5",
3
+ "version": "1.1.0",
4
4
  "description": "Official TypeScript SDK for WarpPay402 pay-per-use AI tools on Base Mainnet",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -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,137 +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;
19
+ /** Custom Solana RPC URL */
20
+ solanaRpcUrl?: string;
33
21
  }
34
22
 
35
23
  export class WarpPayClient {
36
24
  private baseUrl: string;
37
- private account;
25
+ private account?: ReturnType<typeof privateKeyToAccount>;
26
+ private solanaKeypair?: Keypair;
27
+ private solanaConnection: Connection;
38
28
 
39
29
  constructor(config: WarpPayConfig) {
40
30
  this.baseUrl = (config.baseUrl || "https://api.warppay402.com").replace(/\/$/, "");
41
-
42
- const rawKey = config.privateKey.trim();
43
- const formattedKey = (rawKey.startsWith("0x") ? rawKey : `0x${rawKey}`) as `0x${string}`;
44
- 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
+ }
45
52
  }
46
53
 
47
54
  /**
48
- * Internal helper handling the initial HTTP request, 402 Payment Required challenge,
49
- * EIP-712 signing, and automated retry with x402 payment authorization headers.
55
+ * Handles multi-chain HTTP 402 Payment Required challenges dynamically.
50
56
  */
51
57
  private async executePaidRequest<T>(endpoint: string, payload: Record<string, any>): Promise<T> {
52
58
  const url = `${this.baseUrl}${endpoint}`;
53
59
 
54
- // 1. Initial Request
60
+ // 1. Initial Request Probe
55
61
  let response = await fetch(url, {
56
62
  method: "POST",
57
63
  headers: { "Content-Type": "application/json" },
58
64
  body: JSON.stringify(payload),
59
65
  });
60
66
 
61
- // 2. Handle x402 V2 Payment Challenge if HTTP 402 returned
67
+ // 2. Multi-Chain Settlement Challenge Response
62
68
  if (response.status === 402) {
63
69
  const challenge = await response.json();
64
-
65
- const req = challenge.x402?.accepts?.[0] || challenge.accepts?.[0] || {};
66
- const payTo = (req.payToAddress || req.payTo || "0x0000000000000000000000000000000000000000") as `0x${string}`;
67
- const assetContract = (req.asset || req.usdcAddress || "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913") as `0x${string}`;
68
- const value = BigInt(req.maxAmountRequired || req.amount || "10000");
69
-
70
- const domain = {
71
- name: req.extra?.name || "USD Coin",
72
- version: req.extra?.version || "2",
73
- chainId: 8453,
74
- verifyingContract: assetContract,
75
- };
76
-
77
- const types = {
78
- TransferWithAuthorization: [
79
- { name: "from", type: "address" },
80
- { name: "to", type: "address" },
81
- { name: "value", type: "uint256" },
82
- { name: "validAfter", type: "uint256" },
83
- { name: "validBefore", type: "uint256" },
84
- { name: "nonce", type: "bytes32" },
85
- ],
86
- };
87
-
88
- const now = Math.floor(Date.now() / 1000);
89
- const nonce = `0x${crypto.randomBytes(32).toString("hex")}` as `0x${string}`;
90
-
91
- const message = {
92
- from: this.account.address,
93
- to: payTo,
94
- value,
95
- validAfter: BigInt(0),
96
- validBefore: BigInt(now + 3600),
97
- nonce,
98
- };
99
-
100
- // Sign typed EIP-712 USDC TransferWithAuthorization data
101
- const signature = await this.account.signTypedData({
102
- domain,
103
- types,
104
- primaryType: "TransferWithAuthorization",
105
- message,
106
- });
107
-
108
- const paymentPayload = {
109
- x402Version: 2,
110
- scheme: req.scheme || "exact",
111
- network: req.network || "eip155:8453",
112
- payload: {
113
- authorization: {
114
- from: this.account.address,
115
- to: payTo,
116
- value: value.toString(),
117
- validAfter: "0",
118
- validBefore: (now + 3600).toString(),
119
- 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,
120
177
  },
121
- signature,
122
- },
123
- };
178
+ };
179
+ } else {
180
+ throw new Error("No matching private key configured for returned 402 networks.");
181
+ }
124
182
 
125
183
  const encodedPayload = Buffer.from(JSON.stringify(paymentPayload)).toString("base64");
126
184
 
127
- // Retry request with signed x402 headers
185
+ // Resubmit request with signed x402 headers
128
186
  response = await fetch(url, {
129
187
  method: "POST",
130
188
  headers: {
131
189
  "Content-Type": "application/json",
132
190
  "X-PAYMENT": encodedPayload,
133
191
  "PAYMENT-SIGNATURE": encodedPayload,
134
- "X-PAYMENT-SIGNATURE": signature,
135
192
  },
136
193
  body: JSON.stringify(payload),
137
194
  });
@@ -145,24 +202,27 @@ export class WarpPayClient {
145
202
  return (await response.json()) as T;
146
203
  }
147
204
 
148
- /**
149
- * Scrapes any Web URL into clean Markdown for AI context ($0.01 USDC on Base)
150
- */
151
- public async scrapeWeb(url: string): Promise<ScrapeResponse> {
152
- 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 });
153
207
  }
154
208
 
155
- /**
156
- * Fetches Base Mainnet balance and transaction stats for any 0x wallet ($0.02 USDC on Base)
157
- */
158
- public async getBaseAnalytics(address: string): Promise<BaseAnalyticsResponse> {
159
- 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 });
160
211
  }
161
212
 
162
- /**
163
- * Downloads and extracts text preview from a public PDF URL ($0.05 USDC on Base)
164
- */
165
- public async extractPdf(pdfUrl: string): Promise<PdfExtractorResponse> {
166
- 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 });
215
+ }
216
+
217
+ public async browserScrape(url: string): Promise<any> {
218
+ return this.executePaidRequest("/api/v1/tools/browser-scraper", { url });
219
+ }
220
+
221
+ public async renderScreenshot(url: string): Promise<any> {
222
+ return this.executePaidRequest("/api/v1/tools/render-screenshot", { url });
223
+ }
224
+
225
+ public async extractJson(url: string, schema?: object): Promise<any> {
226
+ return this.executePaidRequest("/api/v1/tools/extract-json", { url, schema });
167
227
  }
168
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
  }