@bitflowlabs/core-sdk 1.0.1 → 2.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.
- package/dist/src/BitflowSDK.d.ts +23 -2
- package/dist/src/BitflowSDK.js +536 -82
- package/dist/src/BitflowSDK.js.map +1 -1
- package/dist/src/config.d.ts +1 -1
- package/dist/src/config.js +6 -4
- package/dist/src/config.js.map +1 -1
- package/dist/src/helpers/callReadOnlyHelper.js +10 -4
- package/dist/src/helpers/callReadOnlyHelper.js.map +1 -1
- package/dist/src/helpers/callSwapHelper.d.ts +2 -2
- package/dist/src/helpers/callSwapHelper.js +48 -7
- package/dist/src/helpers/callSwapHelper.js.map +1 -1
- package/dist/src/helpers/fetchDataHelper.d.ts +1 -1
- package/dist/src/helpers/fetchDataHelper.js +50 -17
- package/dist/src/helpers/fetchDataHelper.js.map +1 -1
- package/dist/src/helpers/fetchPossibleSwap.d.ts +2 -2
- package/dist/src/helpers/fetchPossibleSwap.js +10 -2
- package/dist/src/helpers/fetchPossibleSwap.js.map +1 -1
- package/dist/src/helpers/handleResultHelper.js +15 -15
- package/dist/src/helpers/handleResultHelper.js.map +1 -1
- package/dist/src/helpers/newPostConditionsHelper.d.ts +2 -0
- package/dist/src/helpers/newPostConditionsHelper.js +145 -0
- package/dist/src/helpers/newPostConditionsHelper.js.map +1 -0
- package/dist/src/helpers/postConditionsHelper.js +38 -13
- package/dist/src/helpers/postConditionsHelper.js.map +1 -1
- package/dist/src/index.d.ts +3 -2
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/keeper/keeperAPI.d.ts +10 -0
- package/dist/src/keeper/keeperAPI.js +332 -0
- package/dist/src/keeper/keeperAPI.js.map +1 -0
- package/dist/src/keeper/types.d.ts +253 -0
- package/dist/src/keeper/types.js +65 -0
- package/dist/src/keeper/types.js.map +1 -0
- package/dist/src/test-keeper-routes.d.ts +1 -0
- package/dist/src/test-keeper-routes.js +67 -0
- package/dist/src/test-keeper-routes.js.map +1 -0
- package/dist/src/test-raw-token-response.d.ts +1 -0
- package/dist/src/test-raw-token-response.js +79 -0
- package/dist/src/test-raw-token-response.js.map +1 -0
- package/dist/src/test-sdk.d.ts +1 -0
- package/dist/src/test-sdk.js +229 -0
- package/dist/src/test-sdk.js.map +1 -0
- package/dist/src/test-token.fetch.d.ts +1 -0
- package/dist/src/test-token.fetch.js +63 -0
- package/dist/src/test-token.fetch.js.map +1 -0
- package/dist/src/types.d.ts +27 -2
- package/package.json +6 -5
- package/src/BitflowSDK.ts +675 -97
- package/src/config.ts +9 -6
- package/src/helpers/callReadOnlyHelper.ts +12 -7
- package/src/helpers/callSwapHelper.ts +21 -7
- package/src/helpers/fetchDataHelper.ts +58 -19
- package/src/helpers/fetchPossibleSwap.ts +18 -4
- package/src/helpers/handleResultHelper.ts +17 -16
- package/src/helpers/newPostConditionsHelper.ts +172 -0
- package/src/helpers/postConditionsHelper.ts +71 -19
- package/src/index.ts +3 -2
- package/src/keeper/keeperAPI.ts +435 -0
- package/src/keeper/types.ts +293 -0
- package/src/test-keeper-routes.ts +76 -0
- package/src/test-raw-token-response.ts +124 -0
- package/src/test-sdk.ts +262 -0
- package/src/test-token.fetch.ts +72 -0
- package/src/types.ts +29 -2
package/src/BitflowSDK.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { StacksProvider } from
|
|
1
|
+
import { STACKS_MAINNET } from "@stacks/network";
|
|
2
|
+
import type { StacksProvider } from "@stacks/connect";
|
|
3
3
|
import {
|
|
4
4
|
SwapContext,
|
|
5
5
|
Token,
|
|
@@ -10,17 +10,48 @@ import {
|
|
|
10
10
|
RouteQuote,
|
|
11
11
|
SwapDataParamsAndPostConditions,
|
|
12
12
|
BitflowSDKConfig,
|
|
13
|
-
} from
|
|
14
|
-
import { fetchAllTokensFromAPI } from
|
|
15
|
-
import { executeSwapHelper } from
|
|
16
|
-
import { callReadOnlyFunctionHelper } from
|
|
17
|
-
import { fetchPossibleSwapsFromAPI } from
|
|
18
|
-
import { getContractInterfaceAndFunction } from
|
|
19
|
-
import { configs, validateConfig } from
|
|
20
|
-
import { executeGetParams } from
|
|
13
|
+
} from "./types";
|
|
14
|
+
import { fetchAllTokensFromAPI } from "./helpers/fetchDataHelper";
|
|
15
|
+
import { executeSwapHelper } from "./helpers/callSwapHelper";
|
|
16
|
+
import { callReadOnlyFunctionHelper } from "./helpers/callReadOnlyHelper";
|
|
17
|
+
import { fetchPossibleSwapsFromAPI } from "./helpers/fetchPossibleSwap";
|
|
18
|
+
import { getContractInterfaceAndFunction } from "./helpers/getContractInterfaceAndFunction";
|
|
19
|
+
import { configs, validateConfig } from "./config";
|
|
20
|
+
import { executeGetParams } from "./helpers/callGetSwapParams";
|
|
21
|
+
import {
|
|
22
|
+
ActionFunctionArgs,
|
|
23
|
+
AggregatorRouteData,
|
|
24
|
+
ALLOWED_CONTRACTS,
|
|
25
|
+
CancelGroupOrderResponse,
|
|
26
|
+
CancelOrderResponse,
|
|
27
|
+
CreateGroupOrderParams,
|
|
28
|
+
CreateGroupOrderResponse,
|
|
29
|
+
CreateOrderParams,
|
|
30
|
+
CreateOrderResponse,
|
|
31
|
+
GetGroupOrderResponse,
|
|
32
|
+
GetKeeperContractParams,
|
|
33
|
+
GetKeeperContractResponse,
|
|
34
|
+
GetOrderResponse,
|
|
35
|
+
GetQuoteParams,
|
|
36
|
+
GetQuoteResponse,
|
|
37
|
+
GetUserResponse,
|
|
38
|
+
KeeperOrderRouteData,
|
|
39
|
+
} from "./keeper/types";
|
|
40
|
+
import {
|
|
41
|
+
cancelGroupOrderAPI,
|
|
42
|
+
cancelOrderAPI,
|
|
43
|
+
createGroupOrderAPI,
|
|
44
|
+
createOrderAPI,
|
|
45
|
+
getGroupOrderAPI,
|
|
46
|
+
getOrCreateKeeperContractAPI,
|
|
47
|
+
getOrderAPI,
|
|
48
|
+
getQuoteAPI,
|
|
49
|
+
getUserAPI,
|
|
50
|
+
} from "./keeper/keeperAPI";
|
|
21
51
|
|
|
22
52
|
export class BitflowSDK {
|
|
23
53
|
private context: SwapContext;
|
|
54
|
+
private stacksProvider: StacksProvider | undefined;
|
|
24
55
|
|
|
25
56
|
constructor(config?: Partial<BitflowSDKConfig>) {
|
|
26
57
|
if (config) Object.assign(configs, config);
|
|
@@ -31,13 +62,30 @@ export class BitflowSDK {
|
|
|
31
62
|
availableTokens: [],
|
|
32
63
|
contractInterfaces: {},
|
|
33
64
|
functionArgs: {},
|
|
34
|
-
network:
|
|
65
|
+
network: STACKS_MAINNET,
|
|
35
66
|
swapOptions: {},
|
|
36
67
|
};
|
|
37
68
|
|
|
38
69
|
this.initializeContext();
|
|
39
70
|
}
|
|
71
|
+
private async loadConnectDependencies() {
|
|
72
|
+
if (typeof window === "undefined") {
|
|
73
|
+
throw new Error(
|
|
74
|
+
"Connect features are only available in browser environments"
|
|
75
|
+
);
|
|
76
|
+
}
|
|
40
77
|
|
|
78
|
+
try {
|
|
79
|
+
const { getStacksProvider } = await import("@stacks/connect");
|
|
80
|
+
if (!this.stacksProvider) {
|
|
81
|
+
this.stacksProvider = await getStacksProvider();
|
|
82
|
+
}
|
|
83
|
+
return this.stacksProvider;
|
|
84
|
+
} catch (error) {
|
|
85
|
+
console.error("Error loading Stacks Connect:", error);
|
|
86
|
+
throw new Error("Failed to load Stacks Connect dependencies");
|
|
87
|
+
}
|
|
88
|
+
}
|
|
41
89
|
private async initializeContext(): Promise<void> {
|
|
42
90
|
this.context.availableTokens = await fetchAllTokensFromAPI();
|
|
43
91
|
}
|
|
@@ -49,6 +97,13 @@ export class BitflowSDK {
|
|
|
49
97
|
return this.context.availableTokens;
|
|
50
98
|
}
|
|
51
99
|
|
|
100
|
+
public async getKeeperTokens(): Promise<Token[]> {
|
|
101
|
+
if (this.context.availableTokens.length === 0) {
|
|
102
|
+
await this.initializeContext();
|
|
103
|
+
}
|
|
104
|
+
return this.context.availableTokens.filter((token) => token.isKeeperToken);
|
|
105
|
+
}
|
|
106
|
+
|
|
52
107
|
public async getPossibleSwaps(tokenX: string): Promise<SwapOptions> {
|
|
53
108
|
if (!this.context.swapOptions[tokenX]) {
|
|
54
109
|
this.context.swapOptions[tokenX] = await fetchPossibleSwapsFromAPI(
|
|
@@ -58,11 +113,28 @@ export class BitflowSDK {
|
|
|
58
113
|
return this.context.swapOptions[tokenX];
|
|
59
114
|
}
|
|
60
115
|
|
|
116
|
+
public async getKeeperPossibleSwaps(tokenX: string): Promise<SwapOptions> {
|
|
117
|
+
// Use a separate cache key for keeper routes
|
|
118
|
+
const cacheKey = `keeper_${tokenX}`;
|
|
119
|
+
if (!this.context.swapOptions[cacheKey]) {
|
|
120
|
+
this.context.swapOptions[cacheKey] = await fetchPossibleSwapsFromAPI(
|
|
121
|
+
tokenX,
|
|
122
|
+
"KEEPER"
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
return this.context.swapOptions[cacheKey];
|
|
126
|
+
}
|
|
127
|
+
|
|
61
128
|
public async getAllPossibleTokenY(tokenX: string): Promise<string[]> {
|
|
62
129
|
const swapOptions = await this.getPossibleSwaps(tokenX);
|
|
63
130
|
return Object.keys(swapOptions);
|
|
64
131
|
}
|
|
65
132
|
|
|
133
|
+
public async getAllKeeperPossibleTokenY(tokenX: string): Promise<string[]> {
|
|
134
|
+
const swapOptions = await this.getKeeperPossibleSwaps(tokenX);
|
|
135
|
+
return Object.keys(swapOptions);
|
|
136
|
+
}
|
|
137
|
+
|
|
66
138
|
public async getAllPossibleTokenYRoutes(
|
|
67
139
|
tokenX: string,
|
|
68
140
|
tokenY: string
|
|
@@ -71,6 +143,14 @@ export class BitflowSDK {
|
|
|
71
143
|
return swapOptions[tokenY] || [];
|
|
72
144
|
}
|
|
73
145
|
|
|
146
|
+
public async getAllKeeperPossibleTokenYRoutes(
|
|
147
|
+
tokenX: string,
|
|
148
|
+
tokenY: string
|
|
149
|
+
): Promise<SelectedSwapRoute[]> {
|
|
150
|
+
const swapOptions = await this.getKeeperPossibleSwaps(tokenX);
|
|
151
|
+
return swapOptions[tokenY] || [];
|
|
152
|
+
}
|
|
153
|
+
|
|
74
154
|
public async getQuoteForRoute(
|
|
75
155
|
tokenX: string,
|
|
76
156
|
tokenY: string,
|
|
@@ -82,7 +162,6 @@ export class BitflowSDK {
|
|
|
82
162
|
for (let routeIndex = 0; routeIndex < routes.length; routeIndex++) {
|
|
83
163
|
const route = routes[routeIndex];
|
|
84
164
|
try {
|
|
85
|
-
// Check if quoteData is null or undefined
|
|
86
165
|
if (!route.quoteData) {
|
|
87
166
|
console.warn(
|
|
88
167
|
`Skipping route ${routeIndex + 1} due to null quoteData:`,
|
|
@@ -97,7 +176,6 @@ export class BitflowSDK {
|
|
|
97
176
|
parameters,
|
|
98
177
|
} = route.quoteData;
|
|
99
178
|
|
|
100
|
-
// Check if any required property is missing
|
|
101
179
|
if (!contract || !functionName || !parameters) {
|
|
102
180
|
console.warn(
|
|
103
181
|
`Skipping route ${
|
|
@@ -108,7 +186,7 @@ export class BitflowSDK {
|
|
|
108
186
|
continue;
|
|
109
187
|
}
|
|
110
188
|
|
|
111
|
-
const [contractDeployer, contractName] = contract.split(
|
|
189
|
+
const [contractDeployer, contractName] = contract.split(".");
|
|
112
190
|
|
|
113
191
|
if (!this.context.contractInterfaces[contract]) {
|
|
114
192
|
this.context.contractInterfaces[contract] =
|
|
@@ -123,21 +201,21 @@ export class BitflowSDK {
|
|
|
123
201
|
|
|
124
202
|
const params = { ...parameters };
|
|
125
203
|
|
|
126
|
-
if (
|
|
204
|
+
if ("dx" in params && params.dx === null) {
|
|
127
205
|
params.dx = amountInput;
|
|
128
|
-
} else if (
|
|
206
|
+
} else if ("dy" in params && params.dy === null) {
|
|
129
207
|
params.dy = amountInput;
|
|
130
|
-
} else if (
|
|
208
|
+
} else if ("amount" in params && params.amount === null) {
|
|
131
209
|
params.amount = amountInput;
|
|
132
|
-
} else if (
|
|
133
|
-
params[
|
|
134
|
-
} else if (
|
|
135
|
-
params[
|
|
136
|
-
} else if (
|
|
137
|
-
params[
|
|
138
|
-
params[
|
|
139
|
-
} else if (
|
|
140
|
-
params[
|
|
210
|
+
} else if ("amt-in" in params && params["amt-in"] === null) {
|
|
211
|
+
params["amt-in"] = amountInput;
|
|
212
|
+
} else if ("amt-in-max" in params && params["amt-in-max"] === null) {
|
|
213
|
+
params["amt-in-max"] = amountInput;
|
|
214
|
+
} else if ("y-amount" in params && params["y-amount"] === null) {
|
|
215
|
+
params["y-amount"] = amountInput;
|
|
216
|
+
params["x-amount"] = amountInput;
|
|
217
|
+
} else if ("x-amount" in params && params["x-amount"] === null) {
|
|
218
|
+
params["x-amount"] = amountInput;
|
|
141
219
|
} else {
|
|
142
220
|
params.dx = amountInput;
|
|
143
221
|
}
|
|
@@ -155,7 +233,7 @@ export class BitflowSDK {
|
|
|
155
233
|
this.context
|
|
156
234
|
);
|
|
157
235
|
|
|
158
|
-
if (typeof convertedResult ===
|
|
236
|
+
if (typeof convertedResult === "number" && convertedResult > 0) {
|
|
159
237
|
const updatedQuoteData = {
|
|
160
238
|
...route.quoteData,
|
|
161
239
|
parameters: { ...params },
|
|
@@ -168,70 +246,70 @@ export class BitflowSDK {
|
|
|
168
246
|
amount:
|
|
169
247
|
params.amount ||
|
|
170
248
|
params.dx ||
|
|
171
|
-
params[
|
|
172
|
-
params[
|
|
173
|
-
params[
|
|
174
|
-
params[
|
|
249
|
+
params["amt-in"] ||
|
|
250
|
+
params["amt-in-max"] ||
|
|
251
|
+
params["y-amount"] ||
|
|
252
|
+
params["x-amount"] ||
|
|
175
253
|
params.dy,
|
|
176
254
|
dx:
|
|
177
255
|
params.amount ||
|
|
178
256
|
params.dx ||
|
|
179
|
-
params[
|
|
180
|
-
params[
|
|
181
|
-
params[
|
|
182
|
-
params[
|
|
257
|
+
params["amt-in"] ||
|
|
258
|
+
params["amt-in-max"] ||
|
|
259
|
+
params["y-amount"] ||
|
|
260
|
+
params["x-amount"] ||
|
|
183
261
|
params.dy,
|
|
184
262
|
dy:
|
|
185
263
|
params.amount ||
|
|
186
264
|
params.dx ||
|
|
187
|
-
params[
|
|
188
|
-
params[
|
|
189
|
-
params[
|
|
190
|
-
params[
|
|
265
|
+
params["amt-in"] ||
|
|
266
|
+
params["amt-in-max"] ||
|
|
267
|
+
params["y-amount"] ||
|
|
268
|
+
params["x-amount"] ||
|
|
191
269
|
params.dy,
|
|
192
|
-
|
|
270
|
+
"amt-in":
|
|
193
271
|
params.amount ||
|
|
194
272
|
params.dx ||
|
|
195
|
-
params[
|
|
196
|
-
params[
|
|
197
|
-
params[
|
|
198
|
-
params[
|
|
273
|
+
params["amt-in"] ||
|
|
274
|
+
params["amt-in-max"] ||
|
|
275
|
+
params["y-amount"] ||
|
|
276
|
+
params["x-amount"] ||
|
|
199
277
|
params.dy,
|
|
200
|
-
|
|
278
|
+
"amt-in-max":
|
|
201
279
|
params.amount ||
|
|
202
280
|
params.dx ||
|
|
203
|
-
params[
|
|
204
|
-
params[
|
|
205
|
-
params[
|
|
206
|
-
params[
|
|
281
|
+
params["amt-in"] ||
|
|
282
|
+
params["amt-in-max"] ||
|
|
283
|
+
params["y-amount"] ||
|
|
284
|
+
params["x-amount"] ||
|
|
207
285
|
params.dy,
|
|
208
|
-
|
|
286
|
+
"y-amount":
|
|
209
287
|
params.amount ||
|
|
210
288
|
params.dx ||
|
|
211
|
-
params[
|
|
212
|
-
params[
|
|
213
|
-
params[
|
|
214
|
-
params[
|
|
289
|
+
params["amt-in"] ||
|
|
290
|
+
params["amt-in-max"] ||
|
|
291
|
+
params["y-amount"] ||
|
|
292
|
+
params["x-amount"] ||
|
|
215
293
|
params.dy,
|
|
216
|
-
|
|
294
|
+
"x-amount":
|
|
217
295
|
params.amount ||
|
|
218
296
|
params.dx ||
|
|
219
|
-
params[
|
|
220
|
-
params[
|
|
221
|
-
params[
|
|
222
|
-
params[
|
|
297
|
+
params["amt-in"] ||
|
|
298
|
+
params["amt-in-max"] ||
|
|
299
|
+
params["y-amount"] ||
|
|
300
|
+
params["x-amount"] ||
|
|
223
301
|
params.dy,
|
|
224
302
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
303
|
+
"min-received": rawResult,
|
|
304
|
+
"min-dy": rawResult,
|
|
305
|
+
"min-dz": rawResult,
|
|
306
|
+
"min-dw": rawResult,
|
|
307
|
+
"amt-out": rawResult,
|
|
308
|
+
"amt-out-min": rawResult,
|
|
309
|
+
"min-x-amount": rawResult,
|
|
310
|
+
"min-dv": rawResult,
|
|
311
|
+
"min-y-amount": rawResult,
|
|
312
|
+
"min-dx": rawResult,
|
|
235
313
|
},
|
|
236
314
|
};
|
|
237
315
|
|
|
@@ -253,7 +331,7 @@ export class BitflowSDK {
|
|
|
253
331
|
|
|
254
332
|
allRoutes.push(quoteResult);
|
|
255
333
|
} else {
|
|
256
|
-
throw new Error(
|
|
334
|
+
throw new Error("Invalid quote result");
|
|
257
335
|
}
|
|
258
336
|
} catch (error) {
|
|
259
337
|
console.warn(
|
|
@@ -289,6 +367,224 @@ export class BitflowSDK {
|
|
|
289
367
|
return result;
|
|
290
368
|
}
|
|
291
369
|
|
|
370
|
+
public async getKeeperQuoteForRoute(
|
|
371
|
+
tokenX: string,
|
|
372
|
+
tokenY: string,
|
|
373
|
+
amountInput: number
|
|
374
|
+
): Promise<QuoteResult> {
|
|
375
|
+
const COMPATIBLE_DEX_PATHS = new Set([
|
|
376
|
+
"BITFLOW_STABLE_XY_2",
|
|
377
|
+
"BITFLOW_XYK_XY_2",
|
|
378
|
+
]);
|
|
379
|
+
|
|
380
|
+
const isCompatibleRoute = (dexPath: string[]): boolean => {
|
|
381
|
+
return dexPath.every((path) => COMPATIBLE_DEX_PATHS.has(path));
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
let routes = await this.getAllPossibleTokenYRoutes(tokenX, tokenY);
|
|
385
|
+
routes = routes.filter((route) => isCompatibleRoute(route.dex_path));
|
|
386
|
+
|
|
387
|
+
const allRoutes: RouteQuote[] = [];
|
|
388
|
+
|
|
389
|
+
for (let routeIndex = 0; routeIndex < routes.length; routeIndex++) {
|
|
390
|
+
const route = routes[routeIndex];
|
|
391
|
+
|
|
392
|
+
try {
|
|
393
|
+
if (!route.quoteData) {
|
|
394
|
+
console.warn(
|
|
395
|
+
`Skipping route ${routeIndex + 1} due to null quoteData:`,
|
|
396
|
+
route
|
|
397
|
+
);
|
|
398
|
+
continue;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
const {
|
|
402
|
+
contract,
|
|
403
|
+
function: functionName,
|
|
404
|
+
parameters,
|
|
405
|
+
} = route.quoteData;
|
|
406
|
+
|
|
407
|
+
if (!contract || !functionName || !parameters) {
|
|
408
|
+
console.warn(
|
|
409
|
+
`Skipping route ${
|
|
410
|
+
routeIndex + 1
|
|
411
|
+
} due to missing required properties:`,
|
|
412
|
+
route.quoteData
|
|
413
|
+
);
|
|
414
|
+
continue;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
const [contractDeployer, contractName] = contract.split(".");
|
|
418
|
+
|
|
419
|
+
if (!this.context.contractInterfaces[contract]) {
|
|
420
|
+
this.context.contractInterfaces[contract] =
|
|
421
|
+
await getContractInterfaceAndFunction(
|
|
422
|
+
contractDeployer,
|
|
423
|
+
contractName,
|
|
424
|
+
functionName
|
|
425
|
+
);
|
|
426
|
+
}
|
|
427
|
+
const { interface: contractInterface, functionArgs } =
|
|
428
|
+
this.context.contractInterfaces[contract];
|
|
429
|
+
|
|
430
|
+
const params = { ...parameters };
|
|
431
|
+
|
|
432
|
+
if ("dx" in params && params.dx === null) {
|
|
433
|
+
params.dx = amountInput;
|
|
434
|
+
} else if ("dy" in params && params.dy === null) {
|
|
435
|
+
params.dy = amountInput;
|
|
436
|
+
} else if ("amount" in params && params.amount === null) {
|
|
437
|
+
params.amount = amountInput;
|
|
438
|
+
} else if ("amt-in" in params && params["amt-in"] === null) {
|
|
439
|
+
params["amt-in"] = amountInput;
|
|
440
|
+
} else if ("amt-in-max" in params && params["amt-in-max"] === null) {
|
|
441
|
+
params["amt-in-max"] = amountInput;
|
|
442
|
+
} else if ("y-amount" in params && params["y-amount"] === null) {
|
|
443
|
+
params["y-amount"] = amountInput;
|
|
444
|
+
params["x-amount"] = amountInput;
|
|
445
|
+
} else if ("x-amount" in params && params["x-amount"] === null) {
|
|
446
|
+
params["x-amount"] = amountInput;
|
|
447
|
+
} else {
|
|
448
|
+
params.dx = amountInput;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
const { convertedResult, rawResult, tokenXDecimals, tokenYDecimals } =
|
|
452
|
+
await callReadOnlyFunctionHelper(
|
|
453
|
+
contractDeployer,
|
|
454
|
+
contractName,
|
|
455
|
+
functionName,
|
|
456
|
+
params,
|
|
457
|
+
contractDeployer,
|
|
458
|
+
tokenX,
|
|
459
|
+
tokenY,
|
|
460
|
+
route.swapData,
|
|
461
|
+
this.context
|
|
462
|
+
);
|
|
463
|
+
|
|
464
|
+
if (typeof convertedResult === "number" && convertedResult > 0) {
|
|
465
|
+
const updatedQuoteData = {
|
|
466
|
+
...route.quoteData,
|
|
467
|
+
parameters: { ...params },
|
|
468
|
+
};
|
|
469
|
+
|
|
470
|
+
const updatedSwapData = {
|
|
471
|
+
...route.swapData,
|
|
472
|
+
parameters: {
|
|
473
|
+
...route.swapData.parameters,
|
|
474
|
+
amount:
|
|
475
|
+
params.amount ||
|
|
476
|
+
params.dx ||
|
|
477
|
+
params["amt-in"] ||
|
|
478
|
+
params["amt-in-max"] ||
|
|
479
|
+
params["y-amount"] ||
|
|
480
|
+
params["x-amount"] ||
|
|
481
|
+
params.dy,
|
|
482
|
+
dx:
|
|
483
|
+
params.amount ||
|
|
484
|
+
params.dx ||
|
|
485
|
+
params["amt-in"] ||
|
|
486
|
+
params["amt-in-max"] ||
|
|
487
|
+
params["y-amount"] ||
|
|
488
|
+
params["x-amount"] ||
|
|
489
|
+
params.dy,
|
|
490
|
+
"amt-in":
|
|
491
|
+
params.amount ||
|
|
492
|
+
params.dx ||
|
|
493
|
+
params["amt-in"] ||
|
|
494
|
+
params["amt-in-max"] ||
|
|
495
|
+
params["y-amount"] ||
|
|
496
|
+
params["x-amount"] ||
|
|
497
|
+
params.dy,
|
|
498
|
+
"amt-in-max":
|
|
499
|
+
params.amount ||
|
|
500
|
+
params.dx ||
|
|
501
|
+
params["amt-in"] ||
|
|
502
|
+
params["amt-in-max"] ||
|
|
503
|
+
params["y-amount"] ||
|
|
504
|
+
params["x-amount"] ||
|
|
505
|
+
params.dy,
|
|
506
|
+
"y-amount":
|
|
507
|
+
params.amount ||
|
|
508
|
+
params.dx ||
|
|
509
|
+
params["amt-in"] ||
|
|
510
|
+
params["amt-in-max"] ||
|
|
511
|
+
params["y-amount"] ||
|
|
512
|
+
params["x-amount"] ||
|
|
513
|
+
params.dy,
|
|
514
|
+
"x-amount":
|
|
515
|
+
params.amount ||
|
|
516
|
+
params.dx ||
|
|
517
|
+
params["amt-in"] ||
|
|
518
|
+
params["amt-in-max"] ||
|
|
519
|
+
params["y-amount"] ||
|
|
520
|
+
params["x-amount"] ||
|
|
521
|
+
params.dy,
|
|
522
|
+
"min-received": rawResult,
|
|
523
|
+
"min-dy": rawResult,
|
|
524
|
+
"min-dz": rawResult,
|
|
525
|
+
"min-dw": rawResult,
|
|
526
|
+
"amt-out": rawResult,
|
|
527
|
+
"amt-out-min": rawResult,
|
|
528
|
+
"min-x-amount": rawResult,
|
|
529
|
+
"min-dv": rawResult,
|
|
530
|
+
"min-y-amount": rawResult,
|
|
531
|
+
"min-dx": rawResult,
|
|
532
|
+
},
|
|
533
|
+
};
|
|
534
|
+
|
|
535
|
+
const quoteResult: RouteQuote = {
|
|
536
|
+
route: {
|
|
537
|
+
...route,
|
|
538
|
+
quoteData: updatedQuoteData,
|
|
539
|
+
swapData: updatedSwapData,
|
|
540
|
+
},
|
|
541
|
+
quote: convertedResult,
|
|
542
|
+
params: params,
|
|
543
|
+
quoteData: updatedQuoteData,
|
|
544
|
+
swapData: updatedSwapData,
|
|
545
|
+
dexPath: route.dex_path,
|
|
546
|
+
tokenPath: route.token_path,
|
|
547
|
+
tokenXDecimals: tokenXDecimals,
|
|
548
|
+
tokenYDecimals: tokenYDecimals,
|
|
549
|
+
};
|
|
550
|
+
|
|
551
|
+
allRoutes.push(quoteResult);
|
|
552
|
+
} else {
|
|
553
|
+
throw new Error("Invalid quote result");
|
|
554
|
+
}
|
|
555
|
+
} catch (error) {
|
|
556
|
+
console.warn(
|
|
557
|
+
`Failed to get quote for route ${routeIndex + 1}:`,
|
|
558
|
+
route,
|
|
559
|
+
error
|
|
560
|
+
);
|
|
561
|
+
allRoutes.push({
|
|
562
|
+
route,
|
|
563
|
+
quote: null,
|
|
564
|
+
params: route.quoteData
|
|
565
|
+
? { ...route.quoteData.parameters, amountInput }
|
|
566
|
+
: { amountInput },
|
|
567
|
+
quoteData: route.quoteData,
|
|
568
|
+
swapData: route.swapData,
|
|
569
|
+
dexPath: route.dex_path,
|
|
570
|
+
tokenPath: route.token_path,
|
|
571
|
+
tokenXDecimals: route.tokenXDecimals,
|
|
572
|
+
tokenYDecimals: route.tokenYDecimals,
|
|
573
|
+
error: (error as Error).message,
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
allRoutes.sort((a, b) => (b.quote || 0) - (a.quote || 0));
|
|
579
|
+
const result = {
|
|
580
|
+
bestRoute: allRoutes[0]?.quote !== null ? allRoutes[0] : null,
|
|
581
|
+
allRoutes,
|
|
582
|
+
inputData: { tokenX, tokenY, amountInput },
|
|
583
|
+
};
|
|
584
|
+
|
|
585
|
+
return result;
|
|
586
|
+
}
|
|
587
|
+
|
|
292
588
|
public async getSwapParams(
|
|
293
589
|
swapExecutionData: SwapExecutionData,
|
|
294
590
|
senderAddress: string,
|
|
@@ -306,42 +602,42 @@ export class BitflowSDK {
|
|
|
306
602
|
amount:
|
|
307
603
|
route.swapData.parameters.amount ||
|
|
308
604
|
amount ||
|
|
309
|
-
route.swapData.parameters[
|
|
310
|
-
route.swapData.parameters[
|
|
311
|
-
route.swapData.parameters[
|
|
605
|
+
route.swapData.parameters["amt-in"] ||
|
|
606
|
+
route.swapData.parameters["amt-in-max"] ||
|
|
607
|
+
route.swapData.parameters["y-amount"],
|
|
312
608
|
dx:
|
|
313
609
|
route.swapData.parameters.dx ||
|
|
314
610
|
amount ||
|
|
315
|
-
route.swapData.parameters[
|
|
316
|
-
route.swapData.parameters[
|
|
317
|
-
route.swapData.parameters[
|
|
318
|
-
|
|
611
|
+
route.swapData.parameters["amt-in"] ||
|
|
612
|
+
route.swapData.parameters["amt-in-max"] ||
|
|
613
|
+
route.swapData.parameters["y-amount"],
|
|
614
|
+
"amt-in":
|
|
319
615
|
route.swapData.parameters.dx ||
|
|
320
616
|
amount ||
|
|
321
|
-
route.swapData.parameters[
|
|
322
|
-
route.swapData.parameters[
|
|
323
|
-
route.swapData.parameters[
|
|
617
|
+
route.swapData.parameters["amt-in"] ||
|
|
618
|
+
route.swapData.parameters["amt-in-max"] ||
|
|
619
|
+
route.swapData.parameters["y-amount"] ||
|
|
324
620
|
route.swapData.parameters.dy,
|
|
325
|
-
|
|
621
|
+
"amt-in-max":
|
|
326
622
|
route.swapData.parameters.dx ||
|
|
327
623
|
amount ||
|
|
328
|
-
route.swapData.parameters[
|
|
329
|
-
route.swapData.parameters[
|
|
330
|
-
route.swapData.parameters[
|
|
624
|
+
route.swapData.parameters["amt-in"] ||
|
|
625
|
+
route.swapData.parameters["amt-in-max"] ||
|
|
626
|
+
route.swapData.parameters["y-amount"] ||
|
|
331
627
|
route.swapData.parameters.dy,
|
|
332
|
-
|
|
628
|
+
"y-amount":
|
|
333
629
|
route.swapData.parameters.dx ||
|
|
334
630
|
amount ||
|
|
335
|
-
route.swapData.parameters[
|
|
336
|
-
route.swapData.parameters[
|
|
337
|
-
route.swapData.parameters[
|
|
631
|
+
route.swapData.parameters["amt-in"] ||
|
|
632
|
+
route.swapData.parameters["amt-in-max"] ||
|
|
633
|
+
route.swapData.parameters["y-amount"] ||
|
|
338
634
|
route.swapData.parameters.dy,
|
|
339
635
|
dy:
|
|
340
636
|
route.swapData.parameters.dy ||
|
|
341
637
|
amount ||
|
|
342
|
-
route.swapData.parameters[
|
|
343
|
-
route.swapData.parameters[
|
|
344
|
-
route.swapData.parameters[
|
|
638
|
+
route.swapData.parameters["amt-in"] ||
|
|
639
|
+
route.swapData.parameters["amt-in-max"] ||
|
|
640
|
+
route.swapData.parameters["y-amount"] ||
|
|
345
641
|
route.swapData.parameters.dy,
|
|
346
642
|
},
|
|
347
643
|
},
|
|
@@ -373,13 +669,295 @@ export class BitflowSDK {
|
|
|
373
669
|
slippageTolerance
|
|
374
670
|
);
|
|
375
671
|
|
|
376
|
-
|
|
377
|
-
|
|
672
|
+
if (typeof window === "undefined") {
|
|
673
|
+
throw new Error(
|
|
674
|
+
"executeSwap is only available in browser environments. " +
|
|
675
|
+
"For Node.js environments, use getSwapParams to get the transaction parameters " +
|
|
676
|
+
"and handle the transaction execution separately."
|
|
677
|
+
);
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
try {
|
|
681
|
+
let provider: StacksProvider;
|
|
682
|
+
if (stacksProvider) {
|
|
683
|
+
provider = stacksProvider;
|
|
684
|
+
} else {
|
|
685
|
+
const loadedProvider = await this.loadConnectDependencies();
|
|
686
|
+
if (!loadedProvider) {
|
|
687
|
+
throw new Error("Failed to initialize Stacks provider");
|
|
688
|
+
}
|
|
689
|
+
provider = loadedProvider;
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
await executeSwapHelper(
|
|
693
|
+
swapParams,
|
|
694
|
+
senderAddress,
|
|
695
|
+
this.context,
|
|
696
|
+
provider,
|
|
697
|
+
onFinish,
|
|
698
|
+
onCancel
|
|
699
|
+
);
|
|
700
|
+
} catch (error) {
|
|
701
|
+
if (
|
|
702
|
+
error instanceof Error &&
|
|
703
|
+
error.message.includes("only available in browser environments")
|
|
704
|
+
) {
|
|
705
|
+
throw error;
|
|
706
|
+
}
|
|
707
|
+
console.error("Error executing swap:", error);
|
|
708
|
+
throw new Error(
|
|
709
|
+
`Failed to execute swap: ${
|
|
710
|
+
error instanceof Error ? error.message : "Unknown error"
|
|
711
|
+
}`
|
|
712
|
+
);
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
public async prepareSwap(
|
|
717
|
+
swapExecutionData: SwapExecutionData,
|
|
718
|
+
senderAddress: string,
|
|
719
|
+
slippageTolerance: number = 0.015
|
|
720
|
+
): Promise<SwapDataParamsAndPostConditions> {
|
|
721
|
+
return await this.getSwapParams(
|
|
722
|
+
swapExecutionData,
|
|
378
723
|
senderAddress,
|
|
379
|
-
|
|
380
|
-
stacksProvider,
|
|
381
|
-
onFinish,
|
|
382
|
-
onCancel
|
|
724
|
+
slippageTolerance
|
|
383
725
|
);
|
|
384
726
|
}
|
|
727
|
+
|
|
728
|
+
public async getOrCreateKeeperContract(
|
|
729
|
+
params: GetKeeperContractParams
|
|
730
|
+
): Promise<GetKeeperContractResponse> {
|
|
731
|
+
try {
|
|
732
|
+
return await getOrCreateKeeperContractAPI(params);
|
|
733
|
+
} catch (error) {
|
|
734
|
+
console.error("Error in BitflowSDK.getOrCreateKeeperContract:", error);
|
|
735
|
+
throw error;
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
public async getOrder(orderId: string): Promise<GetOrderResponse> {
|
|
740
|
+
try {
|
|
741
|
+
return await getOrderAPI(orderId);
|
|
742
|
+
} catch (error) {
|
|
743
|
+
console.error("Error in BitflowSDK.getOrder:", error);
|
|
744
|
+
throw error;
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
public async getUser(stacksAddress: string): Promise<GetUserResponse> {
|
|
749
|
+
try {
|
|
750
|
+
return await getUserAPI(stacksAddress);
|
|
751
|
+
} catch (error) {
|
|
752
|
+
console.error("Error in BitflowSDK.getUser:", error);
|
|
753
|
+
throw error;
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
public async createOrder(
|
|
758
|
+
params: CreateOrderParams
|
|
759
|
+
): Promise<CreateOrderResponse> {
|
|
760
|
+
try {
|
|
761
|
+
return await createOrderAPI(params);
|
|
762
|
+
} catch (error) {
|
|
763
|
+
console.error("Error in BitflowSDK.createOrder:", error);
|
|
764
|
+
throw error;
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
public async getQuote(params: GetQuoteParams): Promise<GetQuoteResponse> {
|
|
769
|
+
try {
|
|
770
|
+
return await getQuoteAPI(params);
|
|
771
|
+
} catch (error) {
|
|
772
|
+
console.error("Error in BitflowSDK.getQuote:", error);
|
|
773
|
+
throw error;
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
private mapDexPathToActionTrait(dexPath: string[]): string {
|
|
778
|
+
const isXYK = dexPath.some((d) => d.toLowerCase().includes("xyk"));
|
|
779
|
+
const isStable = dexPath.some((d) => d.toLowerCase().includes("stable"));
|
|
780
|
+
|
|
781
|
+
if (isXYK && !isStable) {
|
|
782
|
+
return "SM1793C4R5PZ4NS4VQ4WMP7SKKYVH8JZEWSZ9HCCR.keeper-action-1-v-1-1";
|
|
783
|
+
}
|
|
784
|
+
if (isXYK && isStable) {
|
|
785
|
+
return "SM1793C4R5PZ4NS4VQ4WMP7SKKYVH8JZEWSZ9HCCR.keeper-action-2-v-1-1";
|
|
786
|
+
}
|
|
787
|
+
if (!isXYK && isStable) {
|
|
788
|
+
return "SM1793C4R5PZ4NS4VQ4WMP7SKKYVH8JZEWSZ9HCCR.keeper-action-3-v-1-1";
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
throw new Error(`Unsupported DEX path: ${dexPath.join(", ")}`);
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
private async transformRouteToActionArgs(
|
|
795
|
+
route: RouteQuote
|
|
796
|
+
): Promise<ActionFunctionArgs> {
|
|
797
|
+
const actionFunctionArgs: ActionFunctionArgs = {
|
|
798
|
+
tokenList: {},
|
|
799
|
+
xykPoolList: {},
|
|
800
|
+
stableswapPoolList: {},
|
|
801
|
+
boolList: {},
|
|
802
|
+
};
|
|
803
|
+
|
|
804
|
+
const swapData = route.swapData;
|
|
805
|
+
if (!swapData || !swapData.parameters) {
|
|
806
|
+
throw new Error(
|
|
807
|
+
"Invalid route data - missing swapData or swapData.parameters"
|
|
808
|
+
);
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
const availableTokens = await this.getAvailableTokens();
|
|
812
|
+
const tokenPath = route.tokenPath;
|
|
813
|
+
const expandedTokenPath: string[] = [];
|
|
814
|
+
|
|
815
|
+
for (let i = 0; i < tokenPath.length - 1; i++) {
|
|
816
|
+
expandedTokenPath.push(tokenPath[i]);
|
|
817
|
+
if (i > 0 && i < tokenPath.length - 1) {
|
|
818
|
+
expandedTokenPath.push(tokenPath[i]);
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
expandedTokenPath.push(tokenPath[tokenPath.length - 1]);
|
|
822
|
+
|
|
823
|
+
const tokenList: Record<string, string> = {};
|
|
824
|
+
expandedTokenPath.forEach((tokenId, index) => {
|
|
825
|
+
let contractIdentifier: string;
|
|
826
|
+
if (tokenId === "token-stx") {
|
|
827
|
+
contractIdentifier =
|
|
828
|
+
"SM1793C4R5PZ4NS4VQ4WMP7SKKYVH8JZEWSZ9HCCR.token-stx-v-1-2";
|
|
829
|
+
} else {
|
|
830
|
+
const token = availableTokens.find((t) => t.tokenId === tokenId);
|
|
831
|
+
if (!token || !token.tokenContract) {
|
|
832
|
+
throw new Error(
|
|
833
|
+
`Could not find contract identifier for token ${tokenId}`
|
|
834
|
+
);
|
|
835
|
+
}
|
|
836
|
+
contractIdentifier = token.tokenContract;
|
|
837
|
+
}
|
|
838
|
+
const key = String.fromCharCode(97 + index); // 97 = 'a'
|
|
839
|
+
tokenList[key] = contractIdentifier;
|
|
840
|
+
});
|
|
841
|
+
|
|
842
|
+
actionFunctionArgs.tokenList = tokenList;
|
|
843
|
+
|
|
844
|
+
const transformPoolList = (pools: any): Record<string, string> => {
|
|
845
|
+
if (typeof pools === "string") {
|
|
846
|
+
return { a: pools };
|
|
847
|
+
}
|
|
848
|
+
if (Array.isArray(pools)) {
|
|
849
|
+
const poolObject: Record<string, string> = {};
|
|
850
|
+
const letters = "abcdefghijklmnopqrstuvwxyz";
|
|
851
|
+
pools.forEach((pool, index) => {
|
|
852
|
+
poolObject[letters[index]] = pool;
|
|
853
|
+
});
|
|
854
|
+
return poolObject;
|
|
855
|
+
}
|
|
856
|
+
if (typeof pools === "object" && pools !== null) {
|
|
857
|
+
return pools;
|
|
858
|
+
}
|
|
859
|
+
return {};
|
|
860
|
+
};
|
|
861
|
+
|
|
862
|
+
if (swapData.parameters["xyk-pools"]) {
|
|
863
|
+
actionFunctionArgs.xykPoolList = transformPoolList(
|
|
864
|
+
swapData.parameters["xyk-pools"]
|
|
865
|
+
);
|
|
866
|
+
} else if (swapData.parameters["pool-trait"]) {
|
|
867
|
+
actionFunctionArgs.xykPoolList = transformPoolList(
|
|
868
|
+
swapData.parameters["pool-trait"]
|
|
869
|
+
);
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
if (swapData.parameters["stableswap-pools"]) {
|
|
873
|
+
actionFunctionArgs.stableswapPoolList =
|
|
874
|
+
swapData.parameters["stableswap-pools"];
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
if ("swaps-reversed" in swapData.parameters) {
|
|
878
|
+
actionFunctionArgs.boolList = {
|
|
879
|
+
a: swapData.parameters["swaps-reversed"].toString(),
|
|
880
|
+
};
|
|
881
|
+
} else {
|
|
882
|
+
delete actionFunctionArgs.boolList;
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
const dexPath = route.dexPath;
|
|
886
|
+
const trait = this.mapDexPathToActionTrait(dexPath);
|
|
887
|
+
actionFunctionArgs.actionTrait = trait;
|
|
888
|
+
|
|
889
|
+
return actionFunctionArgs;
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
public async getKeeperAggregatorRouteData(
|
|
893
|
+
tokenX: string,
|
|
894
|
+
tokenY: string,
|
|
895
|
+
amountX: number
|
|
896
|
+
): Promise<ActionFunctionArgs> {
|
|
897
|
+
const quoteResult = await this.getKeeperQuoteForRoute(
|
|
898
|
+
tokenX,
|
|
899
|
+
tokenY,
|
|
900
|
+
amountX
|
|
901
|
+
);
|
|
902
|
+
|
|
903
|
+
if (
|
|
904
|
+
!quoteResult ||
|
|
905
|
+
!quoteResult.allRoutes ||
|
|
906
|
+
quoteResult.allRoutes.length === 0
|
|
907
|
+
) {
|
|
908
|
+
throw new Error("No routes found");
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
const { bestRoute } = quoteResult;
|
|
912
|
+
if (!bestRoute) {
|
|
913
|
+
throw new Error("No best route found for keeper-compatible DEX paths");
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
const actionFunctionArgs = this.transformRouteToActionArgs(bestRoute);
|
|
917
|
+
|
|
918
|
+
return actionFunctionArgs;
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
public async createGroupOrder(
|
|
922
|
+
params: CreateGroupOrderParams
|
|
923
|
+
): Promise<CreateGroupOrderResponse> {
|
|
924
|
+
try {
|
|
925
|
+
return await createGroupOrderAPI(params);
|
|
926
|
+
} catch (error) {
|
|
927
|
+
console.error("Error in BitflowSDK.createGroupOrder:", error);
|
|
928
|
+
throw error;
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
public async getGroupOrder(
|
|
933
|
+
groupId: string,
|
|
934
|
+
includeOrders?: boolean
|
|
935
|
+
): Promise<GetGroupOrderResponse> {
|
|
936
|
+
try {
|
|
937
|
+
return await getGroupOrderAPI(groupId, includeOrders);
|
|
938
|
+
} catch (error) {
|
|
939
|
+
console.error("Error in BitflowSDK.getGroupOrder:", error);
|
|
940
|
+
throw error;
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
public async cancelOrder(orderId: string): Promise<CancelOrderResponse> {
|
|
945
|
+
try {
|
|
946
|
+
return await cancelOrderAPI(orderId);
|
|
947
|
+
} catch (error) {
|
|
948
|
+
console.error("Error in BitflowSDK.cancelOrder:", error);
|
|
949
|
+
throw error;
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
public async cancelGroupOrder(
|
|
954
|
+
groupId: string
|
|
955
|
+
): Promise<CancelGroupOrderResponse> {
|
|
956
|
+
try {
|
|
957
|
+
return await cancelGroupOrderAPI(groupId);
|
|
958
|
+
} catch (error) {
|
|
959
|
+
console.error("Error in BitflowSDK.cancelGroupOrder:", error);
|
|
960
|
+
throw error;
|
|
961
|
+
}
|
|
962
|
+
}
|
|
385
963
|
}
|