riskmarket-sdk 1.0.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.
Potentially problematic release.
This version of riskmarket-sdk might be problematic. Click here for more details.
- package/README.md +418 -0
- package/dist/ProtocolSDK.d.ts +82 -0
- package/dist/ProtocolSDK.d.ts.map +1 -0
- package/dist/ProtocolSDK.js +129 -0
- package/dist/abi/ExampleABI.d.ts +160 -0
- package/dist/abi/ExampleABI.d.ts.map +1 -0
- package/dist/abi/ExampleABI.js +92 -0
- package/dist/api/APIClient.d.ts +106 -0
- package/dist/api/APIClient.d.ts.map +1 -0
- package/dist/api/APIClient.js +201 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.esm.js +729 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +746 -0
- package/dist/index.js.map +1 -0
- package/dist/transactions/TransactionBuilder.d.ts +89 -0
- package/dist/transactions/TransactionBuilder.d.ts.map +1 -0
- package/dist/transactions/TransactionBuilder.js +111 -0
- package/dist/types/index.d.ts +109 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +21 -0
- package/dist/utils/constants.d.ts +83 -0
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/constants.js +82 -0
- package/dist/utils/helpers.d.ts +75 -0
- package/dist/utils/helpers.d.ts.map +1 -0
- package/dist/utils/helpers.js +185 -0
- package/package.json +51 -0
|
@@ -0,0 +1,729 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import { ethers } from 'ethers';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Error types
|
|
6
|
+
*/
|
|
7
|
+
var ErrorType;
|
|
8
|
+
(function (ErrorType) {
|
|
9
|
+
ErrorType["API_ERROR"] = "API_ERROR";
|
|
10
|
+
ErrorType["TRANSACTION_ERROR"] = "TRANSACTION_ERROR";
|
|
11
|
+
ErrorType["VALIDATION_ERROR"] = "VALIDATION_ERROR";
|
|
12
|
+
ErrorType["NETWORK_ERROR"] = "NETWORK_ERROR";
|
|
13
|
+
})(ErrorType || (ErrorType = {}));
|
|
14
|
+
/**
|
|
15
|
+
* Custom SDK Error
|
|
16
|
+
*/
|
|
17
|
+
class SDKError extends Error {
|
|
18
|
+
constructor(message, type, details) {
|
|
19
|
+
super(message);
|
|
20
|
+
this.name = 'SDKError';
|
|
21
|
+
this.type = type;
|
|
22
|
+
this.details = details;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* APIClient class for interacting with backend APIs
|
|
28
|
+
*/
|
|
29
|
+
class APIClient {
|
|
30
|
+
/**
|
|
31
|
+
* Initialize API client
|
|
32
|
+
* @param baseURL - Base URL for API endpoints
|
|
33
|
+
* @param apiKey - Optional API key for authentication
|
|
34
|
+
*/
|
|
35
|
+
constructor(baseURL, apiKey) {
|
|
36
|
+
this.baseURL = baseURL;
|
|
37
|
+
this.apiKey = apiKey;
|
|
38
|
+
this.client = axios.create({
|
|
39
|
+
baseURL,
|
|
40
|
+
timeout: 30000,
|
|
41
|
+
headers: {
|
|
42
|
+
"Content-Type": "application/json",
|
|
43
|
+
...(apiKey && { Authorization: `Bearer ${apiKey}` }),
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
// Add response interceptor for error handling
|
|
47
|
+
this.client.interceptors.response.use((response) => response, (error) => {
|
|
48
|
+
throw this.handleAPIError(error);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Handle API errors
|
|
53
|
+
* @private
|
|
54
|
+
*/
|
|
55
|
+
handleAPIError(error) {
|
|
56
|
+
if (error.response) {
|
|
57
|
+
// Server responded with error status
|
|
58
|
+
const message = error.response.data?.message || error.message;
|
|
59
|
+
return new SDKError(`API Error: ${message}`, ErrorType.API_ERROR, {
|
|
60
|
+
status: error.response.status,
|
|
61
|
+
data: error.response.data,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
else if (error.request) {
|
|
65
|
+
// Request was made but no response
|
|
66
|
+
return new SDKError("No response from server", ErrorType.NETWORK_ERROR, {
|
|
67
|
+
originalError: error,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
// Something else happened
|
|
72
|
+
return new SDKError(`Request failed: ${error.message}`, ErrorType.API_ERROR);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// ============================================
|
|
76
|
+
// ADD YOUR API METHODS HERE
|
|
77
|
+
// ============================================
|
|
78
|
+
/**
|
|
79
|
+
* Example method - Replace with your actual API calls
|
|
80
|
+
*
|
|
81
|
+
* Template for a GET request:
|
|
82
|
+
*
|
|
83
|
+
* async getYourData(id: string): Promise<YourDataType> {
|
|
84
|
+
* try {
|
|
85
|
+
* const response = await this.client.get<APIResponse<YourDataType>>(
|
|
86
|
+
* `/your-endpoint/${id}`
|
|
87
|
+
* );
|
|
88
|
+
*
|
|
89
|
+
* if (!response.data.success) {
|
|
90
|
+
* throw new SDKError(
|
|
91
|
+
* response.data.error || 'Failed to fetch data',
|
|
92
|
+
* ErrorType.API_ERROR
|
|
93
|
+
* );
|
|
94
|
+
* }
|
|
95
|
+
*
|
|
96
|
+
* return response.data.data;
|
|
97
|
+
* } catch (error) {
|
|
98
|
+
* if (error instanceof SDKError) throw error;
|
|
99
|
+
* throw new SDKError(
|
|
100
|
+
* `Failed to fetch data: ${error}`,
|
|
101
|
+
* ErrorType.API_ERROR
|
|
102
|
+
* );
|
|
103
|
+
* }
|
|
104
|
+
* }
|
|
105
|
+
*
|
|
106
|
+
* Template for a POST request:
|
|
107
|
+
*
|
|
108
|
+
* async createYourData(data: YourInputType): Promise<YourDataType> {
|
|
109
|
+
* try {
|
|
110
|
+
* const response = await this.client.post<APIResponse<YourDataType>>(
|
|
111
|
+
* '/your-endpoint',
|
|
112
|
+
* data
|
|
113
|
+
* );
|
|
114
|
+
*
|
|
115
|
+
* if (!response.data.success) {
|
|
116
|
+
* throw new SDKError(
|
|
117
|
+
* response.data.error || 'Failed to create data',
|
|
118
|
+
* ErrorType.API_ERROR
|
|
119
|
+
* );
|
|
120
|
+
* }
|
|
121
|
+
*
|
|
122
|
+
* return response.data.data;
|
|
123
|
+
* } catch (error) {
|
|
124
|
+
* if (error instanceof SDKError) throw error;
|
|
125
|
+
* throw new SDKError(
|
|
126
|
+
* `Failed to create data: ${error}`,
|
|
127
|
+
* ErrorType.API_ERROR
|
|
128
|
+
* );
|
|
129
|
+
* }
|
|
130
|
+
* }
|
|
131
|
+
*/
|
|
132
|
+
// ============================================
|
|
133
|
+
// GENERIC REQUEST METHODS (Keep these - they're useful!)
|
|
134
|
+
// ============================================
|
|
135
|
+
/**
|
|
136
|
+
* Generic GET request
|
|
137
|
+
* @param endpoint - API endpoint (relative to baseURL)
|
|
138
|
+
* @param params - Query parameters
|
|
139
|
+
*/
|
|
140
|
+
async get(endpoint, params) {
|
|
141
|
+
try {
|
|
142
|
+
const response = await this.client.get(endpoint, {
|
|
143
|
+
params,
|
|
144
|
+
});
|
|
145
|
+
if (!response.data.success) {
|
|
146
|
+
throw new SDKError(response.data.error || "Request failed", ErrorType.API_ERROR);
|
|
147
|
+
}
|
|
148
|
+
return response.data.data;
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
if (error instanceof SDKError)
|
|
152
|
+
throw error;
|
|
153
|
+
throw new SDKError(`GET request failed: ${error}`, ErrorType.API_ERROR);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Generic POST request
|
|
158
|
+
* @param endpoint - API endpoint (relative to baseURL)
|
|
159
|
+
* @param data - Request body data
|
|
160
|
+
*/
|
|
161
|
+
async post(endpoint, data) {
|
|
162
|
+
try {
|
|
163
|
+
const response = await this.client.post(endpoint, data);
|
|
164
|
+
if (!response.data.success) {
|
|
165
|
+
throw new SDKError(response.data.error || "Request failed", ErrorType.API_ERROR);
|
|
166
|
+
}
|
|
167
|
+
return response.data.data;
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
if (error instanceof SDKError)
|
|
171
|
+
throw error;
|
|
172
|
+
throw new SDKError(`POST request failed: ${error}`, ErrorType.API_ERROR);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Generic PUT request
|
|
177
|
+
* @param endpoint - API endpoint (relative to baseURL)
|
|
178
|
+
* @param data - Request body data
|
|
179
|
+
*/
|
|
180
|
+
async put(endpoint, data) {
|
|
181
|
+
try {
|
|
182
|
+
const response = await this.client.put(endpoint, data);
|
|
183
|
+
if (!response.data.success) {
|
|
184
|
+
throw new SDKError(response.data.error || "Request failed", ErrorType.API_ERROR);
|
|
185
|
+
}
|
|
186
|
+
return response.data.data;
|
|
187
|
+
}
|
|
188
|
+
catch (error) {
|
|
189
|
+
if (error instanceof SDKError)
|
|
190
|
+
throw error;
|
|
191
|
+
throw new SDKError(`PUT request failed: ${error}`, ErrorType.API_ERROR);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Generic DELETE request
|
|
196
|
+
* @param endpoint - API endpoint (relative to baseURL)
|
|
197
|
+
*/
|
|
198
|
+
async delete(endpoint) {
|
|
199
|
+
try {
|
|
200
|
+
const response = await this.client.delete(endpoint);
|
|
201
|
+
if (!response.data.success) {
|
|
202
|
+
throw new SDKError(response.data.error || "Request failed", ErrorType.API_ERROR);
|
|
203
|
+
}
|
|
204
|
+
return response.data.data;
|
|
205
|
+
}
|
|
206
|
+
catch (error) {
|
|
207
|
+
if (error instanceof SDKError)
|
|
208
|
+
throw error;
|
|
209
|
+
throw new SDKError(`DELETE request failed: ${error}`, ErrorType.API_ERROR);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Get the base URL
|
|
214
|
+
*/
|
|
215
|
+
getBaseURL() {
|
|
216
|
+
return this.baseURL;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Get the axios instance for advanced usage
|
|
220
|
+
*/
|
|
221
|
+
getClient() {
|
|
222
|
+
return this.client;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Utility class with helper functions
|
|
228
|
+
*/
|
|
229
|
+
class Utils {
|
|
230
|
+
/**
|
|
231
|
+
* Validate Ethereum address
|
|
232
|
+
*/
|
|
233
|
+
static isValidAddress(address) {
|
|
234
|
+
try {
|
|
235
|
+
return ethers.isAddress(address);
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Validate and checksum an address
|
|
243
|
+
*/
|
|
244
|
+
static validateAddress(address) {
|
|
245
|
+
if (!this.isValidAddress(address)) {
|
|
246
|
+
throw new SDKError(`Invalid Ethereum address: ${address}`, ErrorType.VALIDATION_ERROR);
|
|
247
|
+
}
|
|
248
|
+
return ethers.getAddress(address);
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Format token amount from wei to human-readable format
|
|
252
|
+
*/
|
|
253
|
+
static formatAmount(amount, decimals = 18) {
|
|
254
|
+
try {
|
|
255
|
+
return ethers.formatUnits(amount, decimals);
|
|
256
|
+
}
|
|
257
|
+
catch (error) {
|
|
258
|
+
throw new SDKError(`Failed to format amount: ${error}`, ErrorType.VALIDATION_ERROR);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Parse human-readable amount to wei
|
|
263
|
+
*/
|
|
264
|
+
static parseAmount(amount, decimals = 18) {
|
|
265
|
+
try {
|
|
266
|
+
return ethers.parseUnits(amount, decimals).toString();
|
|
267
|
+
}
|
|
268
|
+
catch (error) {
|
|
269
|
+
throw new SDKError(`Failed to parse amount: ${error}`, ErrorType.VALIDATION_ERROR);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Validate amount is positive and not zero
|
|
274
|
+
*/
|
|
275
|
+
static validateAmount(amount) {
|
|
276
|
+
const amountBN = BigInt(amount);
|
|
277
|
+
if (amountBN <= 0n) {
|
|
278
|
+
throw new SDKError('Amount must be greater than zero', ErrorType.VALIDATION_ERROR);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Calculate deadline timestamp (current time + minutes)
|
|
283
|
+
*/
|
|
284
|
+
static getDeadline(minutes = 20) {
|
|
285
|
+
return Math.floor(Date.now() / 1000) + minutes * 60;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Calculate percentage difference
|
|
289
|
+
*/
|
|
290
|
+
static calculatePercentageChange(oldValue, newValue) {
|
|
291
|
+
const old = parseFloat(oldValue);
|
|
292
|
+
const newVal = parseFloat(newValue);
|
|
293
|
+
if (old === 0)
|
|
294
|
+
return '0';
|
|
295
|
+
const change = ((newVal - old) / old) * 100;
|
|
296
|
+
return change.toFixed(2);
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Estimate gas with buffer (adds 20% buffer)
|
|
300
|
+
*/
|
|
301
|
+
static addGasBuffer(gasEstimate, bufferPercent = 20) {
|
|
302
|
+
const estimate = BigInt(gasEstimate);
|
|
303
|
+
const buffer = estimate * BigInt(bufferPercent) / 100n;
|
|
304
|
+
return (estimate + buffer).toString();
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Parse error message from contract call
|
|
308
|
+
*/
|
|
309
|
+
static parseContractError(error) {
|
|
310
|
+
// Check for common error patterns
|
|
311
|
+
if (error.reason) {
|
|
312
|
+
return error.reason;
|
|
313
|
+
}
|
|
314
|
+
if (error.message) {
|
|
315
|
+
// Extract revert reason if present
|
|
316
|
+
const revertMatch = error.message.match(/reason="([^"]*)"/);
|
|
317
|
+
if (revertMatch) {
|
|
318
|
+
return revertMatch[1];
|
|
319
|
+
}
|
|
320
|
+
return error.message;
|
|
321
|
+
}
|
|
322
|
+
if (error.data?.message) {
|
|
323
|
+
return error.data.message;
|
|
324
|
+
}
|
|
325
|
+
return 'Unknown error occurred';
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Wait for transaction confirmation
|
|
329
|
+
*/
|
|
330
|
+
static async waitForTransaction(txHash, provider, confirmations = 1) {
|
|
331
|
+
try {
|
|
332
|
+
const receipt = await provider.waitForTransaction(txHash, confirmations);
|
|
333
|
+
return receipt;
|
|
334
|
+
}
|
|
335
|
+
catch (error) {
|
|
336
|
+
throw new SDKError(`Transaction failed: ${this.parseContractError(error)}`, ErrorType.TRANSACTION_ERROR, { txHash });
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Get current gas prices
|
|
341
|
+
*/
|
|
342
|
+
static async getGasPrices(provider) {
|
|
343
|
+
try {
|
|
344
|
+
const feeData = await provider.getFeeData();
|
|
345
|
+
return {
|
|
346
|
+
gasPrice: feeData.gasPrice || undefined,
|
|
347
|
+
maxFeePerGas: feeData.maxFeePerGas || undefined,
|
|
348
|
+
maxPriorityFeePerGas: feeData.maxPriorityFeePerGas || undefined,
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
catch (error) {
|
|
352
|
+
throw new SDKError(`Failed to fetch gas prices: ${error}`, ErrorType.NETWORK_ERROR);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Convert chain ID to network name
|
|
357
|
+
*/
|
|
358
|
+
static getNetworkName(chainId) {
|
|
359
|
+
const networks = {
|
|
360
|
+
1: 'Ethereum Mainnet',
|
|
361
|
+
5: 'Goerli',
|
|
362
|
+
11155111: 'Sepolia',
|
|
363
|
+
137: 'Polygon',
|
|
364
|
+
42161: 'Arbitrum One',
|
|
365
|
+
10: 'Optimism',
|
|
366
|
+
};
|
|
367
|
+
return networks[chainId] || `Unknown Network (${chainId})`;
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Sleep/delay utility
|
|
371
|
+
*/
|
|
372
|
+
static sleep(ms) {
|
|
373
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Retry logic for API calls
|
|
377
|
+
*/
|
|
378
|
+
static async retry(fn, maxRetries = 3, delayMs = 1000) {
|
|
379
|
+
let lastError;
|
|
380
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
381
|
+
try {
|
|
382
|
+
return await fn();
|
|
383
|
+
}
|
|
384
|
+
catch (error) {
|
|
385
|
+
lastError = error;
|
|
386
|
+
if (i < maxRetries - 1) {
|
|
387
|
+
await this.sleep(delayMs * (i + 1));
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
throw lastError;
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Format transaction hash with ellipsis
|
|
395
|
+
*/
|
|
396
|
+
static shortenHash(hash, startLength = 6, endLength = 4) {
|
|
397
|
+
if (hash.length <= startLength + endLength) {
|
|
398
|
+
return hash;
|
|
399
|
+
}
|
|
400
|
+
return `${hash.slice(0, startLength)}...${hash.slice(-endLength)}`;
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Check if a transaction was successful
|
|
404
|
+
*/
|
|
405
|
+
static isTransactionSuccessful(receipt) {
|
|
406
|
+
return receipt?.status === 1;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* TransactionBuilder class for creating blockchain transactions
|
|
412
|
+
* Returns unsigned transaction data that can be signed and sent by the frontend
|
|
413
|
+
*
|
|
414
|
+
* This is a TEMPLATE - add your own transaction methods based on your contract functions
|
|
415
|
+
*/
|
|
416
|
+
class TransactionBuilder {
|
|
417
|
+
/**
|
|
418
|
+
* Initialize TransactionBuilder
|
|
419
|
+
* @param provider - Ethers provider instance
|
|
420
|
+
* @param contractAddress - Main protocol contract address
|
|
421
|
+
* @param abi - Contract ABI
|
|
422
|
+
*/
|
|
423
|
+
constructor(provider, contractAddress, abi) {
|
|
424
|
+
this.provider = provider;
|
|
425
|
+
this.contractAddress = Utils.validateAddress(contractAddress);
|
|
426
|
+
this.contract = new ethers.Contract(this.contractAddress, abi, provider);
|
|
427
|
+
}
|
|
428
|
+
// ============================================
|
|
429
|
+
// ADD YOUR TRANSACTION PREPARATION METHODS HERE
|
|
430
|
+
// ============================================
|
|
431
|
+
/**
|
|
432
|
+
* Example method - Replace with your actual contract functions
|
|
433
|
+
*
|
|
434
|
+
* Template for preparing a transaction:
|
|
435
|
+
*
|
|
436
|
+
* async prepareYourTransaction(params: YourParams): Promise<TransactionRequest> {
|
|
437
|
+
* try {
|
|
438
|
+
* // 1. Validate inputs
|
|
439
|
+
* Utils.validateAddress(params.someAddress);
|
|
440
|
+
* Utils.validateAmount(params.amount);
|
|
441
|
+
*
|
|
442
|
+
* // 2. Populate transaction from your contract
|
|
443
|
+
* const tx = await this.contract.yourFunction.populateTransaction(
|
|
444
|
+
* params.arg1,
|
|
445
|
+
* params.arg2,
|
|
446
|
+
* // ... your parameters
|
|
447
|
+
* );
|
|
448
|
+
*
|
|
449
|
+
* // 3. Estimate gas (optional but recommended)
|
|
450
|
+
* try {
|
|
451
|
+
* const gasEstimate = await this.contract.yourFunction.estimateGas(
|
|
452
|
+
* params.arg1,
|
|
453
|
+
* params.arg2
|
|
454
|
+
* );
|
|
455
|
+
* tx.gasLimit = Utils.addGasBuffer(gasEstimate);
|
|
456
|
+
* } catch (error) {
|
|
457
|
+
* // Fallback to a default gas limit if estimation fails
|
|
458
|
+
* tx.gasLimit = BigInt(200000);
|
|
459
|
+
* console.warn('Gas estimation failed, using default:', error);
|
|
460
|
+
* }
|
|
461
|
+
*
|
|
462
|
+
* // 4. Return the unsigned transaction
|
|
463
|
+
* return tx;
|
|
464
|
+
* } catch (error) {
|
|
465
|
+
* throw new SDKError(
|
|
466
|
+
* `Failed to prepare transaction: ${Utils.parseContractError(error)}`,
|
|
467
|
+
* ErrorType.TRANSACTION_ERROR,
|
|
468
|
+
* { params }
|
|
469
|
+
* );
|
|
470
|
+
* }
|
|
471
|
+
* }
|
|
472
|
+
*/
|
|
473
|
+
// ============================================
|
|
474
|
+
// UTILITY METHODS (Keep these - they're useful for any protocol)
|
|
475
|
+
// ============================================
|
|
476
|
+
/**
|
|
477
|
+
* Create a contract instance for custom interactions
|
|
478
|
+
* @param abi - Contract ABI
|
|
479
|
+
* @param address - Contract address (optional, defaults to main contract)
|
|
480
|
+
*/
|
|
481
|
+
getContractInstance(abi, address) {
|
|
482
|
+
const contractAddress = address || this.contractAddress;
|
|
483
|
+
Utils.validateAddress(contractAddress);
|
|
484
|
+
return new ethers.Contract(contractAddress, abi, this.provider);
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Get the main contract instance
|
|
488
|
+
*/
|
|
489
|
+
getContract() {
|
|
490
|
+
return this.contract;
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Get the provider
|
|
494
|
+
*/
|
|
495
|
+
getProvider() {
|
|
496
|
+
return this.provider;
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* Estimate gas for any transaction
|
|
500
|
+
* @param tx - Transaction request
|
|
501
|
+
*/
|
|
502
|
+
async estimateGas(tx) {
|
|
503
|
+
try {
|
|
504
|
+
const gasEstimate = await this.provider.estimateGas(tx);
|
|
505
|
+
return BigInt(Utils.addGasBuffer(gasEstimate));
|
|
506
|
+
}
|
|
507
|
+
catch (error) {
|
|
508
|
+
throw new SDKError(`Failed to estimate gas: ${Utils.parseContractError(error)}`, ErrorType.TRANSACTION_ERROR);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
/**
|
|
512
|
+
* Get current gas prices
|
|
513
|
+
*/
|
|
514
|
+
async getGasPrices() {
|
|
515
|
+
return Utils.getGasPrices(this.provider);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* Main SDK class that combines all functionality
|
|
521
|
+
*
|
|
522
|
+
* @example
|
|
523
|
+
* ```typescript
|
|
524
|
+
* import { ProtocolSDK } from '@yourorg/protocol-sdk';
|
|
525
|
+
* import { ethers } from 'ethers';
|
|
526
|
+
*
|
|
527
|
+
* const provider = new ethers.JsonRpcProvider('YOUR_RPC_URL');
|
|
528
|
+
*
|
|
529
|
+
* const sdk = new ProtocolSDK({
|
|
530
|
+
* apiBaseURL: 'https://api.yourprotocol.com',
|
|
531
|
+
* provider: provider,
|
|
532
|
+
* contractAddress: '0x...',
|
|
533
|
+
* abi: YourContractABI,
|
|
534
|
+
* apiKey: 'your-api-key', // optional
|
|
535
|
+
* });
|
|
536
|
+
*
|
|
537
|
+
* // Use the SDK
|
|
538
|
+
* const markets = await sdk.api.getAllMarkets();
|
|
539
|
+
* const tx = await sdk.tx.prepareSwapTransaction({ ... });
|
|
540
|
+
* ```
|
|
541
|
+
*/
|
|
542
|
+
class ProtocolSDK {
|
|
543
|
+
/**
|
|
544
|
+
* Initialize the SDK
|
|
545
|
+
* @param config - SDK configuration
|
|
546
|
+
*/
|
|
547
|
+
constructor(config) {
|
|
548
|
+
// Validate configuration
|
|
549
|
+
this.validateConfig(config);
|
|
550
|
+
// Initialize components
|
|
551
|
+
this.provider = config.provider;
|
|
552
|
+
this.contractAddress = config.contractAddress;
|
|
553
|
+
this.chainId = config.chainId;
|
|
554
|
+
this.api = new APIClient(config.apiBaseURL, config.apiKey);
|
|
555
|
+
this.tx = new TransactionBuilder(config.provider, config.contractAddress, config.abi);
|
|
556
|
+
this.utils = Utils;
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* Validate SDK configuration
|
|
560
|
+
*/
|
|
561
|
+
validateConfig(config) {
|
|
562
|
+
if (!config.apiBaseURL) {
|
|
563
|
+
throw new SDKError('apiBaseURL is required', ErrorType.VALIDATION_ERROR);
|
|
564
|
+
}
|
|
565
|
+
if (!config.provider) {
|
|
566
|
+
throw new SDKError('provider is required', ErrorType.VALIDATION_ERROR);
|
|
567
|
+
}
|
|
568
|
+
if (!config.contractAddress) {
|
|
569
|
+
throw new SDKError('contractAddress is required', ErrorType.VALIDATION_ERROR);
|
|
570
|
+
}
|
|
571
|
+
if (!config.abi || !Array.isArray(config.abi)) {
|
|
572
|
+
throw new SDKError('abi must be an array', ErrorType.VALIDATION_ERROR);
|
|
573
|
+
}
|
|
574
|
+
// Validate contract address format
|
|
575
|
+
if (!Utils.isValidAddress(config.contractAddress)) {
|
|
576
|
+
throw new SDKError('Invalid contract address', ErrorType.VALIDATION_ERROR);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* Get network information
|
|
581
|
+
*/
|
|
582
|
+
async getNetworkInfo() {
|
|
583
|
+
try {
|
|
584
|
+
const network = await this.provider.getNetwork();
|
|
585
|
+
return {
|
|
586
|
+
name: Utils.getNetworkName(Number(network.chainId)),
|
|
587
|
+
chainId: Number(network.chainId),
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
catch (error) {
|
|
591
|
+
throw new SDKError(`Failed to get network info: ${error}`, ErrorType.NETWORK_ERROR);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
/**
|
|
595
|
+
* Get current block number
|
|
596
|
+
*/
|
|
597
|
+
async getBlockNumber() {
|
|
598
|
+
try {
|
|
599
|
+
return await this.provider.getBlockNumber();
|
|
600
|
+
}
|
|
601
|
+
catch (error) {
|
|
602
|
+
throw new SDKError(`Failed to get block number: ${error}`, ErrorType.NETWORK_ERROR);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
/**
|
|
606
|
+
* Check if provider is connected
|
|
607
|
+
*/
|
|
608
|
+
async isConnected() {
|
|
609
|
+
try {
|
|
610
|
+
await this.provider.getBlockNumber();
|
|
611
|
+
return true;
|
|
612
|
+
}
|
|
613
|
+
catch {
|
|
614
|
+
return false;
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
/**
|
|
618
|
+
* Get transaction receipt
|
|
619
|
+
* @param txHash - Transaction hash
|
|
620
|
+
*/
|
|
621
|
+
async getTransactionReceipt(txHash) {
|
|
622
|
+
try {
|
|
623
|
+
return await this.provider.getTransactionReceipt(txHash);
|
|
624
|
+
}
|
|
625
|
+
catch (error) {
|
|
626
|
+
throw new SDKError(`Failed to get transaction receipt: ${error}`, ErrorType.NETWORK_ERROR, { txHash });
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
/**
|
|
630
|
+
* Wait for transaction confirmation
|
|
631
|
+
* @param txHash - Transaction hash
|
|
632
|
+
* @param confirmations - Number of confirmations to wait for
|
|
633
|
+
*/
|
|
634
|
+
async waitForTransaction(txHash, confirmations = 1) {
|
|
635
|
+
return Utils.waitForTransaction(txHash, this.provider, confirmations);
|
|
636
|
+
}
|
|
637
|
+
/**
|
|
638
|
+
* Get SDK version
|
|
639
|
+
*/
|
|
640
|
+
static getVersion() {
|
|
641
|
+
return '1.0.0'; // This should match package.json version
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
/**
|
|
646
|
+
* Network configuration
|
|
647
|
+
*/
|
|
648
|
+
const NETWORKS = {
|
|
649
|
+
MAINNET: {
|
|
650
|
+
chainId: 1,
|
|
651
|
+
name: 'Ethereum Mainnet',
|
|
652
|
+
rpcUrl: 'https://eth.llamarpc.com',
|
|
653
|
+
},
|
|
654
|
+
GOERLI: {
|
|
655
|
+
chainId: 5,
|
|
656
|
+
name: 'Goerli Testnet',
|
|
657
|
+
rpcUrl: 'https://goerli.infura.io/v3/',
|
|
658
|
+
},
|
|
659
|
+
SEPOLIA: {
|
|
660
|
+
chainId: 11155111,
|
|
661
|
+
name: 'Sepolia Testnet',
|
|
662
|
+
rpcUrl: 'https://sepolia.infura.io/v3/',
|
|
663
|
+
},
|
|
664
|
+
POLYGON: {
|
|
665
|
+
chainId: 137,
|
|
666
|
+
name: 'Polygon Mainnet',
|
|
667
|
+
rpcUrl: 'https://polygon-rpc.com',
|
|
668
|
+
},
|
|
669
|
+
ARBITRUM: {
|
|
670
|
+
chainId: 42161,
|
|
671
|
+
name: 'Arbitrum One',
|
|
672
|
+
rpcUrl: 'https://arb1.arbitrum.io/rpc',
|
|
673
|
+
},
|
|
674
|
+
};
|
|
675
|
+
/**
|
|
676
|
+
* API endpoints
|
|
677
|
+
*/
|
|
678
|
+
const API_ENDPOINTS = {
|
|
679
|
+
MARKET_DATA: '/markets',
|
|
680
|
+
USER_BALANCE: '/balance',
|
|
681
|
+
TRANSACTIONS: '/transactions',
|
|
682
|
+
PRICES: '/prices',
|
|
683
|
+
};
|
|
684
|
+
/**
|
|
685
|
+
* Contract method names
|
|
686
|
+
*/
|
|
687
|
+
const CONTRACT_METHODS = {
|
|
688
|
+
SWAP: 'swap',
|
|
689
|
+
DEPOSIT: 'deposit',
|
|
690
|
+
WITHDRAW: 'withdraw',
|
|
691
|
+
APPROVE: 'approve',
|
|
692
|
+
BALANCE_OF: 'balanceOf',
|
|
693
|
+
ALLOWANCE: 'allowance',
|
|
694
|
+
};
|
|
695
|
+
/**
|
|
696
|
+
* Token decimals (common tokens)
|
|
697
|
+
*/
|
|
698
|
+
const TOKEN_DECIMALS = {
|
|
699
|
+
ETH: 18,
|
|
700
|
+
USDC: 6,
|
|
701
|
+
USDT: 6,
|
|
702
|
+
DAI: 18,
|
|
703
|
+
WBTC: 8,
|
|
704
|
+
};
|
|
705
|
+
/**
|
|
706
|
+
* Gas limit estimates for different operations
|
|
707
|
+
*/
|
|
708
|
+
const GAS_LIMITS = {
|
|
709
|
+
APPROVE: 50000,
|
|
710
|
+
SWAP: 200000,
|
|
711
|
+
DEPOSIT: 150000,
|
|
712
|
+
WITHDRAW: 150000,
|
|
713
|
+
TRANSFER: 21000,
|
|
714
|
+
};
|
|
715
|
+
/**
|
|
716
|
+
* Default transaction deadline (20 minutes from now)
|
|
717
|
+
*/
|
|
718
|
+
const DEFAULT_DEADLINE_MINUTES = 20;
|
|
719
|
+
/**
|
|
720
|
+
* Maximum uint256 value for unlimited approvals
|
|
721
|
+
*/
|
|
722
|
+
const MAX_UINT256 = '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff';
|
|
723
|
+
/**
|
|
724
|
+
* Zero address
|
|
725
|
+
*/
|
|
726
|
+
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
|
|
727
|
+
|
|
728
|
+
export { APIClient, API_ENDPOINTS, CONTRACT_METHODS, DEFAULT_DEADLINE_MINUTES, ErrorType, GAS_LIMITS, MAX_UINT256, NETWORKS, ProtocolSDK, SDKError, TOKEN_DECIMALS, TransactionBuilder, Utils, ZERO_ADDRESS, ProtocolSDK as default };
|
|
729
|
+
//# sourceMappingURL=index.esm.js.map
|