apinow-sdk 0.12.5 → 0.12.6

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
@@ -7,6 +7,7 @@ A TypeScript SDK for interacting with ApiNow endpoints, supporting Ethereum and
7
7
  - **Automatic x402 Payments**: Intercepts `402` responses to handle payment flows automatically.
8
8
  - **On-the-fly Token Swaps**: If you don't have the required payment token, the SDK can swap a common asset (like ETH, WETH, or USDC) to make the payment, powered by 0x.
9
9
  - **Flexible Pricing**: Supports endpoints that require a fixed token amount or a USD equivalent.
10
+ - **Endpoint Discovery**: Includes a `search` method to find endpoints semantically.
10
11
  - **Configurable Payment**: Prioritize which tokens you prefer to pay with.
11
12
  - **Multi-chain support**: Works with Ethereum and Base.
12
13
  - **Node.js Environment**: Designed to work in a Node.js environment.
@@ -19,33 +20,31 @@ npm install apinow-sdk
19
20
  yarn add apinow-sdk
20
21
  ```
21
22
 
22
- ## Usage
23
+ ## Quick Example
23
24
 
24
25
  The primary way to use the SDK is with the `execute` method. It's a single call that handles all the complexity of API payments for you.
25
26
 
26
27
  ```typescript
27
28
  import apiNow from 'apinow-sdk';
28
29
 
29
- // The API endpoint you want to interact with.
30
- const ENDPOINT_URL = 'https://apinow.fun/api/endpoints/your-endpoint';
31
-
32
30
  // Your private key, securely stored (e.g., in an environment variable).
33
- const YOUR_WALLET_PRIVATE_KEY = '0x...';
31
+ const YOUR_WALLET_PRIVATE_KEY = process.env.USER_PRIVATE_KEY;
34
32
 
35
33
  async function main() {
36
34
  try {
37
35
  // The `execute` method handles everything automatically.
38
- // If the API requires a payment (402), the SDK will:
39
- // 1. Find the best token you hold to pay with.
40
- // 2. If needed, swap a common asset (like ETH or USDC) to the required token.
41
- // 3. Send the payment transaction.
42
- // 4. Retry the original request with proof of payment.
36
+ // If the API requires a payment (402), the SDK will find the best
37
+ // token you hold, swap if necessary, send the payment, and retry
38
+ // the original request with proof of payment.
43
39
  const response = await apiNow.execute(
44
- ENDPOINT_URL,
40
+ 'https://apinow.fun/api/endpoints/apinowfun/translate-TRANSLATE',
45
41
  YOUR_WALLET_PRIVATE_KEY,
46
42
  { // Optional: request options
47
43
  method: 'POST',
48
- data: { query: 'your-data' }
44
+ data: {
45
+ text: 'Hello world',
46
+ selectedLanguage: 'es'
47
+ }
49
48
  }
50
49
  );
51
50
 
@@ -58,100 +57,28 @@ async function main() {
58
57
  main();
59
58
  ```
60
59
 
60
+ For a complete, runnable example, see [`example.js`](./example.js).
61
+
61
62
  ## How It Works: Automatic Payments
62
63
 
63
64
  When you call `execute`, the SDK makes a request to the endpoint. If the server responds with a `402 Payment Required` status, the SDK automatically performs the following steps:
64
65
 
65
- 1. **Parses Payment Options**: The `402` response contains a list of accepted payment options. This can be a single token (fixed price) or multiple tokens (USD equivalent price, e.g., "$5 of USDC" or "$5 of ETH").
66
+ 1. **Parses Payment Options**: The `402` response contains a list of accepted payment options.
66
67
  2. **Checks Balances**: It checks your wallet balance for each of the accepted payment tokens.
67
68
  3. **Prioritizes Payment**: It attempts to pay using your tokens in a preferred order (default: `['USDC', 'WETH', 'ETH']`).
68
- 4. **Swaps if Needed**: If you don't have any of the *required* tokens, the SDK will try to swap one of your preferred assets for the required one. For example, it can swap your USDC to pay with a different required token.
69
+ 4. **Swaps if Needed**: If you don't have any of the *required* tokens, the SDK will try to swap one of your preferred assets for the required one.
69
70
  5. **Pays and Retries**: Once the payment transaction is sent, the SDK automatically retries the original API request, now with proof of payment.
70
71
 
71
- ## Configuration
72
-
73
- You can customize the behavior of the `execute` method with the `opts` and `paymentConfig` parameters.
74
-
75
- ### Request Options (`opts`)
76
-
77
- Passed as the third argument to `execute`. This corresponds to `TxResponseOptions`.
78
-
79
- - `method`: The HTTP method for your request (e.g., `'GET'`, `'POST'`). Defaults to `'GET'`.
80
- - `data`: The payload for your request. For `POST` requests, this is the JSON body. For `GET`, it's converted to query parameters.
81
-
82
- ### Payment Configuration (`paymentConfig`)
83
-
84
- Passed as the fourth argument to `execute`. This corresponds to `X402PaymentConfig`.
85
-
86
- - `preferredTokens`: An array of token symbols (e.g., `['USDC', 'WETH']`) that you prefer to pay with. The SDK will check your balance of these tokens first.
87
-
88
- ```typescript
89
- await apiNow.execute(
90
- ENDPOINT_URL,
91
- YOUR_WALLET_PRIVATE_KEY,
92
- { method: 'POST', data: { /* ... */ } }, // opts
93
- { preferredTokens: ['DAI', 'USDC'] } // paymentConfig
94
- );
95
- ```
96
-
97
- ## Legacy Flow (Backward Compatibility)
98
-
99
- For backward compatibility, the `infoBuyResponse` method is still available. It performs a less sophisticated multi-step payment process.
100
-
101
- ```typescript
102
- const response = await apiNow.infoBuyResponse(
103
- ENDPOINT_URL,
104
- YOUR_WALLET_PRIVATE_KEY
105
- );
106
- ```
107
-
108
72
  ## API Reference
109
73
 
110
74
  ### `execute(endpoint, privateKey, opts?, paymentConfig?)`
111
75
  Handles a request and its potential payment in a single, automatic call. This is the recommended method.
112
76
 
113
- ### `infoBuyResponse(endpoint, privateKey, rpcUrl?, opts?)`
114
- (Legacy) Combines `info`, `buy`, and `txResponse` into a single call.
115
-
116
- ### `info(endpoint)`
117
- (Legacy) Gets payment requirement information from an endpoint.
118
-
119
- ### `buy(walletAddress, amount, privateKey, chain, ...)`
120
- (Legacy) Sends a payment transaction.
121
-
122
- ### `txResponse(endpoint, txHash, opts?)`
123
- (Legacy) Fetches the API response after a payment has been made manually.
77
+ ### `search(params, privateKey, paymentConfig?)`
78
+ Performs a semantic search for endpoints.
124
79
 
125
- ## Types
126
-
127
- ```typescript
128
- // Response from a 402 error
129
- interface X402PaymentInfo {
130
- challenge: string;
131
- chain: 'eth' | 'base';
132
- recipientAddress: string;
133
- options: X402PaymentOption[];
134
- }
135
-
136
- // A single way to pay
137
- interface X402PaymentOption {
138
- tokenAddress: string;
139
- symbol: string;
140
- amount: string;
141
- decimals: number;
142
- }
143
-
144
- // Configuration for payments
145
- interface X402PaymentConfig {
146
- preferredTokens?: string[];
147
- }
148
-
149
- // Options for the API request itself
150
- interface TxResponseOptions {
151
- method?: string;
152
- data?: any;
153
- }
154
- ```
80
+ ### `info(endpointUrl)`
81
+ Retrieves public, detailed information about an endpoint.
155
82
 
156
83
  ## Default RPC URLs
157
84
 
@@ -179,47 +106,3 @@ It is NOT directly compatible with browsers or edge environments that do not pro
179
106
  ## License
180
107
 
181
108
  MIT
182
-
183
- ## Examples
184
-
185
- This project includes a test server and a test runner to demonstrate various payment scenarios.
186
-
187
- 1. **Create a `.env` file** in the root of the project and add your wallet's private key:
188
- ```
189
- PRIVATE_KEY=your_private_key_here
190
- ```
191
-
192
- 2. **Install dependencies:**
193
- ```bash
194
- npm install
195
- ```
196
-
197
- 3. **Start the test server:**
198
- The test server simulates an API that requires different types of payments.
199
- ```bash
200
- node test/test-server.js
201
- ```
202
-
203
- 4. **Run the test runner:**
204
- In a separate terminal, run the test runner to execute a series of transactions against the test server.
205
- ```bash
206
- node test/test-runner.js
207
- ```
208
-
209
- This will demonstrate:
210
- - Paying with USDC
211
- - Paying with a custom ERC20 token
212
- - Paying with a token priced in USDC
213
- - Fallback token payments
214
- - Handling various error conditions
215
-
216
- ## Local Development
217
-
218
- 1. **Build the project:**
219
- ```bash
220
- npm run build
221
- ```
222
-
223
- This will compile the TypeScript source files into JavaScript in the `dist` directory.
224
-
225
- ## Contributing
package/dist/index.d.ts CHANGED
@@ -4,13 +4,35 @@ interface TxResponseOptions {
4
4
  data?: any;
5
5
  signature?: string;
6
6
  }
7
- interface InfoResponse {
8
- requiredAmount: string;
7
+ interface PaymentOption {
8
+ tokenAddress: string;
9
+ symbol: string;
10
+ amount?: string;
11
+ usdAmount?: string;
12
+ decimals: number;
13
+ }
14
+ interface EndpointInfo {
15
+ namespace: string;
16
+ endpointName: string;
17
+ description: string;
9
18
  walletAddress: string;
19
+ paymentOptions: PaymentOption[];
10
20
  httpMethod: string;
11
- tokenAddress?: string;
12
- chain: 'eth' | 'base';
13
- decimals?: number;
21
+ querySchema?: any;
22
+ docsUrl?: string;
23
+ status: string;
24
+ chain: 'eth' | 'sol' | 'base';
25
+ url: string;
26
+ lastTx?: {
27
+ txHash: string;
28
+ chain: 'eth' | 'sol';
29
+ timestamp: string;
30
+ };
31
+ }
32
+ interface SearchParams {
33
+ query: string;
34
+ limit?: number;
35
+ minScore?: number;
14
36
  }
15
37
  interface X402PaymentOption {
16
38
  tokenAddress: string;
@@ -36,16 +58,14 @@ interface X402PaymentConfig {
36
58
  declare function get0xSwapQuote(buyToken: string, sellToken: string, buyAmount: bigint, buyTokenDecimals: number, takerAddress: string, chain: 'eth' | 'base', slippagePercentage?: string): Promise<any>;
37
59
  declare class ApiNow {
38
60
  private handlers;
39
- info(endpoint: string): Promise<InfoResponse>;
61
+ info(endpointUrl: string): Promise<EndpointInfo>;
62
+ search(params: SearchParams, userWalletPrivateKey: string, paymentConfig?: X402PaymentConfig): Promise<any>;
40
63
  buy(walletAddress: string, amount: bigint, userWalletPrivateKey: string, chain: 'eth' | 'base', rpcUrl?: string, tokenAddress?: string, fastMode?: boolean): Promise<string>;
41
64
  execute(endpoint: string, userWalletPrivateKey: string, opts?: TxResponseOptions, paymentConfig?: X402PaymentConfig): Promise<any>;
42
65
  approve(wallet: Wallet, tokenAddress: string, spenderAddress: string, amount: bigint): Promise<string>;
43
66
  txResponse(endpoint: string, txHash: string, opts?: TxResponseOptions): Promise<any>;
44
- infoBuyResponse(endpoint: string, userWalletPrivateKey: string, rpcUrl?: string, opts?: TxResponseOptions & {
45
- fastMode?: boolean;
46
- }): Promise<any>;
47
67
  }
48
68
  declare const apiNow: ApiNow;
49
69
  export default apiNow;
50
70
  export { get0xSwapQuote };
51
- export type { InfoResponse, TxResponseOptions, X402PaymentInfo, X402PaymentOption, X402PaymentConfig };
71
+ export type { TxResponseOptions, X402PaymentInfo, X402PaymentOption, X402PaymentConfig, EndpointInfo, SearchParams, PaymentOption };
package/dist/index.js CHANGED
@@ -519,18 +519,42 @@ class ApiNow {
519
519
  base: new EthereumHandler()
520
520
  };
521
521
  }
522
- async info(endpoint) {
523
- if (!endpoint || typeof endpoint !== 'string') {
524
- throw new Error('Invalid endpoint URL');
525
- }
522
+ async info(endpointUrl) {
523
+ if (!endpointUrl || typeof endpointUrl !== 'string') {
524
+ throw new Error('Invalid endpoint URL provided.');
525
+ }
526
+ // Ensure the URL doesn't already end in /details before appending
527
+ const detailsUrl = endpointUrl.endsWith('/details')
528
+ ? endpointUrl
529
+ : `${endpointUrl}/details`;
530
+ console.log(`[sdk] Fetching public info from: ${detailsUrl}`);
526
531
  try {
527
- return await fetchJson(endpoint);
532
+ // Using a simple fetch as this is a public, non-paying endpoint
533
+ const response = await fetch(detailsUrl);
534
+ if (!response.ok) {
535
+ const errorBody = await response.text();
536
+ throw new Error(`Failed to fetch endpoint info (${response.status}): ${errorBody}`);
537
+ }
538
+ return await response.json();
528
539
  }
529
540
  catch (error) {
530
- console.error(`Failed to fetch info from ${endpoint}:`, error);
531
- throw new Error(`Could not get endpoint info: ${error instanceof Error ? error.message : String(error)}`);
541
+ console.error(`[sdk] Error in info():`, error);
542
+ const message = error instanceof Error ? error.message : String(error);
543
+ throw new Error(`Could not get endpoint info: ${message}`);
532
544
  }
533
545
  }
546
+ async search(params, userWalletPrivateKey, paymentConfig = {}) {
547
+ const searchEndpoint = 'https://apinow.fun/api/endpoints/apinowfun/endpoint-search';
548
+ console.log(`[sdk] Performing semantic search with query: "${params.query}"`);
549
+ if (!params.query || typeof params.query !== 'string' || params.query.trim() === '') {
550
+ throw new Error('A non-empty search query string is required.');
551
+ }
552
+ // Reuse the existing execute method to handle the x402 payment flow
553
+ return this.execute(searchEndpoint, userWalletPrivateKey, {
554
+ method: 'POST',
555
+ data: params, // The search parameters become the body of the POST request
556
+ }, paymentConfig);
557
+ }
534
558
  async buy(walletAddress, amount, userWalletPrivateKey, chain, rpcUrl, tokenAddress, fastMode) {
535
559
  const handler = this.handlers[chain];
536
560
  if (!handler) {
@@ -643,48 +667,6 @@ class ApiNow {
643
667
  throw new Error(`Could not get transaction response: ${error instanceof Error ? error.message : String(error)}`);
644
668
  }
645
669
  }
646
- async infoBuyResponse(endpoint, userWalletPrivateKey, rpcUrl, opts = {}) {
647
- console.error(`Starting infoBuyResponse for endpoint: ${endpoint}`);
648
- const info = await this.info(endpoint);
649
- console.error("Received info:", info);
650
- const { requiredAmount, walletAddress, chain, tokenAddress, decimals } = info;
651
- if (!chain || !this.handlers[chain]) {
652
- throw new Error(`Unsupported chain specified by endpoint: ${chain}`);
653
- }
654
- let amountBigInt;
655
- try {
656
- // Use info.decimals if available, otherwise default to 18 (for ETH)
657
- const parseDecimals = (tokenAddress && decimals !== undefined) ? decimals : 18;
658
- amountBigInt = parseUnits(requiredAmount, parseDecimals);
659
- if (amountBigInt <= 0n) {
660
- throw new Error('Required amount must be positive.');
661
- }
662
- }
663
- catch (e) {
664
- throw new Error(`Invalid requiredAmount format or value: ${requiredAmount}. Could not parse with ${(tokenAddress && decimals !== undefined) ? decimals : 18} decimals.`);
665
- }
666
- console.error(`Attempting payment: Chain=${chain}, To=${walletAddress}, Amount=${amountBigInt.toString()}, Token=${tokenAddress || 'Native'}`);
667
- const txHash = await this.buy(walletAddress, amountBigInt, userWalletPrivateKey, chain, rpcUrl, tokenAddress, opts.fastMode);
668
- console.error(`Transaction sent: ${txHash}`);
669
- const wallet = new Wallet(userWalletPrivateKey);
670
- const signature = await wallet.signMessage(txHash);
671
- console.error(`Generated signature for txHash ${txHash}: ${signature}`);
672
- if (!opts.fastMode) {
673
- await new Promise(resolve => setTimeout(resolve, 3000));
674
- }
675
- else {
676
- await new Promise(resolve => setTimeout(resolve, 500));
677
- }
678
- console.error(`Fetching response for tx: ${txHash}`);
679
- // Create specific options for txResponse
680
- const txResponseOpts = {
681
- method: info.httpMethod || 'POST', // Use the method from info, default to POST
682
- data: opts.data, // Pass the original data payload intended for the API
683
- signature: signature
684
- };
685
- // Call txResponse with the tailored options
686
- return this.txResponse(endpoint, txHash, txResponseOpts);
687
- }
688
670
  }
689
671
  const apiNow = new ApiNow();
690
672
  export default apiNow;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apinow-sdk",
3
- "version": "0.12.5",
3
+ "version": "0.12.6",
4
4
  "description": "ApiNow SDK · The endpoint vending machine",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",