apinow-sdk 0.7.0 → 0.8.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 ADDED
@@ -0,0 +1,162 @@
1
+ # ApiNow SDK
2
+
3
+ A TypeScript SDK for interacting with ApiNow endpoints, supporting Ethereum (including Base), and Solana chains.
4
+
5
+ ## Features
6
+
7
+ - Multi-chain support (Ethereum, Base, Solana)
8
+ - Token transfers (ERC20 on ETH/Base, SPL on Solana)
9
+ - Fast mode for quicker transaction processing
10
+ - TypeScript types for better development experience
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ npm install apinow-sdk
16
+ ```
17
+
18
+ ## Usage
19
+
20
+ ### Basic Example
21
+
22
+ ```typescript
23
+ import apiNow from 'apinow-sdk';
24
+
25
+ // Get endpoint info
26
+ const info = await apiNow.info('https://apinow.fun/api/endpoints/your-endpoint');
27
+
28
+ // Send payment and get response
29
+ const response = await apiNow.infoBuyResponse(
30
+ 'https://apinow.fun/api/endpoints/your-endpoint',
31
+ 'YOUR_PRIVATE_KEY',
32
+ 'YOUR_RPC_URL'
33
+ );
34
+ ```
35
+
36
+ ### Fast Mode
37
+
38
+ Fast mode skips transaction confirmation and only waits for the transaction to be in the mempool. This provides much faster responses but slightly less security:
39
+
40
+ ```typescript
41
+ const response = await apiNow.infoBuyResponse(
42
+ 'https://apinow.fun/api/endpoints/your-endpoint',
43
+ 'YOUR_PRIVATE_KEY',
44
+ 'YOUR_RPC_URL',
45
+ { fastMode: true }
46
+ );
47
+ ```
48
+
49
+ ### Chain-Specific Examples
50
+
51
+ #### Ethereum/Base
52
+
53
+ ```typescript
54
+ // Native ETH/BASE transfer
55
+ const txHash = await apiNow.buy(
56
+ 'RECIPIENT_ADDRESS',
57
+ ethers.parseEther('0.1'),
58
+ 'YOUR_PRIVATE_KEY',
59
+ 'YOUR_RPC_URL',
60
+ 'eth'
61
+ );
62
+
63
+ // ERC20 token transfer
64
+ const txHash = await apiNow.buy(
65
+ 'RECIPIENT_ADDRESS',
66
+ ethers.parseUnits('100', 18), // Use appropriate decimals
67
+ 'YOUR_PRIVATE_KEY',
68
+ 'YOUR_RPC_URL',
69
+ 'eth',
70
+ 'TOKEN_ADDRESS'
71
+ );
72
+ ```
73
+
74
+ #### Solana
75
+
76
+ ```typescript
77
+ // Native SOL transfer
78
+ const txHash = await apiNow.buy(
79
+ 'RECIPIENT_ADDRESS',
80
+ BigInt(LAMPORTS_PER_SOL), // 1 SOL
81
+ 'YOUR_PRIVATE_KEY',
82
+ 'YOUR_RPC_URL',
83
+ 'sol'
84
+ );
85
+
86
+ // SPL token transfer
87
+ const txHash = await apiNow.buy(
88
+ 'RECIPIENT_ADDRESS',
89
+ BigInt(1000000), // Amount in raw units (e.g. 1.0 for 6 decimals)
90
+ 'YOUR_PRIVATE_KEY',
91
+ 'YOUR_RPC_URL',
92
+ 'sol',
93
+ 'TOKEN_ADDRESS'
94
+ );
95
+ ```
96
+
97
+ ## API Reference
98
+
99
+ ### `info(endpoint: string): Promise<InfoResponse>`
100
+
101
+ Gets information about an endpoint.
102
+
103
+ ### `buy(walletAddress: string, amount: bigint, pkey: string, rpc: string, chain?: 'eth' | 'sol', tokenAddress?: string, fastMode?: boolean): Promise<string>`
104
+
105
+ Sends a payment transaction. For tokens, provide the amount in raw units (e.g. wei for ERC20, raw units for SPL).
106
+
107
+ ### `txResponse(endpoint: string, txHash: string, opts?: TxResponseOptions): Promise<any>`
108
+
109
+ Gets the API response for a transaction.
110
+
111
+ ### `infoBuyResponse(endpoint: string, pkey: string, rpc: string, opts?: TxResponseOptions & { fastMode?: boolean }): Promise<any>`
112
+
113
+ Combines info, buy, and txResponse into a single call.
114
+
115
+ ## Types
116
+
117
+ ```typescript
118
+ interface TxResponseOptions {
119
+ method?: string;
120
+ data?: any;
121
+ }
122
+
123
+ interface InfoResponse {
124
+ requiredAmount: string;
125
+ walletAddress: string;
126
+ httpMethod: string;
127
+ tokenAddress?: string;
128
+ chain: 'eth' | 'sol';
129
+ }
130
+ ```
131
+
132
+ ## Error Handling
133
+
134
+ The SDK throws descriptive errors for various failure cases:
135
+ - Invalid endpoint URLs
136
+ - Transaction failures
137
+ - Network issues
138
+ - Invalid addresses or amounts
139
+
140
+ ## License
141
+
142
+ MIT
143
+
144
+ Copyright (c) 2024 Your Name
145
+
146
+ Permission is hereby granted, free of charge, to any person obtaining a copy
147
+ of this software and associated documentation files (the "Software"), to deal
148
+ in the Software without restriction, including without limitation the rights
149
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
150
+ copies of the Software, and to permit persons to whom the Software is
151
+ furnished to do so, subject to the following conditions:
152
+
153
+ The above copyright notice and permission notice shall be included in all
154
+ copies or substantial portions of the Software.
155
+
156
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
157
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
158
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
159
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
160
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
161
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
162
+ SOFTWARE.
package/dist/index.js CHANGED
@@ -1,111 +1,47 @@
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
- const ethers_1 = require("ethers");
7
- const node_fetch_1 = __importDefault(require("node-fetch"));
8
- const web3_js_1 = require("@solana/web3.js");
9
- const spl_token_1 = require("@solana/spl-token");
10
- const bs58_1 = __importDefault(require("bs58"));
1
+ import { ethers } from 'ethers';
2
+ import fetch from 'node-fetch';
3
+ import { Connection, PublicKey, LAMPORTS_PER_SOL, Transaction, SystemProgram, Keypair, ComputeBudgetProgram } from '@solana/web3.js';
4
+ import { createTransferInstruction, getAssociatedTokenAddress, getMint } from '@solana/spl-token';
5
+ import bs58 from 'bs58';
11
6
  class EthereumHandler {
12
7
  async buy(walletAddress, amount, pkey, rpc, tokenAddress, fastMode) {
13
- console.log(`[EthereumHandler] Initiating transaction`);
14
- console.log(`[EthereumHandler] Transaction details:`, {
15
- recipient: walletAddress,
16
- amount: amount.toString(),
17
- rpc: rpc.substring(0, 20) + '...',
18
- hasTokenAddress: !!tokenAddress,
19
- fastMode
20
- });
21
8
  if (!rpc || typeof rpc !== 'string') {
22
- console.error(`[EthereumHandler] Invalid RPC URL: ${rpc}`);
23
9
  throw new Error('Invalid RPC URL');
24
10
  }
25
- if (!walletAddress || !ethers_1.ethers.isAddress(walletAddress)) {
26
- console.error(`[EthereumHandler] Invalid wallet address: ${walletAddress}`);
11
+ if (!walletAddress || !ethers.isAddress(walletAddress)) {
27
12
  throw new Error('Invalid wallet address');
28
13
  }
14
+ const provider = new ethers.JsonRpcProvider(rpc);
15
+ const wallet = new ethers.Wallet(pkey, provider);
29
16
  try {
30
- console.log(`[EthereumHandler] Creating provider with RPC: ${rpc.substring(0, 20)}...`);
31
- const provider = new ethers_1.ethers.JsonRpcProvider(rpc);
32
- console.log(`[EthereumHandler] Creating wallet from private key`);
33
- const wallet = new ethers_1.ethers.Wallet(pkey, provider);
34
- console.log(`[EthereumHandler] Wallet address: ${wallet.address}`);
35
- console.time(`[EthereumHandler] Get network`);
36
- const network = await provider.getNetwork();
37
- console.timeEnd(`[EthereumHandler] Get network`);
38
- console.log(`[EthereumHandler] Connected to network: ${network.name} (${network.chainId})`);
39
- console.time(`[EthereumHandler] Get balance`);
17
+ await provider.getNetwork();
40
18
  const balance = await provider.getBalance(wallet.address);
41
- console.timeEnd(`[EthereumHandler] Get balance`);
42
- console.log(`[EthereumHandler] Sender balance: ${ethers_1.ethers.formatEther(balance)} ETH`);
43
- if (balance < amount && !tokenAddress) {
44
- console.error(`[EthereumHandler] Insufficient balance: ${ethers_1.ethers.formatEther(balance)} ETH, required: ${ethers_1.ethers.formatEther(amount)} ETH`);
45
- throw new Error(`Insufficient balance: ${ethers_1.ethers.formatEther(balance)} ETH, required: ${ethers_1.ethers.formatEther(amount)} ETH`);
46
- }
47
- console.time(`[EthereumHandler] Get nonce`);
19
+ console.log('Sender balance:', ethers.formatEther(balance), 'ETH');
48
20
  const nonce = await provider.getTransactionCount(wallet.address, 'latest');
49
- console.timeEnd(`[EthereumHandler] Get nonce`);
50
- console.log(`[EthereumHandler] Nonce: ${nonce}`);
51
21
  const gasLimit = wallet.address.toLowerCase() === walletAddress.toLowerCase()
52
22
  ? 30000
53
23
  : 21000;
54
- console.log(`[EthereumHandler] Gas limit: ${gasLimit}`);
55
- let txHash;
56
24
  if (tokenAddress) {
57
- console.log(`[EthereumHandler] Executing ERC-20 token transfer`);
58
- console.log(`[EthereumHandler] Token address: ${tokenAddress}`);
59
25
  const abi = ["function transfer(address to, uint256 amount) returns (bool)"];
60
- console.log(`[EthereumHandler] Creating token contract instance`);
61
- const tokenContract = new ethers_1.ethers.Contract(tokenAddress, abi, wallet);
62
- console.time(`[EthereumHandler] Token transfer`);
63
- console.log(`[EthereumHandler] Transferring ${amount.toString()} tokens to ${walletAddress}`);
26
+ const tokenContract = new ethers.Contract(tokenAddress, abi, wallet);
64
27
  const tx = await tokenContract.transfer(walletAddress, amount);
65
- console.timeEnd(`[EthereumHandler] Token transfer`);
66
- console.log(`[EthereumHandler] Token transfer transaction hash: ${tx.hash}`);
67
- txHash = tx.hash;
28
+ return tx.hash;
68
29
  }
69
30
  else {
70
- console.log(`[EthereumHandler] Executing native token transfer`);
71
- console.time(`[EthereumHandler] Native transfer`);
72
- console.log(`[EthereumHandler] Transferring ${ethers_1.ethers.formatEther(amount)} ETH to ${walletAddress}`);
73
31
  const tx = await wallet.sendTransaction({
74
32
  to: walletAddress,
75
33
  value: amount,
76
34
  type: 2,
77
- maxFeePerGas: ethers_1.ethers.parseUnits('0.1', 'gwei'),
78
- maxPriorityFeePerGas: ethers_1.ethers.parseUnits('0.1', 'gwei'),
35
+ maxFeePerGas: ethers.parseUnits('0.1', 'gwei'),
36
+ maxPriorityFeePerGas: ethers.parseUnits('0.1', 'gwei'),
79
37
  gasLimit,
80
38
  nonce
81
39
  });
82
- console.timeEnd(`[EthereumHandler] Native transfer`);
83
- console.log(`[EthereumHandler] Native transfer transaction hash: ${tx.hash}`);
84
- txHash = tx.hash;
85
- }
86
- if (!fastMode) {
87
- console.log(`[EthereumHandler] Waiting for transaction confirmation...`);
88
- console.time(`[EthereumHandler] Transaction confirmation`);
89
- const receipt = await provider.waitForTransaction(txHash);
90
- console.timeEnd(`[EthereumHandler] Transaction confirmation`);
91
- console.log(`[EthereumHandler] Transaction confirmed:`, {
92
- blockNumber: receipt?.blockNumber,
93
- status: receipt?.status === 1 ? 'success' : 'failed',
94
- gasUsed: receipt?.gasUsed?.toString()
95
- });
96
- if (receipt?.status !== 1) {
97
- console.error(`[EthereumHandler] Transaction failed with status: ${receipt?.status}`);
98
- throw new Error('Transaction failed');
99
- }
100
- }
101
- else {
102
- console.log(`[EthereumHandler] Fast mode enabled, not waiting for confirmation`);
40
+ return tx.hash;
103
41
  }
104
- return txHash;
105
42
  }
106
43
  catch (error) {
107
- console.error(`[EthereumHandler] Transaction failed:`, error);
108
- console.error(`[EthereumHandler] Error stack:`, error instanceof Error ? error.stack : 'No stack trace');
44
+ console.error('Detailed error:', error);
109
45
  throw new Error(`Transaction failed: ${error instanceof Error ? error.message : String(error)}`);
110
46
  }
111
47
  }
@@ -115,47 +51,40 @@ class SolanaHandler {
115
51
  let lastError;
116
52
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
117
53
  try {
118
- console.log(`[SolanaHandler] Attempt ${attempt}/${maxAttempts}`);
119
- console.time(`[SolanaHandler] Get blockhash`);
54
+ console.log(`\nAttempt ${attempt}/${maxAttempts}`);
120
55
  const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('processed');
121
- console.timeEnd(`[SolanaHandler] Get blockhash`);
122
- console.log(`[SolanaHandler] Got blockhash: ${blockhash.slice(0, 10)}...`);
56
+ console.log('Got blockhash:', blockhash.slice(0, 10) + '...');
123
57
  transaction.recentBlockhash = blockhash;
124
58
  transaction.lastValidBlockHeight = lastValidBlockHeight;
125
59
  transaction.feePayer = senderKeypair.publicKey;
126
60
  transaction.signatures = [];
127
61
  transaction.sign(senderKeypair);
128
62
  const rawTx = transaction.serialize();
129
- console.log(`[SolanaHandler] Transaction serialized, size: ${rawTx.length} bytes`);
130
- console.time(`[SolanaHandler] Send transaction`);
131
63
  const signature = await connection.sendRawTransaction(rawTx, {
132
64
  skipPreflight: false,
133
65
  maxRetries: 1,
134
66
  preflightCommitment: 'processed'
135
67
  });
136
- console.timeEnd(`[SolanaHandler] Send transaction`);
137
- console.log(`[SolanaHandler] Transaction sent! Signature: ${signature}`);
68
+ console.log('Transaction sent! Signature:', signature);
138
69
  if (!fastMode) {
139
- console.log(`[SolanaHandler] Waiting for confirmation...`);
70
+ console.log('Waiting for confirmation...');
140
71
  let confirmationAttempt = 1;
141
72
  while (confirmationAttempt <= 5) {
142
73
  try {
143
- console.log(`[SolanaHandler] Confirmation attempt ${confirmationAttempt}/5`);
144
- console.time(`[SolanaHandler] Confirm transaction attempt ${confirmationAttempt}`);
74
+ console.log(`Confirmation attempt ${confirmationAttempt}/5`);
145
75
  await connection.confirmTransaction({
146
76
  signature,
147
77
  blockhash,
148
78
  lastValidBlockHeight
149
79
  }, 'processed');
150
- console.timeEnd(`[SolanaHandler] Confirm transaction attempt ${confirmationAttempt}`);
151
- console.log(`[SolanaHandler] Transaction confirmed!`);
80
+ console.log('Transaction confirmed!');
152
81
  return signature;
153
82
  }
154
83
  catch (confirmError) {
155
84
  const errorMessage = confirmError instanceof Error
156
85
  ? confirmError.message
157
86
  : 'Unknown confirmation error';
158
- console.log(`[SolanaHandler] Confirmation failed: ${errorMessage}`);
87
+ console.log('Confirmation failed:', errorMessage);
159
88
  if (confirmationAttempt === 5)
160
89
  throw confirmError;
161
90
  confirmationAttempt++;
@@ -169,11 +98,10 @@ class SolanaHandler {
169
98
  const errorMessage = error instanceof Error
170
99
  ? error.message
171
100
  : 'Unknown error';
172
- console.log(`[SolanaHandler] Attempt failed: ${errorMessage}`);
173
- console.error(`[SolanaHandler] Error stack:`, error instanceof Error ? error.stack : 'No stack trace');
101
+ console.log('Attempt failed:', errorMessage);
174
102
  lastError = error;
175
103
  if (attempt < maxAttempts) {
176
- console.log(`[SolanaHandler] Waiting 500ms before retry...`);
104
+ console.log('Waiting 500ms before retry...');
177
105
  await new Promise(resolve => setTimeout(resolve, 500));
178
106
  }
179
107
  }
@@ -181,71 +109,42 @@ class SolanaHandler {
181
109
  throw lastError;
182
110
  }
183
111
  async buy(walletAddress, amount, pkey, rpc, tokenAddress, fastMode) {
184
- console.log(`[SolanaHandler] Initiating transaction`);
185
- console.log(`[SolanaHandler] Transaction details:`, {
186
- recipient: walletAddress,
187
- amount: amount.toString(),
188
- rpc: rpc.substring(0, 20) + '...',
189
- hasTokenAddress: !!tokenAddress,
190
- fastMode
191
- });
192
- console.log(`[SolanaHandler] Creating connection to RPC: ${rpc.substring(0, 20)}...`);
193
- const connection = new web3_js_1.Connection(rpc, {
112
+ const connection = new Connection(rpc, {
194
113
  commitment: 'processed',
195
114
  confirmTransactionInitialTimeout: 10000
196
115
  });
197
116
  try {
198
- console.log(`[SolanaHandler] Parsing recipient public key: ${walletAddress}`);
199
- const recipientPubkey = new web3_js_1.PublicKey(walletAddress);
200
- console.log(`[SolanaHandler] Creating sender keypair from private key`);
201
- const senderKeypair = web3_js_1.Keypair.fromSecretKey(bs58_1.default.decode(pkey));
202
- console.log(`[SolanaHandler] Sender public key: ${senderKeypair.publicKey.toString()}`);
203
- console.log(`[SolanaHandler] Creating transaction`);
204
- const transaction = new web3_js_1.Transaction();
117
+ const recipientPubkey = new PublicKey(walletAddress);
118
+ const senderKeypair = Keypair.fromSecretKey(bs58.decode(pkey));
119
+ const transaction = new Transaction();
205
120
  // Add priority fee instruction
206
- console.log(`[SolanaHandler] Adding compute unit price instruction (priority fee)`);
207
- transaction.add(web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({
121
+ transaction.add(ComputeBudgetProgram.setComputeUnitPrice({
208
122
  microLamports: 50000
209
123
  }));
210
124
  if (tokenAddress) {
211
- console.log(`[SolanaHandler] Preparing SPL token transfer`);
212
- console.log(`[SolanaHandler] Token address: ${tokenAddress}`);
213
- const mint = new web3_js_1.PublicKey(tokenAddress);
214
- console.time(`[SolanaHandler] Get sender ATA`);
215
- const senderATA = await (0, spl_token_1.getAssociatedTokenAddress)(mint, senderKeypair.publicKey);
216
- console.timeEnd(`[SolanaHandler] Get sender ATA`);
217
- console.log(`[SolanaHandler] Sender ATA: ${senderATA.toString()}`);
218
- console.time(`[SolanaHandler] Get recipient ATA`);
219
- const recipientATA = await (0, spl_token_1.getAssociatedTokenAddress)(mint, recipientPubkey);
220
- console.timeEnd(`[SolanaHandler] Get recipient ATA`);
221
- console.log(`[SolanaHandler] Recipient ATA: ${recipientATA.toString()}`);
125
+ const mint = new PublicKey(tokenAddress);
126
+ const senderATA = await getAssociatedTokenAddress(mint, senderKeypair.publicKey);
127
+ const recipientATA = await getAssociatedTokenAddress(mint, recipientPubkey);
222
128
  // Get token decimals
223
- console.time(`[SolanaHandler] Get mint info`);
224
- const mintInfo = await (0, spl_token_1.getMint)(connection, mint);
225
- console.timeEnd(`[SolanaHandler] Get mint info`);
226
- console.log(`[SolanaHandler] Token decimals: ${mintInfo.decimals}`);
227
- console.log(`[SolanaHandler] Original amount: ${amount.toString()}`);
129
+ const mintInfo = await getMint(connection, mint);
130
+ console.log('Token decimals:', mintInfo.decimals);
131
+ console.log('Original amount:', amount.toString());
228
132
  // Don't multiply by decimals since amount is already raw
229
- console.log(`[SolanaHandler] Adding token transfer instruction`);
230
- transaction.add((0, spl_token_1.createTransferInstruction)(senderATA, recipientATA, senderKeypair.publicKey, Number(amount) // Use raw amount directly
133
+ transaction.add(createTransferInstruction(senderATA, recipientATA, senderKeypair.publicKey, Number(amount) // Use raw amount directly
231
134
  ));
232
135
  }
233
136
  else {
234
137
  // SOL transfer
235
- console.log(`[SolanaHandler] Preparing SOL transfer`);
236
- console.log(`[SolanaHandler] Adding SOL transfer instruction: ${Number(amount)} lamports`);
237
- transaction.add(web3_js_1.SystemProgram.transfer({
138
+ transaction.add(SystemProgram.transfer({
238
139
  fromPubkey: senderKeypair.publicKey,
239
140
  toPubkey: recipientPubkey,
240
141
  lamports: Number(amount)
241
142
  }));
242
143
  }
243
- console.log(`[SolanaHandler] Sending transaction with retry logic`);
244
144
  return await this.sendWithRetry(connection, transaction, senderKeypair, !!fastMode);
245
145
  }
246
146
  catch (error) {
247
- console.error(`[SolanaHandler] Transaction failed:`, error);
248
- console.error(`[SolanaHandler] Error stack:`, error instanceof Error ? error.stack : 'No stack trace');
147
+ console.error('Detailed error:', error);
249
148
  throw new Error(`Transaction failed: ${error instanceof Error ? error.message : String(error)}`);
250
149
  }
251
150
  }
@@ -259,78 +158,28 @@ class ApiNow {
259
158
  };
260
159
  }
261
160
  async info(endpoint) {
262
- console.log(`[ApiNow] Fetching info from endpoint: ${endpoint}`);
263
161
  if (!endpoint.startsWith('https://apinow.fun/api/endpoints/')) {
264
- console.error(`[ApiNow] Invalid endpoint URL format: ${endpoint}`);
265
162
  throw new Error('Invalid endpoint URL format');
266
163
  }
267
- console.time(`[ApiNow] Fetch endpoint info`);
268
- try {
269
- const response = await (0, node_fetch_1.default)(`${endpoint}`);
270
- console.timeEnd(`[ApiNow] Fetch endpoint info`);
271
- console.log(`[ApiNow] Info response status: ${response.status}`);
272
- if (!response.ok) {
273
- console.error(`[ApiNow] Failed to fetch endpoint info: ${response.status} ${response.statusText}`);
274
- const errorText = await response.text();
275
- console.error(`[ApiNow] Error response body: ${errorText}`);
276
- throw new Error(`Failed to fetch endpoint info: ${response.status}`);
277
- }
278
- const data = await response.json();
279
- console.log(`[ApiNow] Endpoint info retrieved:`, {
280
- chain: data.chain,
281
- requiredAmount: data.requiredAmount,
282
- walletAddress: data.walletAddress,
283
- httpMethod: data.httpMethod,
284
- hasTokenAddress: !!data.tokenAddress
285
- });
286
- return data;
287
- }
288
- catch (error) {
289
- console.error(`[ApiNow] Error fetching endpoint info:`, error);
290
- console.error(`[ApiNow] Error stack:`, error instanceof Error ? error.stack : 'No stack trace');
291
- throw error;
164
+ console.log(`Fetching info from ${endpoint}`);
165
+ const response = await fetch(`${endpoint}`);
166
+ if (!response.ok) {
167
+ throw new Error(`Failed to fetch endpoint info: ${response.status}`);
292
168
  }
169
+ return response.json();
293
170
  }
294
171
  async buy(walletAddress, amount, pkey, rpc, chain = 'eth', tokenAddress, fastMode) {
295
- console.log(`[ApiNow] Initiating transaction on chain: ${chain}`);
296
- console.log(`[ApiNow] Transaction details:`, {
297
- recipient: walletAddress,
298
- amount: amount.toString(),
299
- chain,
300
- hasTokenAddress: !!tokenAddress,
301
- fastMode
302
- });
303
172
  const handler = this.handlers[chain];
304
173
  if (!handler) {
305
- console.error(`[ApiNow] Unsupported chain: ${chain}`);
306
174
  throw new Error(`Unsupported chain: ${chain}`);
307
175
  }
308
- console.time(`[ApiNow] Transaction on ${chain}`);
309
- try {
310
- const txHash = await handler.buy(walletAddress, amount, pkey, rpc, tokenAddress, fastMode);
311
- console.timeEnd(`[ApiNow] Transaction on ${chain}`);
312
- console.log(`[ApiNow] Transaction successful with hash: ${txHash}`);
313
- return txHash;
314
- }
315
- catch (error) {
316
- console.timeEnd(`[ApiNow] Transaction on ${chain}`);
317
- console.error(`[ApiNow] Transaction failed:`, error);
318
- console.error(`[ApiNow] Error stack:`, error instanceof Error ? error.stack : 'No stack trace');
319
- throw error;
320
- }
176
+ return handler.buy(walletAddress, amount, pkey, rpc, tokenAddress, fastMode);
321
177
  }
322
178
  async txResponse(endpoint, txHash, opts = {}) {
323
- console.log(`[ApiNow] Making API call with transaction hash`);
324
- console.log(`[ApiNow] Call details:`, {
325
- endpoint,
326
- txHash,
327
- method: opts.method || 'GET',
328
- hasData: !!opts.data
329
- });
330
179
  if (!endpoint.startsWith('https://apinow.fun/api/endpoints/')) {
331
- console.error(`[ApiNow] Invalid endpoint URL format: ${endpoint}`);
332
180
  throw new Error('Invalid endpoint URL format');
333
181
  }
182
+ console.log('txResponse:', { endpoint, txHash, ...opts });
334
183
  const options = {
335
184
  method: opts.method || 'GET',
336
185
  headers: {
@@ -339,74 +188,25 @@ class ApiNow {
339
188
  },
340
189
  ...(opts.data && { body: JSON.stringify(opts.data) })
341
190
  };
342
- console.log(`[ApiNow] Request options:`, {
343
- method: options.method,
344
- headers: Object.keys(options.headers),
345
- hasBody: !!options.body
346
- });
347
- console.time(`[ApiNow] API call with transaction hash`);
348
- try {
349
- const response = await (0, node_fetch_1.default)(endpoint, options);
350
- console.timeEnd(`[ApiNow] API call with transaction hash`);
351
- console.log(`[ApiNow] Response status: ${response.status}`);
352
- if (!response.ok) {
353
- console.error(`[ApiNow] API request failed: ${response.status} ${response.statusText}`);
354
- const errorText = await response.text();
355
- console.error(`[ApiNow] Error response body: ${errorText}`);
356
- throw new Error(`API request failed: ${response.status}`);
357
- }
358
- const data = await response.json();
359
- console.log(`[ApiNow] API call successful with data type: ${typeof data}`);
360
- return data;
361
- }
362
- catch (error) {
363
- console.timeEnd(`[ApiNow] API call with transaction hash`);
364
- console.error(`[ApiNow] API call failed:`, error);
365
- console.error(`[ApiNow] Error stack:`, error instanceof Error ? error.stack : 'No stack trace');
366
- throw error;
191
+ const response = await fetch(endpoint, options);
192
+ if (!response.ok) {
193
+ throw new Error(`API request failed: ${response.status}`);
367
194
  }
195
+ return response.json();
368
196
  }
369
197
  async infoBuyResponse(endpoint, pkey, rpc, opts = {}) {
370
- console.log(`[ApiNow] Starting infoBuyResponse flow for endpoint: ${endpoint}`);
371
- console.log(`[ApiNow] Options:`, {
372
- method: opts.method,
373
- hasData: !!opts.data,
374
- fastMode: opts.fastMode
198
+ const info = await this.info(endpoint);
199
+ const amount = info.chain === 'sol'
200
+ ? BigInt(Math.round(Number(info.requiredAmount) * LAMPORTS_PER_SOL))
201
+ : ethers.parseEther(info.requiredAmount);
202
+ const txHash = await this.buy(info.walletAddress, amount, pkey, rpc, info.chain, info.tokenAddress, opts.fastMode);
203
+ console.log('infoBuyResponse:', { endpoint, txHash, ...opts });
204
+ const response = await this.txResponse(endpoint, txHash, {
205
+ method: opts.method || info.httpMethod,
206
+ data: opts.data
375
207
  });
376
- try {
377
- console.time(`[ApiNow] Total infoBuyResponse flow`);
378
- // Step 1: Get endpoint info
379
- console.time(`[ApiNow] Get endpoint info`);
380
- const info = await this.info(endpoint);
381
- console.timeEnd(`[ApiNow] Get endpoint info`);
382
- // Step 2: Calculate amount
383
- console.log(`[ApiNow] Calculating transaction amount for chain: ${info.chain}`);
384
- const amount = info.chain === 'sol'
385
- ? BigInt(Math.round(Number(info.requiredAmount) * web3_js_1.LAMPORTS_PER_SOL))
386
- : ethers_1.ethers.parseEther(info.requiredAmount);
387
- console.log(`[ApiNow] Calculated amount: ${amount.toString()}`);
388
- // Step 3: Execute transaction
389
- console.time(`[ApiNow] Execute transaction`);
390
- const txHash = await this.buy(info.walletAddress, amount, pkey, rpc, info.chain, info.tokenAddress, opts.fastMode);
391
- console.timeEnd(`[ApiNow] Execute transaction`);
392
- // Step 4: Make API call with transaction hash
393
- console.log(`[ApiNow] Making API call with transaction hash: ${txHash}`);
394
- console.time(`[ApiNow] API call with transaction hash`);
395
- const response = await this.txResponse(endpoint, txHash, {
396
- method: opts.method || info.httpMethod,
397
- data: opts.data
398
- });
399
- console.timeEnd(`[ApiNow] API call with transaction hash`);
400
- console.timeEnd(`[ApiNow] Total infoBuyResponse flow`);
401
- console.log(`[ApiNow] infoBuyResponse flow completed successfully`);
402
- return response;
403
- }
404
- catch (error) {
405
- console.timeEnd(`[ApiNow] Total infoBuyResponse flow`);
406
- console.error(`[ApiNow] infoBuyResponse flow failed:`, error);
407
- console.error(`[ApiNow] Error stack:`, error instanceof Error ? error.stack : 'No stack trace');
408
- throw error;
409
- }
208
+ console.log('response:', response);
209
+ return response;
410
210
  }
411
211
  }
412
- exports.default = new ApiNow();
212
+ export default new ApiNow();
package/package.json CHANGED
@@ -1,33 +1,37 @@
1
1
  {
2
2
  "name": "apinow-sdk",
3
- "version": "0.7.0",
4
- "description": "SDK for APINow.fun API with enhanced logging",
3
+ "version": "0.8.0",
4
+ "description": "ApiNow SDK · The endpoint vending machine",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
+ "type": "module",
8
+ "files": [
9
+ "dist"
10
+ ],
7
11
  "scripts": {
8
12
  "build": "tsc",
9
- "prepublishOnly": "npm run build"
13
+ "test": "jest",
14
+ "prepare": "npm run build"
10
15
  },
11
16
  "keywords": [
12
17
  "api",
13
- "apinowfun",
14
- "apinow",
15
- "blockchain",
16
18
  "ethereum",
17
- "solana"
19
+ "web3"
18
20
  ],
19
- "author": "ApiNow Fun",
21
+ "author": "ApiNow.fun",
20
22
  "license": "MIT",
21
- "devDependencies": {
22
- "@types/bs58": "^4.0.4",
23
- "@types/node": "^20.17.24",
24
- "typescript": "^5.8.2"
25
- },
26
23
  "dependencies": {
27
- "@solana/spl-token": "^0.3.11",
28
- "@solana/web3.js": "^1.87.6",
29
- "bs58": "^5.0.0",
30
- "ethers": "^6.9.0",
24
+ "@solana/spl-token": "^0.4.12",
25
+ "@solana/web3.js": "^1.98.0",
26
+ "bs58": "^6.0.0",
27
+ "ethers": "^6.13.5",
31
28
  "node-fetch": "^3.3.2"
29
+ },
30
+ "devDependencies": {
31
+ "@types/jest": "^29.5.12",
32
+ "@types/node": "^20.11.24",
33
+ "jest": "^29.7.0",
34
+ "ts-jest": "^29.1.2",
35
+ "typescript": "^5.3.3"
32
36
  }
33
- }
37
+ }
Binary file
package/index.ts DELETED
@@ -1,559 +0,0 @@
1
- import { ethers } from 'ethers';
2
- import fetch from 'node-fetch';
3
- import {
4
- Connection,
5
- PublicKey,
6
- LAMPORTS_PER_SOL,
7
- Transaction,
8
- SystemProgram,
9
- Keypair,
10
- ComputeBudgetProgram
11
- } from '@solana/web3.js';
12
- import {
13
- createTransferInstruction,
14
- getAssociatedTokenAddress,
15
- TOKEN_PROGRAM_ID,
16
- getMint
17
- } from '@solana/spl-token';
18
- import bs58 from 'bs58';
19
-
20
- interface TxResponseOptions {
21
- method?: string;
22
- data?: any;
23
- }
24
-
25
- interface InfoResponse {
26
- requiredAmount: string;
27
- walletAddress: string;
28
- httpMethod: string;
29
- tokenAddress?: string;
30
- chain: 'eth' | 'sol' | 'base';
31
- }
32
-
33
- interface ChainHandler {
34
- buy(
35
- walletAddress: string,
36
- amount: bigint,
37
- pkey: string,
38
- rpc: string,
39
- tokenAddress?: string,
40
- fastMode?: boolean
41
- ): Promise<string>;
42
- }
43
-
44
- class EthereumHandler implements ChainHandler {
45
- async buy(
46
- walletAddress: string,
47
- amount: bigint,
48
- pkey: string,
49
- rpc: string,
50
- tokenAddress?: string,
51
- fastMode?: boolean
52
- ): Promise<string> {
53
- console.log(`[EthereumHandler] Initiating transaction`);
54
- console.log(`[EthereumHandler] Transaction details:`, {
55
- recipient: walletAddress,
56
- amount: amount.toString(),
57
- rpc: rpc.substring(0, 20) + '...',
58
- hasTokenAddress: !!tokenAddress,
59
- fastMode
60
- });
61
-
62
- if (!rpc || typeof rpc !== 'string') {
63
- console.error(`[EthereumHandler] Invalid RPC URL: ${rpc}`);
64
- throw new Error('Invalid RPC URL');
65
- }
66
-
67
- if (!walletAddress || !ethers.isAddress(walletAddress)) {
68
- console.error(`[EthereumHandler] Invalid wallet address: ${walletAddress}`);
69
- throw new Error('Invalid wallet address');
70
- }
71
-
72
- try {
73
- console.log(`[EthereumHandler] Creating provider with RPC: ${rpc.substring(0, 20)}...`);
74
- const provider = new ethers.JsonRpcProvider(rpc);
75
-
76
- console.log(`[EthereumHandler] Creating wallet from private key`);
77
- const wallet = new ethers.Wallet(pkey, provider);
78
- console.log(`[EthereumHandler] Wallet address: ${wallet.address}`);
79
-
80
- console.time(`[EthereumHandler] Get network`);
81
- const network = await provider.getNetwork();
82
- console.timeEnd(`[EthereumHandler] Get network`);
83
- console.log(`[EthereumHandler] Connected to network: ${network.name} (${network.chainId})`);
84
-
85
- console.time(`[EthereumHandler] Get balance`);
86
- const balance = await provider.getBalance(wallet.address);
87
- console.timeEnd(`[EthereumHandler] Get balance`);
88
- console.log(`[EthereumHandler] Sender balance: ${ethers.formatEther(balance)} ETH`);
89
-
90
- if (balance < amount && !tokenAddress) {
91
- console.error(`[EthereumHandler] Insufficient balance: ${ethers.formatEther(balance)} ETH, required: ${ethers.formatEther(amount)} ETH`);
92
- throw new Error(`Insufficient balance: ${ethers.formatEther(balance)} ETH, required: ${ethers.formatEther(amount)} ETH`);
93
- }
94
-
95
- console.time(`[EthereumHandler] Get nonce`);
96
- const nonce = await provider.getTransactionCount(wallet.address, 'latest');
97
- console.timeEnd(`[EthereumHandler] Get nonce`);
98
- console.log(`[EthereumHandler] Nonce: ${nonce}`);
99
-
100
- const gasLimit = wallet.address.toLowerCase() === walletAddress.toLowerCase()
101
- ? 30000
102
- : 21000;
103
- console.log(`[EthereumHandler] Gas limit: ${gasLimit}`);
104
-
105
- let txHash: string;
106
-
107
- if (tokenAddress) {
108
- console.log(`[EthereumHandler] Executing ERC-20 token transfer`);
109
- console.log(`[EthereumHandler] Token address: ${tokenAddress}`);
110
-
111
- const abi = ["function transfer(address to, uint256 amount) returns (bool)"];
112
- console.log(`[EthereumHandler] Creating token contract instance`);
113
- const tokenContract = new ethers.Contract(tokenAddress, abi, wallet);
114
-
115
- console.time(`[EthereumHandler] Token transfer`);
116
- console.log(`[EthereumHandler] Transferring ${amount.toString()} tokens to ${walletAddress}`);
117
- const tx = await tokenContract.transfer(walletAddress, amount);
118
- console.timeEnd(`[EthereumHandler] Token transfer`);
119
-
120
- console.log(`[EthereumHandler] Token transfer transaction hash: ${tx.hash}`);
121
- txHash = tx.hash;
122
- } else {
123
- console.log(`[EthereumHandler] Executing native token transfer`);
124
-
125
- console.time(`[EthereumHandler] Native transfer`);
126
- console.log(`[EthereumHandler] Transferring ${ethers.formatEther(amount)} ETH to ${walletAddress}`);
127
- const tx = await wallet.sendTransaction({
128
- to: walletAddress,
129
- value: amount,
130
- type: 2,
131
- maxFeePerGas: ethers.parseUnits('0.1', 'gwei'),
132
- maxPriorityFeePerGas: ethers.parseUnits('0.1', 'gwei'),
133
- gasLimit,
134
- nonce
135
- });
136
- console.timeEnd(`[EthereumHandler] Native transfer`);
137
-
138
- console.log(`[EthereumHandler] Native transfer transaction hash: ${tx.hash}`);
139
- txHash = tx.hash;
140
- }
141
-
142
- if (!fastMode) {
143
- console.log(`[EthereumHandler] Waiting for transaction confirmation...`);
144
- console.time(`[EthereumHandler] Transaction confirmation`);
145
- const receipt = await provider.waitForTransaction(txHash);
146
- console.timeEnd(`[EthereumHandler] Transaction confirmation`);
147
-
148
- console.log(`[EthereumHandler] Transaction confirmed:`, {
149
- blockNumber: receipt?.blockNumber,
150
- status: receipt?.status === 1 ? 'success' : 'failed',
151
- gasUsed: receipt?.gasUsed?.toString()
152
- });
153
-
154
- if (receipt?.status !== 1) {
155
- console.error(`[EthereumHandler] Transaction failed with status: ${receipt?.status}`);
156
- throw new Error('Transaction failed');
157
- }
158
- } else {
159
- console.log(`[EthereumHandler] Fast mode enabled, not waiting for confirmation`);
160
- }
161
-
162
- return txHash;
163
- } catch (error: unknown) {
164
- console.error(`[EthereumHandler] Transaction failed:`, error);
165
- console.error(`[EthereumHandler] Error stack:`, error instanceof Error ? error.stack : 'No stack trace');
166
- throw new Error(
167
- `Transaction failed: ${error instanceof Error ? error.message : String(error)}`
168
- );
169
- }
170
- }
171
- }
172
-
173
- class SolanaHandler implements ChainHandler {
174
- private async sendWithRetry(
175
- connection: Connection,
176
- transaction: Transaction,
177
- senderKeypair: Keypair,
178
- fastMode: boolean,
179
- maxAttempts = 3
180
- ): Promise<string> {
181
- let lastError;
182
-
183
- for (let attempt = 1; attempt <= maxAttempts; attempt++) {
184
- try {
185
- console.log(`[SolanaHandler] Attempt ${attempt}/${maxAttempts}`);
186
-
187
- console.time(`[SolanaHandler] Get blockhash`);
188
- const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('processed');
189
- console.timeEnd(`[SolanaHandler] Get blockhash`);
190
- console.log(`[SolanaHandler] Got blockhash: ${blockhash.slice(0, 10)}...`);
191
-
192
- transaction.recentBlockhash = blockhash;
193
- transaction.lastValidBlockHeight = lastValidBlockHeight;
194
- transaction.feePayer = senderKeypair.publicKey;
195
-
196
- transaction.signatures = [];
197
- transaction.sign(senderKeypair);
198
-
199
- const rawTx = transaction.serialize();
200
- console.log(`[SolanaHandler] Transaction serialized, size: ${rawTx.length} bytes`);
201
-
202
- console.time(`[SolanaHandler] Send transaction`);
203
- const signature = await connection.sendRawTransaction(rawTx, {
204
- skipPreflight: false,
205
- maxRetries: 1,
206
- preflightCommitment: 'processed'
207
- });
208
- console.timeEnd(`[SolanaHandler] Send transaction`);
209
- console.log(`[SolanaHandler] Transaction sent! Signature: ${signature}`);
210
-
211
- if (!fastMode) {
212
- console.log(`[SolanaHandler] Waiting for confirmation...`);
213
- let confirmationAttempt = 1;
214
- while (confirmationAttempt <= 5) {
215
- try {
216
- console.log(`[SolanaHandler] Confirmation attempt ${confirmationAttempt}/5`);
217
- console.time(`[SolanaHandler] Confirm transaction attempt ${confirmationAttempt}`);
218
- await connection.confirmTransaction({
219
- signature,
220
- blockhash,
221
- lastValidBlockHeight
222
- }, 'processed');
223
- console.timeEnd(`[SolanaHandler] Confirm transaction attempt ${confirmationAttempt}`);
224
- console.log(`[SolanaHandler] Transaction confirmed!`);
225
- return signature;
226
- } catch (confirmError: unknown) {
227
- const errorMessage = confirmError instanceof Error
228
- ? confirmError.message
229
- : 'Unknown confirmation error';
230
- console.log(`[SolanaHandler] Confirmation failed: ${errorMessage}`);
231
- if (confirmationAttempt === 5) throw confirmError;
232
- confirmationAttempt++;
233
- await new Promise(resolve => setTimeout(resolve, 1000));
234
- }
235
- }
236
- }
237
-
238
- return signature;
239
- } catch (error: unknown) {
240
- const errorMessage = error instanceof Error
241
- ? error.message
242
- : 'Unknown error';
243
- console.log(`[SolanaHandler] Attempt failed: ${errorMessage}`);
244
- console.error(`[SolanaHandler] Error stack:`, error instanceof Error ? error.stack : 'No stack trace');
245
- lastError = error;
246
- if (attempt < maxAttempts) {
247
- console.log(`[SolanaHandler] Waiting 500ms before retry...`);
248
- await new Promise(resolve => setTimeout(resolve, 500));
249
- }
250
- }
251
- }
252
- throw lastError;
253
- }
254
-
255
- async buy(
256
- walletAddress: string,
257
- amount: bigint,
258
- pkey: string,
259
- rpc: string,
260
- tokenAddress?: string,
261
- fastMode?: boolean
262
- ): Promise<string> {
263
- console.log(`[SolanaHandler] Initiating transaction`);
264
- console.log(`[SolanaHandler] Transaction details:`, {
265
- recipient: walletAddress,
266
- amount: amount.toString(),
267
- rpc: rpc.substring(0, 20) + '...',
268
- hasTokenAddress: !!tokenAddress,
269
- fastMode
270
- });
271
-
272
- console.log(`[SolanaHandler] Creating connection to RPC: ${rpc.substring(0, 20)}...`);
273
- const connection = new Connection(rpc, {
274
- commitment: 'processed',
275
- confirmTransactionInitialTimeout: 10000
276
- });
277
-
278
- try {
279
- console.log(`[SolanaHandler] Parsing recipient public key: ${walletAddress}`);
280
- const recipientPubkey = new PublicKey(walletAddress);
281
-
282
- console.log(`[SolanaHandler] Creating sender keypair from private key`);
283
- const senderKeypair = Keypair.fromSecretKey(bs58.decode(pkey));
284
- console.log(`[SolanaHandler] Sender public key: ${senderKeypair.publicKey.toString()}`);
285
-
286
- console.log(`[SolanaHandler] Creating transaction`);
287
- const transaction = new Transaction();
288
-
289
- // Add priority fee instruction
290
- console.log(`[SolanaHandler] Adding compute unit price instruction (priority fee)`);
291
- transaction.add(
292
- ComputeBudgetProgram.setComputeUnitPrice({
293
- microLamports: 50000
294
- })
295
- );
296
-
297
- if (tokenAddress) {
298
- console.log(`[SolanaHandler] Preparing SPL token transfer`);
299
- console.log(`[SolanaHandler] Token address: ${tokenAddress}`);
300
-
301
- const mint = new PublicKey(tokenAddress);
302
-
303
- console.time(`[SolanaHandler] Get sender ATA`);
304
- const senderATA = await getAssociatedTokenAddress(mint, senderKeypair.publicKey);
305
- console.timeEnd(`[SolanaHandler] Get sender ATA`);
306
- console.log(`[SolanaHandler] Sender ATA: ${senderATA.toString()}`);
307
-
308
- console.time(`[SolanaHandler] Get recipient ATA`);
309
- const recipientATA = await getAssociatedTokenAddress(mint, recipientPubkey);
310
- console.timeEnd(`[SolanaHandler] Get recipient ATA`);
311
- console.log(`[SolanaHandler] Recipient ATA: ${recipientATA.toString()}`);
312
-
313
- // Get token decimals
314
- console.time(`[SolanaHandler] Get mint info`);
315
- const mintInfo = await getMint(connection, mint);
316
- console.timeEnd(`[SolanaHandler] Get mint info`);
317
- console.log(`[SolanaHandler] Token decimals: ${mintInfo.decimals}`);
318
- console.log(`[SolanaHandler] Original amount: ${amount.toString()}`);
319
-
320
- // Don't multiply by decimals since amount is already raw
321
- console.log(`[SolanaHandler] Adding token transfer instruction`);
322
- transaction.add(
323
- createTransferInstruction(
324
- senderATA,
325
- recipientATA,
326
- senderKeypair.publicKey,
327
- Number(amount) // Use raw amount directly
328
- )
329
- );
330
- } else {
331
- // SOL transfer
332
- console.log(`[SolanaHandler] Preparing SOL transfer`);
333
- console.log(`[SolanaHandler] Adding SOL transfer instruction: ${Number(amount)} lamports`);
334
- transaction.add(
335
- SystemProgram.transfer({
336
- fromPubkey: senderKeypair.publicKey,
337
- toPubkey: recipientPubkey,
338
- lamports: Number(amount)
339
- })
340
- );
341
- }
342
-
343
- console.log(`[SolanaHandler] Sending transaction with retry logic`);
344
- return await this.sendWithRetry(connection, transaction, senderKeypair, !!fastMode);
345
-
346
- } catch (error: unknown) {
347
- console.error(`[SolanaHandler] Transaction failed:`, error);
348
- console.error(`[SolanaHandler] Error stack:`, error instanceof Error ? error.stack : 'No stack trace');
349
- throw new Error(
350
- `Transaction failed: ${error instanceof Error ? error.message : String(error)}`
351
- );
352
- }
353
- }
354
- }
355
-
356
- class ApiNow {
357
- private handlers: { [key: string]: ChainHandler } = {
358
- eth: new EthereumHandler(),
359
- sol: new SolanaHandler(),
360
- base: new EthereumHandler()
361
- };
362
-
363
- async info(endpoint: string): Promise<InfoResponse> {
364
- console.log(`[ApiNow] Fetching info from endpoint: ${endpoint}`);
365
-
366
- if (!endpoint.startsWith('https://apinow.fun/api/endpoints/')) {
367
- console.error(`[ApiNow] Invalid endpoint URL format: ${endpoint}`);
368
- throw new Error('Invalid endpoint URL format');
369
- }
370
-
371
- console.time(`[ApiNow] Fetch endpoint info`);
372
- try {
373
- const response = await fetch(`${endpoint}`);
374
- console.timeEnd(`[ApiNow] Fetch endpoint info`);
375
- console.log(`[ApiNow] Info response status: ${response.status}`);
376
-
377
- if (!response.ok) {
378
- console.error(`[ApiNow] Failed to fetch endpoint info: ${response.status} ${response.statusText}`);
379
- const errorText = await response.text();
380
- console.error(`[ApiNow] Error response body: ${errorText}`);
381
- throw new Error(`Failed to fetch endpoint info: ${response.status}`);
382
- }
383
-
384
- const data = await response.json() as InfoResponse;
385
- console.log(`[ApiNow] Endpoint info retrieved:`, {
386
- chain: data.chain,
387
- requiredAmount: data.requiredAmount,
388
- walletAddress: data.walletAddress,
389
- httpMethod: data.httpMethod,
390
- hasTokenAddress: !!data.tokenAddress
391
- });
392
-
393
- return data;
394
- } catch (error) {
395
- console.error(`[ApiNow] Error fetching endpoint info:`, error);
396
- console.error(`[ApiNow] Error stack:`, error instanceof Error ? error.stack : 'No stack trace');
397
- throw error;
398
- }
399
- }
400
-
401
- async buy(
402
- walletAddress: string,
403
- amount: bigint,
404
- pkey: string,
405
- rpc: string,
406
- chain: 'eth' | 'sol' | 'base' = 'eth',
407
- tokenAddress?: string,
408
- fastMode?: boolean
409
- ): Promise<string> {
410
- console.log(`[ApiNow] Initiating transaction on chain: ${chain}`);
411
- console.log(`[ApiNow] Transaction details:`, {
412
- recipient: walletAddress,
413
- amount: amount.toString(),
414
- chain,
415
- hasTokenAddress: !!tokenAddress,
416
- fastMode
417
- });
418
-
419
- const handler = this.handlers[chain];
420
- if (!handler) {
421
- console.error(`[ApiNow] Unsupported chain: ${chain}`);
422
- throw new Error(`Unsupported chain: ${chain}`);
423
- }
424
-
425
- console.time(`[ApiNow] Transaction on ${chain}`);
426
- try {
427
- const txHash = await handler.buy(walletAddress, amount, pkey, rpc, tokenAddress, fastMode);
428
- console.timeEnd(`[ApiNow] Transaction on ${chain}`);
429
- console.log(`[ApiNow] Transaction successful with hash: ${txHash}`);
430
- return txHash;
431
- } catch (error) {
432
- console.timeEnd(`[ApiNow] Transaction on ${chain}`);
433
- console.error(`[ApiNow] Transaction failed:`, error);
434
- console.error(`[ApiNow] Error stack:`, error instanceof Error ? error.stack : 'No stack trace');
435
- throw error;
436
- }
437
- }
438
-
439
- async txResponse(
440
- endpoint: string,
441
- txHash: string,
442
- opts: TxResponseOptions = {}
443
- ): Promise<any> {
444
- console.log(`[ApiNow] Making API call with transaction hash`);
445
- console.log(`[ApiNow] Call details:`, {
446
- endpoint,
447
- txHash,
448
- method: opts.method || 'GET',
449
- hasData: !!opts.data
450
- });
451
-
452
- if (!endpoint.startsWith('https://apinow.fun/api/endpoints/')) {
453
- console.error(`[ApiNow] Invalid endpoint URL format: ${endpoint}`);
454
- throw new Error('Invalid endpoint URL format');
455
- }
456
-
457
- const options = {
458
- method: opts.method || 'GET',
459
- headers: {
460
- 'x-transaction-hash': txHash,
461
- ...(opts.data && { 'Content-Type': 'application/json' })
462
- },
463
- ...(opts.data && { body: JSON.stringify(opts.data) })
464
- };
465
-
466
- console.log(`[ApiNow] Request options:`, {
467
- method: options.method,
468
- headers: Object.keys(options.headers),
469
- hasBody: !!options.body
470
- });
471
-
472
- console.time(`[ApiNow] API call with transaction hash`);
473
- try {
474
- const response = await fetch(endpoint, options);
475
- console.timeEnd(`[ApiNow] API call with transaction hash`);
476
- console.log(`[ApiNow] Response status: ${response.status}`);
477
-
478
- if (!response.ok) {
479
- console.error(`[ApiNow] API request failed: ${response.status} ${response.statusText}`);
480
- const errorText = await response.text();
481
- console.error(`[ApiNow] Error response body: ${errorText}`);
482
- throw new Error(`API request failed: ${response.status}`);
483
- }
484
-
485
- const data = await response.json();
486
- console.log(`[ApiNow] API call successful with data type: ${typeof data}`);
487
- return data;
488
- } catch (error) {
489
- console.timeEnd(`[ApiNow] API call with transaction hash`);
490
- console.error(`[ApiNow] API call failed:`, error);
491
- console.error(`[ApiNow] Error stack:`, error instanceof Error ? error.stack : 'No stack trace');
492
- throw error;
493
- }
494
- }
495
-
496
- async infoBuyResponse(
497
- endpoint: string,
498
- pkey: string,
499
- rpc: string,
500
- opts: TxResponseOptions & { fastMode?: boolean } = {}
501
- ): Promise<any> {
502
- console.log(`[ApiNow] Starting infoBuyResponse flow for endpoint: ${endpoint}`);
503
- console.log(`[ApiNow] Options:`, {
504
- method: opts.method,
505
- hasData: !!opts.data,
506
- fastMode: opts.fastMode
507
- });
508
-
509
- try {
510
- console.time(`[ApiNow] Total infoBuyResponse flow`);
511
-
512
- // Step 1: Get endpoint info
513
- console.time(`[ApiNow] Get endpoint info`);
514
- const info = await this.info(endpoint);
515
- console.timeEnd(`[ApiNow] Get endpoint info`);
516
-
517
- // Step 2: Calculate amount
518
- console.log(`[ApiNow] Calculating transaction amount for chain: ${info.chain}`);
519
- const amount = info.chain === 'sol'
520
- ? BigInt(Math.round(Number(info.requiredAmount) * LAMPORTS_PER_SOL))
521
- : ethers.parseEther(info.requiredAmount);
522
- console.log(`[ApiNow] Calculated amount: ${amount.toString()}`);
523
-
524
- // Step 3: Execute transaction
525
- console.time(`[ApiNow] Execute transaction`);
526
- const txHash = await this.buy(
527
- info.walletAddress,
528
- amount,
529
- pkey,
530
- rpc,
531
- info.chain,
532
- info.tokenAddress,
533
- opts.fastMode
534
- );
535
- console.timeEnd(`[ApiNow] Execute transaction`);
536
-
537
- // Step 4: Make API call with transaction hash
538
- console.log(`[ApiNow] Making API call with transaction hash: ${txHash}`);
539
- console.time(`[ApiNow] API call with transaction hash`);
540
- const response = await this.txResponse(endpoint, txHash, {
541
- method: opts.method || info.httpMethod,
542
- data: opts.data
543
- });
544
- console.timeEnd(`[ApiNow] API call with transaction hash`);
545
-
546
- console.timeEnd(`[ApiNow] Total infoBuyResponse flow`);
547
- console.log(`[ApiNow] infoBuyResponse flow completed successfully`);
548
-
549
- return response;
550
- } catch (error) {
551
- console.timeEnd(`[ApiNow] Total infoBuyResponse flow`);
552
- console.error(`[ApiNow] infoBuyResponse flow failed:`, error);
553
- console.error(`[ApiNow] Error stack:`, error instanceof Error ? error.stack : 'No stack trace');
554
- throw error;
555
- }
556
- }
557
- }
558
-
559
- export default new ApiNow();
package/tsconfig.json DELETED
@@ -1,15 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2020",
4
- "module": "NodeNext",
5
- "moduleResolution": "NodeNext",
6
- "esModuleInterop": true,
7
- "declaration": true,
8
- "outDir": "./dist",
9
- "strict": true,
10
- "skipLibCheck": true,
11
- "forceConsistentCasingInFileNames": true
12
- },
13
- "include": ["index.ts"],
14
- "exclude": ["node_modules", "dist"]
15
- }