@warppay402/sdk 1.1.5 → 1.1.8

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/.env.example ADDED
@@ -0,0 +1,12 @@
1
+ # EVM / Base Mainnet Wallet Setup
2
+ # Private key for funding Base x402 USDC micropayments (must start with 0x)
3
+ CUSTOMER_BASE_KEY=0x_your_evm_private_key_here
4
+
5
+ # Solana L1 Wallet Setup
6
+ # Base58-encoded secret key for funding Solana SPL USDC micropayments
7
+ CUSTOMER_SOLANA_KEY=base58_encoded_solana_secret_key_here
8
+
9
+ # Optional Configuration Overrides
10
+ # BASE_URL=https://api.warppay402.com
11
+ # BASE_RPC_URL=https://mainnet.base.org
12
+ # SOLANA_RPC_URL=https://api.mainnet-beta.solana.com
package/dist/index.cjs ADDED
@@ -0,0 +1,231 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ WarpPayClient: () => WarpPayClient
34
+ });
35
+ module.exports = __toCommonJS(index_exports);
36
+ var import_node_crypto = __toESM(require("crypto"), 1);
37
+ var import_node_buffer = require("buffer");
38
+ var import_accounts = require("viem/accounts");
39
+ var import_web3 = require("@solana/web3.js");
40
+ var import_spl_token = require("@solana/spl-token");
41
+ var import_bs58 = __toESM(require("bs58"), 1);
42
+ var bs58 = import_bs58.default.default || import_bs58.default;
43
+ var WarpPayClient = class {
44
+ baseUrl;
45
+ account;
46
+ solanaKeypair;
47
+ solanaConnection;
48
+ constructor(config) {
49
+ this.baseUrl = (config.baseUrl || "https://api.warppay402.com").replace(/\/$/, "");
50
+ this.solanaConnection = new import_web3.Connection(
51
+ config.solanaRpcUrl || "https://api.mainnet-beta.solana.com",
52
+ "confirmed"
53
+ );
54
+ if (config.privateKey) {
55
+ const rawKey = config.privateKey.trim();
56
+ const formattedKey = rawKey.startsWith("0x") ? rawKey : `0x${rawKey}`;
57
+ this.account = (0, import_accounts.privateKeyToAccount)(formattedKey);
58
+ }
59
+ if (config.solanaPrivateKey) {
60
+ const decodedSecret = bs58.decode(config.solanaPrivateKey.trim());
61
+ this.solanaKeypair = import_web3.Keypair.fromSecretKey(decodedSecret);
62
+ }
63
+ if (!this.account && !this.solanaKeypair) {
64
+ throw new Error("WarpPayClient requires either a Base privateKey or a solanaPrivateKey.");
65
+ }
66
+ }
67
+ /**
68
+ * Handles multi-chain HTTP 402 Payment Required challenges dynamically.
69
+ */
70
+ async executePaidRequest(endpoint, payload, method = "POST") {
71
+ const url = `${this.baseUrl}${endpoint}`;
72
+ console.log(`
73
+ \u{1F50D} [SDK DEBUG] Initiating ${method} request to: ${url}`);
74
+ const fetchOptions = {
75
+ method,
76
+ headers: { "Content-Type": "application/json" }
77
+ };
78
+ if (method === "POST" && payload) {
79
+ fetchOptions.body = JSON.stringify(payload);
80
+ console.log(`\u{1F50D} [SDK DEBUG] Request Payload:`, JSON.stringify(payload));
81
+ }
82
+ let response = await fetch(url, fetchOptions);
83
+ console.log(`\u{1F50D} [SDK DEBUG] Probe Response Status: ${response.status} ${response.statusText}`);
84
+ if (response.status === 402) {
85
+ const challenge = await response.json();
86
+ console.log(`\u{1F50D} [SDK DEBUG] Received 402 Challenge Payload:`, JSON.stringify(challenge, null, 2));
87
+ const accepts = challenge.x402?.accepts || challenge.accepts || [];
88
+ console.log(`\u{1F50D} [SDK DEBUG] Accepted Payment Rails (${accepts.length}):`, accepts.map((a) => a.network));
89
+ const solanaReq = accepts.find((a) => a.network?.includes("solana"));
90
+ const evmReq = accepts.find((a) => a.network?.includes("eip155"));
91
+ let paymentPayload;
92
+ if (solanaReq && this.solanaKeypair) {
93
+ console.log(`\u{1F50D} [SDK DEBUG] Processing Solana L1 SPL Payment challenge...`);
94
+ const payToPubkey = new import_web3.PublicKey(solanaReq.payTo);
95
+ const usdcMint = new import_web3.PublicKey(solanaReq.asset || "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
96
+ const amountUnits = BigInt(solanaReq.amount || solanaReq.maxAmountRequired || "10000");
97
+ const senderPubkey = this.solanaKeypair.publicKey;
98
+ const senderAta = await (0, import_spl_token.getAssociatedTokenAddress)(usdcMint, senderPubkey);
99
+ const recipientAta = await (0, import_spl_token.getAssociatedTokenAddress)(usdcMint, payToPubkey);
100
+ const tx = new import_web3.Transaction();
101
+ tx.feePayer = senderPubkey;
102
+ tx.recentBlockhash = (await this.solanaConnection.getLatestBlockhash()).blockhash;
103
+ tx.add(
104
+ (0, import_spl_token.createAssociatedTokenAccountIdempotentInstruction)(
105
+ senderPubkey,
106
+ recipientAta,
107
+ payToPubkey,
108
+ usdcMint
109
+ )
110
+ );
111
+ tx.add(
112
+ (0, import_spl_token.createTransferInstruction)(senderAta, recipientAta, senderPubkey, amountUnits)
113
+ );
114
+ tx.sign(this.solanaKeypair);
115
+ const serializedTx = import_node_buffer.Buffer.from(tx.serialize()).toString("base64");
116
+ paymentPayload = {
117
+ x402Version: 2,
118
+ scheme: solanaReq.scheme || "exact",
119
+ network: solanaReq.network || "solana:5eykt4wA89m8E5b9B5658p445VTc28",
120
+ signature: serializedTx,
121
+ paymentPayload: {
122
+ signature: serializedTx,
123
+ network: solanaReq.network
124
+ }
125
+ };
126
+ } else if (evmReq && this.account) {
127
+ console.log(`\u{1F50D} [SDK DEBUG] Processing EVM EIP-712 Payment challenge...`);
128
+ const payTo = evmReq.payToAddress || evmReq.payTo;
129
+ const assetContract = evmReq.asset || evmReq.usdcAddress;
130
+ const value = BigInt(evmReq.maxAmountRequired || evmReq.amount || "10000");
131
+ console.log(`\u{1F50D} [SDK DEBUG] Signer Wallet: ${this.account.address} -> PayTo: ${payTo} | Amount: ${value.toString()}`);
132
+ const domain = {
133
+ name: evmReq.extra?.name || "USD Coin",
134
+ version: evmReq.extra?.version || "2",
135
+ chainId: 8453,
136
+ verifyingContract: assetContract
137
+ };
138
+ const types = {
139
+ TransferWithAuthorization: [
140
+ { name: "from", type: "address" },
141
+ { name: "to", type: "address" },
142
+ { name: "value", type: "uint256" },
143
+ { name: "validAfter", type: "uint256" },
144
+ { name: "validBefore", type: "uint256" },
145
+ { name: "nonce", type: "bytes32" }
146
+ ]
147
+ };
148
+ const now = Math.floor(Date.now() / 1e3);
149
+ const nonce = `0x${import_node_crypto.default.randomBytes(32).toString("hex")}`;
150
+ const message = {
151
+ from: this.account.address,
152
+ to: payTo,
153
+ value,
154
+ validAfter: BigInt(0),
155
+ validBefore: BigInt(now + 3600),
156
+ nonce
157
+ };
158
+ const signature = await this.account.signTypedData({
159
+ domain,
160
+ types,
161
+ primaryType: "TransferWithAuthorization",
162
+ message
163
+ });
164
+ paymentPayload = {
165
+ x402Version: 2,
166
+ scheme: evmReq.scheme || "exact",
167
+ network: evmReq.network || "eip155:8453",
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
177
+ };
178
+ } else {
179
+ console.error(`\u274C [SDK DEBUG] Matching key missing! EVM Account Present: ${Boolean(this.account)} | Solana Keypair Present: ${Boolean(this.solanaKeypair)}`);
180
+ throw new Error("No matching private key configured for returned 402 networks.");
181
+ }
182
+ const encodedPayload = import_node_buffer.Buffer.from(JSON.stringify(paymentPayload)).toString("base64");
183
+ console.log(`\u{1F50D} [SDK DEBUG] Generated Signed x402 Base64 Header (Length: ${encodedPayload.length})`);
184
+ const retryHeaders = {
185
+ "Content-Type": "application/json",
186
+ "PAYMENT-SIGNATURE": encodedPayload,
187
+ "X-PAYMENT-RESPONSE": encodedPayload,
188
+ "X-PAYMENT": encodedPayload,
189
+ "authorization": `Bearer ${encodedPayload}`
190
+ };
191
+ const retryOptions = {
192
+ method,
193
+ headers: retryHeaders
194
+ };
195
+ if (method === "POST" && payload) {
196
+ retryOptions.body = JSON.stringify(payload);
197
+ }
198
+ console.log(`\u{1F50D} [SDK DEBUG] Resubmitting paid ${method} request to: ${url}`);
199
+ response = await fetch(url, retryOptions);
200
+ console.log(`\u{1F50D} [SDK DEBUG] Paid Retry Response Status: ${response.status} ${response.statusText}`);
201
+ }
202
+ if (!response.ok) {
203
+ const errText = await response.text();
204
+ console.error(`\u274C [SDK DEBUG] Request Rejection Body:`, errText);
205
+ throw new Error(`WarpPay API Error (${response.status}): ${errText}`);
206
+ }
207
+ return await response.json();
208
+ }
209
+ async scrapeWeb(url) {
210
+ return this.executePaidRequest("/api/v1/tools/web-scraper", { url });
211
+ }
212
+ async getBaseAnalytics(address) {
213
+ return this.executePaidRequest("/api/v1/tools/base-analytics", { address });
214
+ }
215
+ async extractPdf(pdfUrl) {
216
+ return this.executePaidRequest("/api/v1/tools/pdf-extractor", { pdfUrl });
217
+ }
218
+ async browserScrape(url) {
219
+ return this.executePaidRequest("/api/v1/tools/browser-scraper", { url });
220
+ }
221
+ async renderScreenshot(url) {
222
+ return this.executePaidRequest("/api/v1/tools/render-screenshot", { url });
223
+ }
224
+ async extractJson(url, schema) {
225
+ return this.executePaidRequest("/api/v1/tools/extract-json", { url, schema });
226
+ }
227
+ };
228
+ // Annotate the CommonJS export names for ESM import in node:
229
+ 0 && (module.exports = {
230
+ WarpPayClient
231
+ });
@@ -0,0 +1,29 @@
1
+ interface WarpPayConfig {
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;
6
+ /** Custom gateway URL (Defaults to https://api.warppay402.com) */
7
+ baseUrl?: string;
8
+ /** Custom Solana RPC URL */
9
+ solanaRpcUrl?: string;
10
+ }
11
+ declare class WarpPayClient {
12
+ private baseUrl;
13
+ private account?;
14
+ private solanaKeypair?;
15
+ private solanaConnection;
16
+ constructor(config: WarpPayConfig);
17
+ /**
18
+ * Handles multi-chain HTTP 402 Payment Required challenges dynamically.
19
+ */
20
+ executePaidRequest<T>(endpoint: string, payload?: Record<string, any>, method?: "GET" | "POST"): Promise<T>;
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>;
27
+ }
28
+
29
+ export { WarpPayClient, type WarpPayConfig };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export interface WarpPayConfig {
1
+ interface WarpPayConfig {
2
2
  /** Base Mainnet private key of the agent's wallet funding micro-payments */
3
3
  privateKey?: `0x${string}`;
4
4
  /** Solana Mainnet base58 private key funding micro-payments */
@@ -8,7 +8,7 @@ export interface WarpPayConfig {
8
8
  /** Custom Solana RPC URL */
9
9
  solanaRpcUrl?: string;
10
10
  }
11
- export declare class WarpPayClient {
11
+ declare class WarpPayClient {
12
12
  private baseUrl;
13
13
  private account?;
14
14
  private solanaKeypair?;
@@ -25,3 +25,5 @@ export declare class WarpPayClient {
25
25
  renderScreenshot(url: string): Promise<any>;
26
26
  extractJson(url: string, schema?: object): Promise<any>;
27
27
  }
28
+
29
+ export { WarpPayClient, type WarpPayConfig };
package/dist/index.js CHANGED
@@ -1,191 +1,200 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.WarpPayClient = void 0;
7
- const node_crypto_1 = __importDefault(require("node:crypto"));
8
- const node_buffer_1 = require("node:buffer");
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"));
13
- class WarpPayClient {
14
- baseUrl;
15
- account;
16
- solanaKeypair;
17
- solanaConnection;
18
- constructor(config) {
19
- this.baseUrl = (config.baseUrl || "https://api.warppay402.com").replace(/\/$/, "");
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
- }
35
- }
36
- /**
37
- * Handles multi-chain HTTP 402 Payment Required challenges dynamically.
38
- */
39
- async executePaidRequest(endpoint, payload, method = "POST") {
40
- const url = `${this.baseUrl}${endpoint}`;
41
- console.log(`\n🔍 [SDK DEBUG] Initiating ${method} request to: ${url}`);
42
- const fetchOptions = {
43
- method,
44
- headers: { "Content-Type": "application/json" },
45
- };
46
- if (method === "POST" && payload) {
47
- fetchOptions.body = JSON.stringify(payload);
48
- console.log(`🔍 [SDK DEBUG] Request Payload:`, JSON.stringify(payload));
49
- }
50
- // 1. Initial Request Probe
51
- let response = await fetch(url, fetchOptions);
52
- console.log(`🔍 [SDK DEBUG] Probe Response Status: ${response.status} ${response.statusText}`);
53
- // 2. Multi-Chain Settlement Challenge Response
54
- if (response.status === 402) {
55
- const challenge = await response.json();
56
- console.log(`🔍 [SDK DEBUG] Received 402 Challenge Payload:`, JSON.stringify(challenge, null, 2));
57
- const accepts = challenge.x402?.accepts || challenge.accepts || [];
58
- console.log(`🔍 [SDK DEBUG] Accepted Payment Rails (${accepts.length}):`, accepts.map((a) => a.network));
59
- const solanaReq = accepts.find((a) => a.network?.includes("solana"));
60
- const evmReq = accepts.find((a) => a.network?.includes("eip155"));
61
- let paymentPayload;
62
- if (solanaReq && this.solanaKeypair) {
63
- console.log(`🔍 [SDK DEBUG] Processing Solana L1 SPL Payment challenge...`);
64
- const payToPubkey = new web3_js_1.PublicKey(solanaReq.payTo);
65
- const usdcMint = new web3_js_1.PublicKey(solanaReq.asset || "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
66
- const amountUnits = BigInt(solanaReq.amount || solanaReq.maxAmountRequired || "10000");
67
- const senderPubkey = this.solanaKeypair.publicKey;
68
- const senderAta = await (0, spl_token_1.getAssociatedTokenAddress)(usdcMint, senderPubkey);
69
- const recipientAta = await (0, spl_token_1.getAssociatedTokenAddress)(usdcMint, payToPubkey);
70
- const tx = new web3_js_1.Transaction();
71
- tx.feePayer = senderPubkey;
72
- tx.recentBlockhash = (await this.solanaConnection.getLatestBlockhash()).blockhash;
73
- tx.add((0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(senderPubkey, recipientAta, payToPubkey, usdcMint));
74
- tx.add((0, spl_token_1.createTransferInstruction)(senderAta, recipientAta, senderPubkey, amountUnits));
75
- tx.sign(this.solanaKeypair);
76
- const serializedTx = node_buffer_1.Buffer.from(tx.serialize()).toString("base64");
77
- paymentPayload = {
78
- x402Version: 2,
79
- scheme: solanaReq.scheme || "exact",
80
- network: solanaReq.network || "solana:5eykt4wA89m8E5b9B5658p445VTc28",
81
- signature: serializedTx,
82
- paymentPayload: {
83
- signature: serializedTx,
84
- network: solanaReq.network
85
- }
86
- };
87
- }
88
- else if (evmReq && this.account) {
89
- console.log(`🔍 [SDK DEBUG] Processing EVM EIP-712 Payment challenge...`);
90
- const payTo = (evmReq.payToAddress || evmReq.payTo);
91
- const assetContract = (evmReq.asset || evmReq.usdcAddress);
92
- const value = BigInt(evmReq.maxAmountRequired || evmReq.amount || "10000");
93
- console.log(`🔍 [SDK DEBUG] Signer Wallet: ${this.account.address} -> PayTo: ${payTo} | Amount: ${value.toString()}`);
94
- const domain = {
95
- name: evmReq.extra?.name || "USD Coin",
96
- version: evmReq.extra?.version || "2",
97
- chainId: 8453,
98
- verifyingContract: assetContract,
99
- };
100
- const types = {
101
- TransferWithAuthorization: [
102
- { name: "from", type: "address" },
103
- { name: "to", type: "address" },
104
- { name: "value", type: "uint256" },
105
- { name: "validAfter", type: "uint256" },
106
- { name: "validBefore", type: "uint256" },
107
- { name: "nonce", type: "bytes32" },
108
- ],
109
- };
110
- const now = Math.floor(Date.now() / 1000);
111
- const nonce = `0x${node_crypto_1.default.randomBytes(32).toString("hex")}`;
112
- const message = {
113
- from: this.account.address,
114
- to: payTo,
115
- value,
116
- validAfter: BigInt(0),
117
- validBefore: BigInt(now + 3600),
118
- nonce,
119
- };
120
- const signature = await this.account.signTypedData({
121
- domain,
122
- types,
123
- primaryType: "TransferWithAuthorization",
124
- message,
125
- });
126
- paymentPayload = {
127
- x402Version: 2,
128
- scheme: evmReq.scheme || "exact",
129
- network: evmReq.network || "eip155:8453",
130
- authorization: {
131
- from: this.account.address,
132
- to: payTo,
133
- value: value.toString(),
134
- validAfter: "0",
135
- validBefore: (now + 3600).toString(),
136
- nonce,
137
- },
138
- signature,
139
- };
140
- }
141
- else {
142
- console.error(`❌ [SDK DEBUG] Matching key missing! EVM Account Present: ${Boolean(this.account)} | Solana Keypair Present: ${Boolean(this.solanaKeypair)}`);
143
- throw new Error("No matching private key configured for returned 402 networks.");
144
- }
145
- const encodedPayload = node_buffer_1.Buffer.from(JSON.stringify(paymentPayload)).toString("base64");
146
- console.log(`🔍 [SDK DEBUG] Generated Signed x402 Base64 Header (Length: ${encodedPayload.length})`);
147
- const retryHeaders = {
148
- "Content-Type": "application/json",
149
- "PAYMENT-SIGNATURE": encodedPayload,
150
- "X-PAYMENT-RESPONSE": encodedPayload,
151
- "X-PAYMENT": encodedPayload,
152
- "authorization": `Bearer ${encodedPayload}`,
153
- };
154
- const retryOptions = {
155
- method,
156
- headers: retryHeaders,
157
- };
158
- if (method === "POST" && payload) {
159
- retryOptions.body = JSON.stringify(payload);
160
- }
161
- console.log(`🔍 [SDK DEBUG] Resubmitting paid ${method} request to: ${url}`);
162
- response = await fetch(url, retryOptions);
163
- console.log(`🔍 [SDK DEBUG] Paid Retry Response Status: ${response.status} ${response.statusText}`);
164
- }
165
- if (!response.ok) {
166
- const errText = await response.text();
167
- console.error(`❌ [SDK DEBUG] Request Rejection Body:`, errText);
168
- throw new Error(`WarpPay API Error (${response.status}): ${errText}`);
169
- }
170
- return (await response.json());
1
+ // src/index.ts
2
+ import crypto from "crypto";
3
+ import { Buffer } from "buffer";
4
+ import { privateKeyToAccount } from "viem/accounts";
5
+ import { Keypair, Connection, Transaction, PublicKey } from "@solana/web3.js";
6
+ import {
7
+ getAssociatedTokenAddress,
8
+ createTransferInstruction,
9
+ createAssociatedTokenAccountIdempotentInstruction
10
+ } from "@solana/spl-token";
11
+ import bs58Module from "bs58";
12
+ var bs58 = bs58Module.default || bs58Module;
13
+ var WarpPayClient = class {
14
+ baseUrl;
15
+ account;
16
+ solanaKeypair;
17
+ solanaConnection;
18
+ constructor(config) {
19
+ this.baseUrl = (config.baseUrl || "https://api.warppay402.com").replace(/\/$/, "");
20
+ this.solanaConnection = new Connection(
21
+ config.solanaRpcUrl || "https://api.mainnet-beta.solana.com",
22
+ "confirmed"
23
+ );
24
+ if (config.privateKey) {
25
+ const rawKey = config.privateKey.trim();
26
+ const formattedKey = rawKey.startsWith("0x") ? rawKey : `0x${rawKey}`;
27
+ this.account = privateKeyToAccount(formattedKey);
171
28
  }
172
- async scrapeWeb(url) {
173
- return this.executePaidRequest("/api/v1/tools/web-scraper", { url });
29
+ if (config.solanaPrivateKey) {
30
+ const decodedSecret = bs58.decode(config.solanaPrivateKey.trim());
31
+ this.solanaKeypair = Keypair.fromSecretKey(decodedSecret);
174
32
  }
175
- async getBaseAnalytics(address) {
176
- return this.executePaidRequest("/api/v1/tools/base-analytics", { address });
33
+ if (!this.account && !this.solanaKeypair) {
34
+ throw new Error("WarpPayClient requires either a Base privateKey or a solanaPrivateKey.");
177
35
  }
178
- async extractPdf(pdfUrl) {
179
- return this.executePaidRequest("/api/v1/tools/pdf-extractor", { pdfUrl });
36
+ }
37
+ /**
38
+ * Handles multi-chain HTTP 402 Payment Required challenges dynamically.
39
+ */
40
+ async executePaidRequest(endpoint, payload, method = "POST") {
41
+ const url = `${this.baseUrl}${endpoint}`;
42
+ console.log(`
43
+ \u{1F50D} [SDK DEBUG] Initiating ${method} request to: ${url}`);
44
+ const fetchOptions = {
45
+ method,
46
+ headers: { "Content-Type": "application/json" }
47
+ };
48
+ if (method === "POST" && payload) {
49
+ fetchOptions.body = JSON.stringify(payload);
50
+ console.log(`\u{1F50D} [SDK DEBUG] Request Payload:`, JSON.stringify(payload));
180
51
  }
181
- async browserScrape(url) {
182
- return this.executePaidRequest("/api/v1/tools/browser-scraper", { url });
183
- }
184
- async renderScreenshot(url) {
185
- return this.executePaidRequest("/api/v1/tools/render-screenshot", { url });
52
+ let response = await fetch(url, fetchOptions);
53
+ console.log(`\u{1F50D} [SDK DEBUG] Probe Response Status: ${response.status} ${response.statusText}`);
54
+ if (response.status === 402) {
55
+ const challenge = await response.json();
56
+ console.log(`\u{1F50D} [SDK DEBUG] Received 402 Challenge Payload:`, JSON.stringify(challenge, null, 2));
57
+ const accepts = challenge.x402?.accepts || challenge.accepts || [];
58
+ console.log(`\u{1F50D} [SDK DEBUG] Accepted Payment Rails (${accepts.length}):`, accepts.map((a) => a.network));
59
+ const solanaReq = accepts.find((a) => a.network?.includes("solana"));
60
+ const evmReq = accepts.find((a) => a.network?.includes("eip155"));
61
+ let paymentPayload;
62
+ if (solanaReq && this.solanaKeypair) {
63
+ console.log(`\u{1F50D} [SDK DEBUG] Processing Solana L1 SPL Payment challenge...`);
64
+ const payToPubkey = new PublicKey(solanaReq.payTo);
65
+ const usdcMint = new PublicKey(solanaReq.asset || "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
66
+ const amountUnits = BigInt(solanaReq.amount || solanaReq.maxAmountRequired || "10000");
67
+ const senderPubkey = this.solanaKeypair.publicKey;
68
+ const senderAta = await getAssociatedTokenAddress(usdcMint, senderPubkey);
69
+ const recipientAta = await getAssociatedTokenAddress(usdcMint, payToPubkey);
70
+ const tx = new Transaction();
71
+ tx.feePayer = senderPubkey;
72
+ tx.recentBlockhash = (await this.solanaConnection.getLatestBlockhash()).blockhash;
73
+ tx.add(
74
+ createAssociatedTokenAccountIdempotentInstruction(
75
+ senderPubkey,
76
+ recipientAta,
77
+ payToPubkey,
78
+ usdcMint
79
+ )
80
+ );
81
+ tx.add(
82
+ createTransferInstruction(senderAta, recipientAta, senderPubkey, amountUnits)
83
+ );
84
+ tx.sign(this.solanaKeypair);
85
+ const serializedTx = Buffer.from(tx.serialize()).toString("base64");
86
+ paymentPayload = {
87
+ x402Version: 2,
88
+ scheme: solanaReq.scheme || "exact",
89
+ network: solanaReq.network || "solana:5eykt4wA89m8E5b9B5658p445VTc28",
90
+ signature: serializedTx,
91
+ paymentPayload: {
92
+ signature: serializedTx,
93
+ network: solanaReq.network
94
+ }
95
+ };
96
+ } else if (evmReq && this.account) {
97
+ console.log(`\u{1F50D} [SDK DEBUG] Processing EVM EIP-712 Payment challenge...`);
98
+ const payTo = evmReq.payToAddress || evmReq.payTo;
99
+ const assetContract = evmReq.asset || evmReq.usdcAddress;
100
+ const value = BigInt(evmReq.maxAmountRequired || evmReq.amount || "10000");
101
+ console.log(`\u{1F50D} [SDK DEBUG] Signer Wallet: ${this.account.address} -> PayTo: ${payTo} | Amount: ${value.toString()}`);
102
+ const domain = {
103
+ name: evmReq.extra?.name || "USD Coin",
104
+ version: evmReq.extra?.version || "2",
105
+ chainId: 8453,
106
+ verifyingContract: assetContract
107
+ };
108
+ const types = {
109
+ TransferWithAuthorization: [
110
+ { name: "from", type: "address" },
111
+ { name: "to", type: "address" },
112
+ { name: "value", type: "uint256" },
113
+ { name: "validAfter", type: "uint256" },
114
+ { name: "validBefore", type: "uint256" },
115
+ { name: "nonce", type: "bytes32" }
116
+ ]
117
+ };
118
+ const now = Math.floor(Date.now() / 1e3);
119
+ const nonce = `0x${crypto.randomBytes(32).toString("hex")}`;
120
+ const message = {
121
+ from: this.account.address,
122
+ to: payTo,
123
+ value,
124
+ validAfter: BigInt(0),
125
+ validBefore: BigInt(now + 3600),
126
+ nonce
127
+ };
128
+ const signature = await this.account.signTypedData({
129
+ domain,
130
+ types,
131
+ primaryType: "TransferWithAuthorization",
132
+ message
133
+ });
134
+ paymentPayload = {
135
+ x402Version: 2,
136
+ scheme: evmReq.scheme || "exact",
137
+ network: evmReq.network || "eip155:8453",
138
+ authorization: {
139
+ from: this.account.address,
140
+ to: payTo,
141
+ value: value.toString(),
142
+ validAfter: "0",
143
+ validBefore: (now + 3600).toString(),
144
+ nonce
145
+ },
146
+ signature
147
+ };
148
+ } else {
149
+ console.error(`\u274C [SDK DEBUG] Matching key missing! EVM Account Present: ${Boolean(this.account)} | Solana Keypair Present: ${Boolean(this.solanaKeypair)}`);
150
+ throw new Error("No matching private key configured for returned 402 networks.");
151
+ }
152
+ const encodedPayload = Buffer.from(JSON.stringify(paymentPayload)).toString("base64");
153
+ console.log(`\u{1F50D} [SDK DEBUG] Generated Signed x402 Base64 Header (Length: ${encodedPayload.length})`);
154
+ const retryHeaders = {
155
+ "Content-Type": "application/json",
156
+ "PAYMENT-SIGNATURE": encodedPayload,
157
+ "X-PAYMENT-RESPONSE": encodedPayload,
158
+ "X-PAYMENT": encodedPayload,
159
+ "authorization": `Bearer ${encodedPayload}`
160
+ };
161
+ const retryOptions = {
162
+ method,
163
+ headers: retryHeaders
164
+ };
165
+ if (method === "POST" && payload) {
166
+ retryOptions.body = JSON.stringify(payload);
167
+ }
168
+ console.log(`\u{1F50D} [SDK DEBUG] Resubmitting paid ${method} request to: ${url}`);
169
+ response = await fetch(url, retryOptions);
170
+ console.log(`\u{1F50D} [SDK DEBUG] Paid Retry Response Status: ${response.status} ${response.statusText}`);
186
171
  }
187
- async extractJson(url, schema) {
188
- return this.executePaidRequest("/api/v1/tools/extract-json", { url, schema });
172
+ if (!response.ok) {
173
+ const errText = await response.text();
174
+ console.error(`\u274C [SDK DEBUG] Request Rejection Body:`, errText);
175
+ throw new Error(`WarpPay API Error (${response.status}): ${errText}`);
189
176
  }
190
- }
191
- exports.WarpPayClient = WarpPayClient;
177
+ return await response.json();
178
+ }
179
+ async scrapeWeb(url) {
180
+ return this.executePaidRequest("/api/v1/tools/web-scraper", { url });
181
+ }
182
+ async getBaseAnalytics(address) {
183
+ return this.executePaidRequest("/api/v1/tools/base-analytics", { address });
184
+ }
185
+ async extractPdf(pdfUrl) {
186
+ return this.executePaidRequest("/api/v1/tools/pdf-extractor", { pdfUrl });
187
+ }
188
+ async browserScrape(url) {
189
+ return this.executePaidRequest("/api/v1/tools/browser-scraper", { url });
190
+ }
191
+ async renderScreenshot(url) {
192
+ return this.executePaidRequest("/api/v1/tools/render-screenshot", { url });
193
+ }
194
+ async extractJson(url, schema) {
195
+ return this.executePaidRequest("/api/v1/tools/extract-json", { url, schema });
196
+ }
197
+ };
198
+ export {
199
+ WarpPayClient
200
+ };
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "warppay402-sdk",
3
3
  "name": "warppay402-sdk",
4
- "version": "1.1.5",
4
+ "version": "1.1.8",
5
5
  "description": "Official WarpPay402 TypeScript SDK: Enabling seamless pay-per-use AI tools across Base Mainnet, Solana, and Arbitrum One."
6
- }
6
+ }
package/package.json CHANGED
@@ -1,13 +1,23 @@
1
-
2
1
  {
3
2
  "name": "@warppay402/sdk",
4
- "version": "1.1.5",
3
+ "version": "1.1.8",
5
4
  "license": "MIT",
6
5
  "description": "Official WarpPay402 TypeScript SDK: Enabling seamless pay-per-use AI tools across Base Mainnet, Solana, and Arbitrum One.",
7
- "main": "dist/index.js",
8
- "types": "dist/index.d.ts",
6
+ "type": "module",
7
+ "main": "./dist/index.cjs",
8
+ "module": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js",
14
+ "require": "./dist/index.cjs"
15
+ }
16
+ },
9
17
  "scripts": {
10
- "build": "tsc"
18
+ "build": "tsup src/index.ts --format cjs,esm --dts --clean --external viem,@solana/web3.js,@solana/spl-token",
19
+ "prepublishOnly": "npm run build",
20
+ "version": "node -e \"const fs = require('fs'); const p = JSON.parse(fs.readFileSync('openclaw.plugin.json')); p.version = process.env.npm_package_version; fs.writeFileSync('openclaw.plugin.json', JSON.stringify(p, null, 2) + '\\n');\" && git add openclaw.plugin.json"
11
21
  },
12
22
  "repository": {
13
23
  "type": "git",
@@ -36,6 +46,7 @@
36
46
  },
37
47
  "devDependencies": {
38
48
  "@types/node": "^26.2.0",
49
+ "tsup": "^8.5.1",
39
50
  "typescript": "^5.0.0"
40
51
  },
41
52
  "openclaw": {
@@ -59,4 +70,4 @@
59
70
  }
60
71
  }
61
72
  }
62
- }
73
+ }
@@ -1,23 +0,0 @@
1
- import { WarpPayClient } from "./index.js";
2
- /**
3
- * Generates LangChain-compatible tool definitions initialized with WarpPay402
4
- */
5
- export declare function createWarpPayLangChainTools(client: WarpPayClient): ({
6
- name: string;
7
- description: string;
8
- func: ({ url }: {
9
- url: string;
10
- }) => Promise<any>;
11
- } | {
12
- name: string;
13
- description: string;
14
- func: ({ address }: {
15
- address: string;
16
- }) => Promise<string>;
17
- } | {
18
- name: string;
19
- description: string;
20
- func: ({ pdfUrl }: {
21
- pdfUrl: string;
22
- }) => Promise<any>;
23
- })[];
package/dist/langchain.js DELETED
@@ -1,34 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createWarpPayLangChainTools = createWarpPayLangChainTools;
4
- /**
5
- * Generates LangChain-compatible tool definitions initialized with WarpPay402
6
- */
7
- function createWarpPayLangChainTools(client) {
8
- return [
9
- {
10
- name: "web_scraper",
11
- description: "Scrapes a web page URL and returns clean markdown content. Costs $0.01 USDC on Base.",
12
- func: async ({ url }) => {
13
- const result = await client.scrapeWeb(url);
14
- return result.markdown;
15
- },
16
- },
17
- {
18
- name: "base_analytics",
19
- description: "Fetches ETH balance and nonce for a Base 0x wallet address. Costs $0.02 USDC on Base.",
20
- func: async ({ address }) => {
21
- const result = await client.getBaseAnalytics(address);
22
- return JSON.stringify(result);
23
- },
24
- },
25
- {
26
- name: "pdf_extractor",
27
- description: "Extracts text preview from a public PDF URL. Costs $0.05 USDC on Base.",
28
- func: async ({ pdfUrl }) => {
29
- const result = await client.extractPdf(pdfUrl);
30
- return result.textPreview;
31
- },
32
- },
33
- ];
34
- }