@profullstack/coinpay 0.3.9 → 0.4.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/bin/coinpay.js +1005 -235
- package/package.json +21 -4
- package/src/client.js +87 -0
- package/src/escrow.js +245 -0
- package/src/index.d.ts +65 -2
- package/src/index.js +82 -1
- package/src/swap.d.ts +254 -0
- package/src/swap.js +360 -0
- package/src/wallet.d.ts +259 -0
- package/src/wallet.js +757 -0
package/src/swap.d.ts
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Swap Module Type Definitions
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Supported coins for swaps
|
|
7
|
+
*/
|
|
8
|
+
export declare const SwapCoins: readonly string[];
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Swap status values
|
|
12
|
+
*/
|
|
13
|
+
export declare const SwapStatus: {
|
|
14
|
+
readonly PENDING: 'pending';
|
|
15
|
+
readonly PROCESSING: 'processing';
|
|
16
|
+
readonly SETTLING: 'settling';
|
|
17
|
+
readonly SETTLED: 'settled';
|
|
18
|
+
readonly FAILED: 'failed';
|
|
19
|
+
readonly REFUNDED: 'refunded';
|
|
20
|
+
readonly EXPIRED: 'expired';
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type SwapStatusType = (typeof SwapStatus)[keyof typeof SwapStatus];
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Swap client options
|
|
27
|
+
*/
|
|
28
|
+
export interface SwapClientOptions {
|
|
29
|
+
/** Wallet ID for tracking swaps */
|
|
30
|
+
walletId?: string;
|
|
31
|
+
/** API base URL */
|
|
32
|
+
baseUrl?: string;
|
|
33
|
+
/** Request timeout in ms */
|
|
34
|
+
timeout?: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Coin information
|
|
39
|
+
*/
|
|
40
|
+
export interface CoinInfo {
|
|
41
|
+
symbol: string;
|
|
42
|
+
name: string;
|
|
43
|
+
network: string;
|
|
44
|
+
ticker: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Coins list result
|
|
49
|
+
*/
|
|
50
|
+
export interface CoinsResult {
|
|
51
|
+
success: boolean;
|
|
52
|
+
provider: string;
|
|
53
|
+
coins: CoinInfo[];
|
|
54
|
+
count: number;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Swap quote
|
|
59
|
+
*/
|
|
60
|
+
export interface SwapQuote {
|
|
61
|
+
from: string;
|
|
62
|
+
to: string;
|
|
63
|
+
depositAmount: string;
|
|
64
|
+
settleAmount: string;
|
|
65
|
+
rate: string;
|
|
66
|
+
minAmount: number;
|
|
67
|
+
provider: string;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Quote result
|
|
72
|
+
*/
|
|
73
|
+
export interface QuoteResult {
|
|
74
|
+
success: boolean;
|
|
75
|
+
quote: SwapQuote;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Create swap parameters
|
|
80
|
+
*/
|
|
81
|
+
export interface CreateSwapParams {
|
|
82
|
+
/** Source coin (e.g., 'BTC') */
|
|
83
|
+
from: string;
|
|
84
|
+
/** Destination coin (e.g., 'ETH') */
|
|
85
|
+
to: string;
|
|
86
|
+
/** Amount to swap */
|
|
87
|
+
amount: string | number;
|
|
88
|
+
/** Address to receive swapped coins */
|
|
89
|
+
settleAddress: string;
|
|
90
|
+
/** Address for refunds (recommended) */
|
|
91
|
+
refundAddress?: string;
|
|
92
|
+
/** Override wallet ID */
|
|
93
|
+
walletId?: string;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Swap details
|
|
98
|
+
*/
|
|
99
|
+
export interface Swap {
|
|
100
|
+
id: string;
|
|
101
|
+
from: string;
|
|
102
|
+
to: string;
|
|
103
|
+
depositAddress: string;
|
|
104
|
+
depositAmount: string;
|
|
105
|
+
depositCoin?: string;
|
|
106
|
+
settleAddress: string;
|
|
107
|
+
settleAmount?: string;
|
|
108
|
+
settleCoin?: string;
|
|
109
|
+
status: SwapStatusType;
|
|
110
|
+
createdAt: string;
|
|
111
|
+
provider: string;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Swap result
|
|
116
|
+
*/
|
|
117
|
+
export interface SwapResult {
|
|
118
|
+
success: boolean;
|
|
119
|
+
swap: Swap;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Wait for swap options
|
|
124
|
+
*/
|
|
125
|
+
export interface WaitForSwapOptions {
|
|
126
|
+
/** Polling interval in ms (default: 10000) */
|
|
127
|
+
interval?: number;
|
|
128
|
+
/** Maximum wait time in ms (default: 3600000) */
|
|
129
|
+
timeout?: number;
|
|
130
|
+
/** Statuses to wait for */
|
|
131
|
+
targetStatuses?: SwapStatusType[];
|
|
132
|
+
/** Callback when status changes */
|
|
133
|
+
onStatusChange?: (status: SwapStatusType, swap: Swap) => void;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Swap history options
|
|
138
|
+
*/
|
|
139
|
+
export interface SwapHistoryOptions {
|
|
140
|
+
/** Filter by status */
|
|
141
|
+
status?: SwapStatusType;
|
|
142
|
+
/** Number of results (default: 50) */
|
|
143
|
+
limit?: number;
|
|
144
|
+
/** Pagination offset */
|
|
145
|
+
offset?: number;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Swap history pagination
|
|
150
|
+
*/
|
|
151
|
+
export interface SwapHistoryPagination {
|
|
152
|
+
total: number;
|
|
153
|
+
limit: number;
|
|
154
|
+
offset: number;
|
|
155
|
+
hasMore: boolean;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Swap history result
|
|
160
|
+
*/
|
|
161
|
+
export interface SwapHistoryResult {
|
|
162
|
+
success: boolean;
|
|
163
|
+
swaps: Swap[];
|
|
164
|
+
pagination: SwapHistoryPagination;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* SwapClient class for handling cryptocurrency swaps
|
|
169
|
+
*/
|
|
170
|
+
export declare class SwapClient {
|
|
171
|
+
/**
|
|
172
|
+
* Create a SwapClient
|
|
173
|
+
*/
|
|
174
|
+
constructor(options?: SwapClientOptions);
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Set the wallet ID for tracking swaps
|
|
178
|
+
*/
|
|
179
|
+
setWalletId(walletId: string): void;
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Get list of supported coins for swaps
|
|
183
|
+
*/
|
|
184
|
+
getSwapCoins(options?: { search?: string }): Promise<CoinsResult>;
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Get a swap quote
|
|
188
|
+
*/
|
|
189
|
+
getSwapQuote(from: string, to: string, amount: string | number): Promise<QuoteResult>;
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Create a swap transaction
|
|
193
|
+
*/
|
|
194
|
+
createSwap(params: CreateSwapParams): Promise<SwapResult>;
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Get the status of a swap
|
|
198
|
+
*/
|
|
199
|
+
getSwapStatus(swapId: string): Promise<SwapResult>;
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Wait for a swap to complete
|
|
203
|
+
*/
|
|
204
|
+
waitForSwap(swapId: string, options?: WaitForSwapOptions): Promise<SwapResult>;
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Get swap history for a wallet
|
|
208
|
+
*/
|
|
209
|
+
getSwapHistory(walletId?: string, options?: SwapHistoryOptions): Promise<SwapHistoryResult>;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Get supported swap coins (convenience function)
|
|
214
|
+
*/
|
|
215
|
+
export declare function getSwapCoins(options?: {
|
|
216
|
+
baseUrl?: string;
|
|
217
|
+
search?: string;
|
|
218
|
+
}): Promise<CoinsResult>;
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Get a swap quote (convenience function)
|
|
222
|
+
*/
|
|
223
|
+
export declare function getSwapQuote(
|
|
224
|
+
from: string,
|
|
225
|
+
to: string,
|
|
226
|
+
amount: string | number,
|
|
227
|
+
options?: { baseUrl?: string }
|
|
228
|
+
): Promise<QuoteResult>;
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Create a swap (convenience function)
|
|
232
|
+
*/
|
|
233
|
+
export declare function createSwap(
|
|
234
|
+
params: CreateSwapParams,
|
|
235
|
+
options?: { baseUrl?: string }
|
|
236
|
+
): Promise<SwapResult>;
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Get swap status (convenience function)
|
|
240
|
+
*/
|
|
241
|
+
export declare function getSwapStatus(
|
|
242
|
+
swapId: string,
|
|
243
|
+
options?: { baseUrl?: string }
|
|
244
|
+
): Promise<SwapResult>;
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Get swap history (convenience function)
|
|
248
|
+
*/
|
|
249
|
+
export declare function getSwapHistory(
|
|
250
|
+
walletId: string,
|
|
251
|
+
options?: SwapHistoryOptions & { baseUrl?: string }
|
|
252
|
+
): Promise<SwapHistoryResult>;
|
|
253
|
+
|
|
254
|
+
export default SwapClient;
|
package/src/swap.js
ADDED
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Swap Module for CoinPay SDK
|
|
3
|
+
*
|
|
4
|
+
* Provides cryptocurrency swap functionality using ChangeNow v2 API.
|
|
5
|
+
* Swaps are non-custodial and work in the USA (no KYC required).
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const DEFAULT_BASE_URL = 'https://coinpayportal.com/api';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Supported coins for swaps
|
|
12
|
+
*/
|
|
13
|
+
export const SwapCoins = [
|
|
14
|
+
'BTC', 'BCH', 'ETH', 'POL', 'SOL',
|
|
15
|
+
'BNB', 'DOGE', 'XRP', 'ADA',
|
|
16
|
+
'USDT', 'USDT_ETH', 'USDT_POL', 'USDT_SOL',
|
|
17
|
+
'USDC', 'USDC_ETH', 'USDC_POL', 'USDC_SOL',
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Swap status mapping
|
|
22
|
+
*/
|
|
23
|
+
export const SwapStatus = {
|
|
24
|
+
PENDING: 'pending',
|
|
25
|
+
PROCESSING: 'processing',
|
|
26
|
+
SETTLING: 'settling',
|
|
27
|
+
SETTLED: 'settled',
|
|
28
|
+
FAILED: 'failed',
|
|
29
|
+
REFUNDED: 'refunded',
|
|
30
|
+
EXPIRED: 'expired',
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* SwapClient - Handles cryptocurrency swaps
|
|
35
|
+
*/
|
|
36
|
+
export class SwapClient {
|
|
37
|
+
#baseUrl;
|
|
38
|
+
#timeout;
|
|
39
|
+
#walletId;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Create a SwapClient
|
|
43
|
+
* @param {Object} options - Client options
|
|
44
|
+
* @param {string} [options.walletId] - Wallet ID for tracking swaps
|
|
45
|
+
* @param {string} [options.baseUrl] - API base URL
|
|
46
|
+
* @param {number} [options.timeout] - Request timeout in ms
|
|
47
|
+
*/
|
|
48
|
+
constructor(options = {}) {
|
|
49
|
+
this.#baseUrl = (options.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, '');
|
|
50
|
+
this.#timeout = options.timeout || 30000;
|
|
51
|
+
this.#walletId = options.walletId || null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Set the wallet ID for tracking swaps
|
|
56
|
+
* @param {string} walletId - Wallet ID
|
|
57
|
+
*/
|
|
58
|
+
setWalletId(walletId) {
|
|
59
|
+
this.#walletId = walletId;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Make an API request
|
|
64
|
+
* @private
|
|
65
|
+
*/
|
|
66
|
+
async #request(endpoint, options = {}) {
|
|
67
|
+
const url = `${this.#baseUrl}${endpoint}`;
|
|
68
|
+
const controller = new AbortController();
|
|
69
|
+
const timeoutId = setTimeout(() => controller.abort(), this.#timeout);
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
const response = await fetch(url, {
|
|
73
|
+
...options,
|
|
74
|
+
signal: controller.signal,
|
|
75
|
+
headers: {
|
|
76
|
+
'Content-Type': 'application/json',
|
|
77
|
+
...options.headers,
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const data = await response.json();
|
|
82
|
+
|
|
83
|
+
if (!response.ok) {
|
|
84
|
+
const error = new Error(data.error || `HTTP ${response.status}`);
|
|
85
|
+
error.status = response.status;
|
|
86
|
+
error.response = data;
|
|
87
|
+
throw error;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return data;
|
|
91
|
+
} catch (error) {
|
|
92
|
+
if (error.name === 'AbortError') {
|
|
93
|
+
throw new Error(`Request timeout after ${this.#timeout}ms`);
|
|
94
|
+
}
|
|
95
|
+
throw error;
|
|
96
|
+
} finally {
|
|
97
|
+
clearTimeout(timeoutId);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Get list of supported coins for swaps
|
|
103
|
+
* @param {Object} [options] - Query options
|
|
104
|
+
* @param {string} [options.search] - Search/filter coins by name or symbol
|
|
105
|
+
* @returns {Promise<Object>} List of supported coins
|
|
106
|
+
*/
|
|
107
|
+
async getSwapCoins(options = {}) {
|
|
108
|
+
const result = await this.#request('/swap/coins');
|
|
109
|
+
|
|
110
|
+
if (options.search) {
|
|
111
|
+
const search = options.search.toLowerCase();
|
|
112
|
+
result.coins = result.coins.filter(coin =>
|
|
113
|
+
coin.symbol.toLowerCase().includes(search) ||
|
|
114
|
+
coin.name.toLowerCase().includes(search)
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return result;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Get a swap quote
|
|
123
|
+
* @param {string} from - Source coin (e.g., 'BTC')
|
|
124
|
+
* @param {string} to - Destination coin (e.g., 'ETH')
|
|
125
|
+
* @param {string|number} amount - Amount to swap
|
|
126
|
+
* @returns {Promise<Object>} Swap quote with rates and estimates
|
|
127
|
+
*/
|
|
128
|
+
async getSwapQuote(from, to, amount) {
|
|
129
|
+
if (!from || !to || !amount) {
|
|
130
|
+
throw new Error('from, to, and amount are required');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const fromUpper = from.toUpperCase();
|
|
134
|
+
const toUpper = to.toUpperCase();
|
|
135
|
+
|
|
136
|
+
if (!SwapCoins.includes(fromUpper)) {
|
|
137
|
+
throw new Error(`Unsupported source coin: ${fromUpper}. Supported: ${SwapCoins.join(', ')}`);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (!SwapCoins.includes(toUpper)) {
|
|
141
|
+
throw new Error(`Unsupported destination coin: ${toUpper}. Supported: ${SwapCoins.join(', ')}`);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (fromUpper === toUpper) {
|
|
145
|
+
throw new Error('Cannot swap a coin for itself');
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const params = new URLSearchParams({
|
|
149
|
+
from: fromUpper,
|
|
150
|
+
to: toUpper,
|
|
151
|
+
amount: String(amount),
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
return this.#request(`/swap/quote?${params}`);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Create a swap transaction
|
|
159
|
+
* @param {Object} params - Swap parameters
|
|
160
|
+
* @param {string} params.from - Source coin
|
|
161
|
+
* @param {string} params.to - Destination coin
|
|
162
|
+
* @param {string|number} params.amount - Amount to swap
|
|
163
|
+
* @param {string} params.settleAddress - Address to receive swapped coins
|
|
164
|
+
* @param {string} [params.refundAddress] - Address for refunds (recommended)
|
|
165
|
+
* @param {string} [params.walletId] - Override wallet ID for this swap
|
|
166
|
+
* @returns {Promise<Object>} Swap transaction with deposit address
|
|
167
|
+
*/
|
|
168
|
+
async createSwap(params) {
|
|
169
|
+
const { from, to, amount, settleAddress, refundAddress, walletId } = params;
|
|
170
|
+
|
|
171
|
+
if (!from || !to || !amount || !settleAddress) {
|
|
172
|
+
throw new Error('from, to, amount, and settleAddress are required');
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const effectiveWalletId = walletId || this.#walletId;
|
|
176
|
+
if (!effectiveWalletId) {
|
|
177
|
+
throw new Error('walletId is required. Set it in constructor or pass it in params.');
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const fromUpper = from.toUpperCase();
|
|
181
|
+
const toUpper = to.toUpperCase();
|
|
182
|
+
|
|
183
|
+
if (!SwapCoins.includes(fromUpper)) {
|
|
184
|
+
throw new Error(`Unsupported source coin: ${fromUpper}`);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (!SwapCoins.includes(toUpper)) {
|
|
188
|
+
throw new Error(`Unsupported destination coin: ${toUpper}`);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (fromUpper === toUpper) {
|
|
192
|
+
throw new Error('Cannot swap a coin for itself');
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return this.#request('/swap/create', {
|
|
196
|
+
method: 'POST',
|
|
197
|
+
body: JSON.stringify({
|
|
198
|
+
from: fromUpper,
|
|
199
|
+
to: toUpper,
|
|
200
|
+
amount: String(amount),
|
|
201
|
+
settleAddress,
|
|
202
|
+
refundAddress,
|
|
203
|
+
walletId: effectiveWalletId,
|
|
204
|
+
}),
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Get the status of a swap
|
|
210
|
+
* @param {string} swapId - Swap transaction ID
|
|
211
|
+
* @returns {Promise<Object>} Swap status and details
|
|
212
|
+
*/
|
|
213
|
+
async getSwapStatus(swapId) {
|
|
214
|
+
if (!swapId) {
|
|
215
|
+
throw new Error('swapId is required');
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return this.#request(`/swap/${swapId}`);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Wait for a swap to complete
|
|
223
|
+
* @param {string} swapId - Swap transaction ID
|
|
224
|
+
* @param {Object} [options] - Polling options
|
|
225
|
+
* @param {number} [options.interval=10000] - Polling interval in ms
|
|
226
|
+
* @param {number} [options.timeout=3600000] - Maximum wait time in ms (default: 1 hour)
|
|
227
|
+
* @param {string[]} [options.targetStatuses] - Statuses to wait for
|
|
228
|
+
* @param {Function} [options.onStatusChange] - Callback when status changes
|
|
229
|
+
* @returns {Promise<Object>} Final swap status
|
|
230
|
+
*/
|
|
231
|
+
async waitForSwap(swapId, options = {}) {
|
|
232
|
+
const {
|
|
233
|
+
interval = 10000,
|
|
234
|
+
timeout = 3600000,
|
|
235
|
+
targetStatuses = [SwapStatus.SETTLED, SwapStatus.FAILED, SwapStatus.REFUNDED, SwapStatus.EXPIRED],
|
|
236
|
+
onStatusChange,
|
|
237
|
+
} = options;
|
|
238
|
+
|
|
239
|
+
const startTime = Date.now();
|
|
240
|
+
let lastStatus = null;
|
|
241
|
+
|
|
242
|
+
while (Date.now() - startTime < timeout) {
|
|
243
|
+
const result = await this.getSwapStatus(swapId);
|
|
244
|
+
const currentStatus = result.swap?.status;
|
|
245
|
+
|
|
246
|
+
// Notify on status change
|
|
247
|
+
if (currentStatus !== lastStatus) {
|
|
248
|
+
if (onStatusChange && lastStatus !== null) {
|
|
249
|
+
onStatusChange(currentStatus, result.swap);
|
|
250
|
+
}
|
|
251
|
+
lastStatus = currentStatus;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Check if we've reached a target status
|
|
255
|
+
if (targetStatuses.includes(currentStatus)) {
|
|
256
|
+
return result;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Wait before next poll
|
|
260
|
+
await new Promise(resolve => setTimeout(resolve, interval));
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
throw new Error(`Swap status check timed out after ${timeout}ms`);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Get swap history for a wallet
|
|
268
|
+
* @param {string} [walletId] - Wallet ID (uses default if not provided)
|
|
269
|
+
* @param {Object} [options] - Query options
|
|
270
|
+
* @param {string} [options.status] - Filter by status
|
|
271
|
+
* @param {number} [options.limit=50] - Number of results
|
|
272
|
+
* @param {number} [options.offset=0] - Pagination offset
|
|
273
|
+
* @returns {Promise<Object>} Swap history
|
|
274
|
+
*/
|
|
275
|
+
async getSwapHistory(walletId, options = {}) {
|
|
276
|
+
const effectiveWalletId = walletId || this.#walletId;
|
|
277
|
+
if (!effectiveWalletId) {
|
|
278
|
+
throw new Error('walletId is required');
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const params = new URLSearchParams({
|
|
282
|
+
walletId: effectiveWalletId,
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
if (options.status) params.set('status', options.status);
|
|
286
|
+
if (options.limit) params.set('limit', String(options.limit));
|
|
287
|
+
if (options.offset) params.set('offset', String(options.offset));
|
|
288
|
+
|
|
289
|
+
return this.#request(`/swap/history?${params}`);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// Convenience functions for one-off operations
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Get supported swap coins
|
|
297
|
+
* @param {Object} [options] - Options
|
|
298
|
+
* @param {string} [options.baseUrl] - API base URL
|
|
299
|
+
* @param {string} [options.search] - Search filter
|
|
300
|
+
* @returns {Promise<Object>} Supported coins
|
|
301
|
+
*/
|
|
302
|
+
export async function getSwapCoins(options = {}) {
|
|
303
|
+
const client = new SwapClient({ baseUrl: options.baseUrl });
|
|
304
|
+
return client.getSwapCoins(options);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Get a swap quote
|
|
309
|
+
* @param {string} from - Source coin
|
|
310
|
+
* @param {string} to - Destination coin
|
|
311
|
+
* @param {string|number} amount - Amount
|
|
312
|
+
* @param {Object} [options] - Options
|
|
313
|
+
* @param {string} [options.baseUrl] - API base URL
|
|
314
|
+
* @returns {Promise<Object>} Quote
|
|
315
|
+
*/
|
|
316
|
+
export async function getSwapQuote(from, to, amount, options = {}) {
|
|
317
|
+
const client = new SwapClient({ baseUrl: options.baseUrl });
|
|
318
|
+
return client.getSwapQuote(from, to, amount);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Create a swap
|
|
323
|
+
* @param {Object} params - Swap parameters
|
|
324
|
+
* @param {Object} [options] - Options
|
|
325
|
+
* @param {string} [options.baseUrl] - API base URL
|
|
326
|
+
* @returns {Promise<Object>} Swap details
|
|
327
|
+
*/
|
|
328
|
+
export async function createSwap(params, options = {}) {
|
|
329
|
+
const client = new SwapClient({
|
|
330
|
+
baseUrl: options.baseUrl,
|
|
331
|
+
walletId: params.walletId,
|
|
332
|
+
});
|
|
333
|
+
return client.createSwap(params);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Get swap status
|
|
338
|
+
* @param {string} swapId - Swap ID
|
|
339
|
+
* @param {Object} [options] - Options
|
|
340
|
+
* @param {string} [options.baseUrl] - API base URL
|
|
341
|
+
* @returns {Promise<Object>} Swap status
|
|
342
|
+
*/
|
|
343
|
+
export async function getSwapStatus(swapId, options = {}) {
|
|
344
|
+
const client = new SwapClient({ baseUrl: options.baseUrl });
|
|
345
|
+
return client.getSwapStatus(swapId);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Get swap history
|
|
350
|
+
* @param {string} walletId - Wallet ID
|
|
351
|
+
* @param {Object} [options] - Query options
|
|
352
|
+
* @param {string} [options.baseUrl] - API base URL
|
|
353
|
+
* @returns {Promise<Object>} Swap history
|
|
354
|
+
*/
|
|
355
|
+
export async function getSwapHistory(walletId, options = {}) {
|
|
356
|
+
const client = new SwapClient({ baseUrl: options.baseUrl });
|
|
357
|
+
return client.getSwapHistory(walletId, options);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
export default SwapClient;
|