@bitflowlabs/core-sdk 2.3.0 → 2.3.2-beta.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/config.d.ts +1 -1
- package/dist/src/config.js +12 -10
- package/dist/src/config.js.map +1 -1
- package/dist/src/helpers/callReadOnlyHelper.js +18 -17
- package/dist/src/helpers/callReadOnlyHelper.js.map +1 -1
- package/package.json +2 -3
- package/src/BitflowSDK.ts +0 -1244
- package/src/config.ts +0 -41
- package/src/helpers/callGetSwapParams.ts +0 -122
- package/src/helpers/callReadOnlyHelper.ts +0 -482
- package/src/helpers/callSwapHelper.ts +0 -67
- package/src/helpers/constructFunctionArgs.ts +0 -24
- package/src/helpers/convertValuesHelper.ts +0 -220
- package/src/helpers/fetchContractInterfaceHelper.ts +0 -27
- package/src/helpers/fetchDataHelper.ts +0 -88
- package/src/helpers/fetchPossibleSwap.ts +0 -39
- package/src/helpers/getContractInterfaceAndFunction.ts +0 -20
- package/src/helpers/getFunctionArgs.ts +0 -12
- package/src/helpers/getTokenDecimalsHelper.ts +0 -33
- package/src/helpers/getTokenNameHelper.ts +0 -26
- package/src/helpers/handleResultHelper.ts +0 -84
- package/src/helpers/newPostConditionsHelper.ts +0 -172
- package/src/helpers/postConditionsHelper.ts +0 -298
- package/src/index.ts +0 -3
- package/src/keeper/keeperAPI.ts +0 -365
- package/src/keeper/types.ts +0 -310
- package/src/test/testMethods.ts +0 -246
- package/src/types.ts +0 -168
package/src/config.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { BitflowSDKConfig } from "./types";
|
|
2
|
-
|
|
3
|
-
export const configs: BitflowSDKConfig = {
|
|
4
|
-
BITFLOW_API_HOST:
|
|
5
|
-
(process.env.NEXT_PUBLIC_BITFLOW_API_HOST ??
|
|
6
|
-
process.env.BITFLOW_API_HOST) ||
|
|
7
|
-
"",
|
|
8
|
-
BITFLOW_API_KEY:
|
|
9
|
-
(process.env.NEXT_PUBLIC_BITFLOW_API_KEY ?? process.env.BITFLOW_API_KEY) ||
|
|
10
|
-
"",
|
|
11
|
-
BITFLOW_PROVIDER_ADDRESS:
|
|
12
|
-
(process.env.NEXT_PUBLIC_BITFLOW_PROVIDER_ADDRESS ??
|
|
13
|
-
process.env.BITFLOW_PROVIDER_ADDRESS) ||
|
|
14
|
-
"",
|
|
15
|
-
READONLY_CALL_API_HOST:
|
|
16
|
-
(process.env.NEXT_PUBLIC_READONLY_CALL_API_HOST ??
|
|
17
|
-
process.env.READONLY_CALL_API_HOST) ||
|
|
18
|
-
"",
|
|
19
|
-
READONLY_CALL_API_KEY:
|
|
20
|
-
(process.env.NEXT_PUBLIC_READONLY_CALL_API_KEY ??
|
|
21
|
-
process.env.READONLY_CALL_API_KEY) ||
|
|
22
|
-
"",
|
|
23
|
-
KEEPER_API_KEY:
|
|
24
|
-
(process.env.NEXT_PUBLIC_KEEPER_API_KEY ?? process.env.KEEPER_API_KEY) ||
|
|
25
|
-
"",
|
|
26
|
-
KEEPER_API_HOST:
|
|
27
|
-
(process.env.NEXT_PUBLIC_KEEPER_API_HOST ?? process.env.KEEPER_API_HOST) ||
|
|
28
|
-
"",
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
export function validateConfig() {
|
|
32
|
-
const optionalEnvVars: (keyof BitflowSDKConfig)[] = ['BITFLOW_PROVIDER_ADDRESS'];
|
|
33
|
-
const requiredEnvVars = (Object.keys(configs) as (keyof BitflowSDKConfig)[])
|
|
34
|
-
.filter((key) => !optionalEnvVars.includes(key));
|
|
35
|
-
|
|
36
|
-
for (const envVar of requiredEnvVars) {
|
|
37
|
-
if (!configs[envVar]) {
|
|
38
|
-
throw new Error(`Missing required configuration: ${envVar}`);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import { createSwapPostConditions } from "./postConditionsHelper";
|
|
2
|
-
import {
|
|
3
|
-
SwapContext,
|
|
4
|
-
SwapDataParamsAndPostConditions,
|
|
5
|
-
SwapExecutionData,
|
|
6
|
-
} from "../types";
|
|
7
|
-
import { constructFunctionArgs } from "./constructFunctionArgs";
|
|
8
|
-
import { getContractInterfaceAndFunction } from "./getContractInterfaceAndFunction";
|
|
9
|
-
import { stringifyWithBigInt } from "./callReadOnlyHelper";
|
|
10
|
-
|
|
11
|
-
const applySlippage = (
|
|
12
|
-
value: string | number | bigint,
|
|
13
|
-
slippageTolerance: number
|
|
14
|
-
): bigint => {
|
|
15
|
-
const bigIntValue = BigInt(value);
|
|
16
|
-
const slippageFactor = BigInt(Math.floor((1 - slippageTolerance) * 10000));
|
|
17
|
-
return (bigIntValue * slippageFactor) / BigInt(10000);
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export const executeGetParams = async (
|
|
21
|
-
swapExecutionData: SwapExecutionData,
|
|
22
|
-
senderAddress: string,
|
|
23
|
-
slippageTolerance: number,
|
|
24
|
-
context: SwapContext
|
|
25
|
-
): Promise<SwapDataParamsAndPostConditions> => {
|
|
26
|
-
const network = context.network;
|
|
27
|
-
const { route, amount, tokenXDecimals, tokenYDecimals } = swapExecutionData;
|
|
28
|
-
const [contractAddress, contractName] = route.swapData.contract.split(".");
|
|
29
|
-
|
|
30
|
-
try {
|
|
31
|
-
const contractKey = `${contractAddress}.${contractName}`;
|
|
32
|
-
let contractInterface = context.contractInterfaces[contractKey];
|
|
33
|
-
let functionArgsDefinition =
|
|
34
|
-
context.functionArgs[contractKey]?.[route.swapData.function];
|
|
35
|
-
|
|
36
|
-
if (!contractInterface || !functionArgsDefinition) {
|
|
37
|
-
const result = await getContractInterfaceAndFunction(
|
|
38
|
-
contractAddress,
|
|
39
|
-
contractName,
|
|
40
|
-
route.swapData.function
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
if (!contractInterface) {
|
|
44
|
-
contractInterface = result.contractInterface;
|
|
45
|
-
context.contractInterfaces[contractKey] = contractInterface;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (!functionArgsDefinition) {
|
|
49
|
-
functionArgsDefinition = result.functionArgs;
|
|
50
|
-
if (!context.functionArgs[contractKey]) {
|
|
51
|
-
context.functionArgs[contractKey] = {};
|
|
52
|
-
}
|
|
53
|
-
context.functionArgs[contractKey][route.swapData.function] =
|
|
54
|
-
functionArgsDefinition;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const swapParameters = { ...route.swapData.parameters };
|
|
59
|
-
|
|
60
|
-
// Apply slippage to various parameters
|
|
61
|
-
const slippageParams = [
|
|
62
|
-
"min-received",
|
|
63
|
-
"min-dy",
|
|
64
|
-
"min-dx",
|
|
65
|
-
"min-dz",
|
|
66
|
-
"min-dw",
|
|
67
|
-
"amt-out",
|
|
68
|
-
"amt-out-min",
|
|
69
|
-
"min-x-amount",
|
|
70
|
-
"min-dv",
|
|
71
|
-
"min-y-amount",
|
|
72
|
-
];
|
|
73
|
-
|
|
74
|
-
slippageParams.forEach((param) => {
|
|
75
|
-
if (swapParameters[param]) {
|
|
76
|
-
swapParameters[param] = applySlippage(
|
|
77
|
-
swapParameters[param],
|
|
78
|
-
slippageTolerance
|
|
79
|
-
);
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
// Convert input amounts to BigInt
|
|
84
|
-
const inputParams = [
|
|
85
|
-
"amount",
|
|
86
|
-
"dx",
|
|
87
|
-
"amt-in",
|
|
88
|
-
"amt-in-max",
|
|
89
|
-
"y-amount",
|
|
90
|
-
"dy",
|
|
91
|
-
];
|
|
92
|
-
inputParams.forEach((param) => {
|
|
93
|
-
if (param in swapParameters) {
|
|
94
|
-
swapParameters[param] = BigInt(swapParameters[param]);
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
const functionArgs = constructFunctionArgs(
|
|
99
|
-
swapParameters,
|
|
100
|
-
functionArgsDefinition
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
const postConditions = await createSwapPostConditions(
|
|
104
|
-
swapParameters,
|
|
105
|
-
route.postConditions,
|
|
106
|
-
senderAddress,
|
|
107
|
-
tokenXDecimals,
|
|
108
|
-
tokenYDecimals
|
|
109
|
-
);
|
|
110
|
-
|
|
111
|
-
return {
|
|
112
|
-
functionArgs,
|
|
113
|
-
postConditions,
|
|
114
|
-
contractAddress,
|
|
115
|
-
contractName,
|
|
116
|
-
functionName: route.swapData.function,
|
|
117
|
-
};
|
|
118
|
-
} catch (error) {
|
|
119
|
-
console.error("Error getting swap parameters:", error);
|
|
120
|
-
throw error;
|
|
121
|
-
}
|
|
122
|
-
};
|
|
@@ -1,482 +0,0 @@
|
|
|
1
|
-
import { fetchCallReadOnlyFunction } from '@stacks/transactions';
|
|
2
|
-
import { SwapContext } from '../types';
|
|
3
|
-
import { getTokenDecimals } from './getTokenDecimalsHelper';
|
|
4
|
-
import { constructFunctionArgs } from './constructFunctionArgs';
|
|
5
|
-
import { configs } from '../config';
|
|
6
|
-
import { getContractInterfaceAndFunction } from './getContractInterfaceAndFunction';
|
|
7
|
-
import { handleResult } from './handleResultHelper';
|
|
8
|
-
|
|
9
|
-
export const stringifyWithBigInt = (obj: any): string => {
|
|
10
|
-
return JSON.stringify(obj, (_, v) =>
|
|
11
|
-
typeof v === 'bigint' ? v.toString() : v
|
|
12
|
-
);
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
const getReadonlyHeaders = () => ({
|
|
16
|
-
Accept: "application/json",
|
|
17
|
-
"Content-Type": "application/json",
|
|
18
|
-
...(configs.READONLY_CALL_API_KEY && { "x-api-key": configs.READONLY_CALL_API_KEY }),
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
export const callReadOnlyFunctionHelper = async (
|
|
22
|
-
contractDeployer: string,
|
|
23
|
-
contractName: string,
|
|
24
|
-
functionName: string,
|
|
25
|
-
parameters: any,
|
|
26
|
-
senderAddress: string,
|
|
27
|
-
tokenXId: string,
|
|
28
|
-
tokenYId: string,
|
|
29
|
-
swapData: any,
|
|
30
|
-
context: SwapContext
|
|
31
|
-
): Promise<{
|
|
32
|
-
convertedResult: number;
|
|
33
|
-
rawResult: number;
|
|
34
|
-
tokenXDecimals: number;
|
|
35
|
-
tokenYDecimals: number;
|
|
36
|
-
}> => {
|
|
37
|
-
const network = 'mainnet';
|
|
38
|
-
|
|
39
|
-
const client = {
|
|
40
|
-
baseUrl: configs.READONLY_CALL_API_HOST,
|
|
41
|
-
headers: getReadonlyHeaders(),
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
try {
|
|
45
|
-
const contractKey = `${contractDeployer}.${contractName}`;
|
|
46
|
-
let contractInterface = context.contractInterfaces[contractKey];
|
|
47
|
-
let functionArgsDefinition =
|
|
48
|
-
context.functionArgs[contractKey]?.[functionName];
|
|
49
|
-
|
|
50
|
-
if (!contractInterface || !functionArgsDefinition) {
|
|
51
|
-
const result = await getContractInterfaceAndFunction(
|
|
52
|
-
contractDeployer,
|
|
53
|
-
contractName,
|
|
54
|
-
functionName
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
if (!contractInterface) {
|
|
58
|
-
contractInterface = result.contractInterface;
|
|
59
|
-
context.contractInterfaces[contractKey] = contractInterface;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (!functionArgsDefinition) {
|
|
63
|
-
functionArgsDefinition = result.functionArgs;
|
|
64
|
-
if (!context.functionArgs[contractKey]) {
|
|
65
|
-
context.functionArgs[contractKey] = {};
|
|
66
|
-
}
|
|
67
|
-
context.functionArgs[contractKey][functionName] =
|
|
68
|
-
functionArgsDefinition;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const tokenXDecimals = getTokenDecimals(tokenXId, context);
|
|
73
|
-
let tokenXMatchingDecimal:
|
|
74
|
-
| { tokenContract: string; tokenDecimals: number }
|
|
75
|
-
| undefined;
|
|
76
|
-
|
|
77
|
-
// Attempt to find matching token decimals from parameters
|
|
78
|
-
for (const key in parameters) {
|
|
79
|
-
if (typeof parameters[key] === 'object') {
|
|
80
|
-
for (const subKey in parameters[key]) {
|
|
81
|
-
const contractValue = parameters[key][subKey];
|
|
82
|
-
tokenXMatchingDecimal = tokenXDecimals.find(
|
|
83
|
-
(d) => d.tokenContract === contractValue
|
|
84
|
-
);
|
|
85
|
-
if (tokenXMatchingDecimal) break;
|
|
86
|
-
}
|
|
87
|
-
} else if (typeof parameters[key] === 'string') {
|
|
88
|
-
tokenXMatchingDecimal = tokenXDecimals.find(
|
|
89
|
-
(d) => d.tokenContract === parameters[key]
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
if (tokenXMatchingDecimal) break;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// If not found yet, also check swapData parameters
|
|
96
|
-
if (!tokenXMatchingDecimal && swapData && swapData.parameters) {
|
|
97
|
-
const swapParameters = swapData.parameters;
|
|
98
|
-
for (const key in swapParameters) {
|
|
99
|
-
if (typeof swapParameters[key] === 'object') {
|
|
100
|
-
for (const subKey in swapParameters[key]) {
|
|
101
|
-
const contractValue = swapParameters[key][subKey];
|
|
102
|
-
tokenXMatchingDecimal = tokenXDecimals.find(
|
|
103
|
-
(d) => d.tokenContract === contractValue
|
|
104
|
-
);
|
|
105
|
-
if (tokenXMatchingDecimal) break;
|
|
106
|
-
}
|
|
107
|
-
} else if (typeof swapParameters[key] === 'string') {
|
|
108
|
-
tokenXMatchingDecimal = tokenXDecimals.find(
|
|
109
|
-
(d) => d.tokenContract === swapParameters[key]
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
|
-
if (tokenXMatchingDecimal) break;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Scale parameters if we find a matching decimal for tokenX
|
|
117
|
-
if (tokenXMatchingDecimal) {
|
|
118
|
-
const scaleAmount = (amount: number | string) => {
|
|
119
|
-
const scaledAmount =
|
|
120
|
-
parseFloat(amount.toString()) *
|
|
121
|
-
10 ** tokenXMatchingDecimal!.tokenDecimals;
|
|
122
|
-
return BigInt(Math.floor(scaledAmount));
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
if (parameters.dx !== undefined && parameters.dx !== null) {
|
|
126
|
-
parameters.dx = scaleAmount(parameters.dx);
|
|
127
|
-
} else if (
|
|
128
|
-
parameters.amount !== undefined &&
|
|
129
|
-
parameters.amount !== null
|
|
130
|
-
) {
|
|
131
|
-
parameters.amount = scaleAmount(parameters.amount);
|
|
132
|
-
} else if (
|
|
133
|
-
parameters['amt-in'] !== undefined &&
|
|
134
|
-
parameters['amt-in'] !== null
|
|
135
|
-
) {
|
|
136
|
-
parameters['amt-in'] = scaleAmount(parameters['amt-in']);
|
|
137
|
-
} else if (
|
|
138
|
-
parameters['amt-in-max'] !== undefined &&
|
|
139
|
-
parameters['amt-in-max'] !== null
|
|
140
|
-
) {
|
|
141
|
-
parameters['amt-in-max'] = scaleAmount(parameters['amt-in-max']);
|
|
142
|
-
} else if (
|
|
143
|
-
parameters['y-amount'] !== undefined &&
|
|
144
|
-
parameters['y-amount'] !== null
|
|
145
|
-
) {
|
|
146
|
-
parameters['y-amount'] = scaleAmount(parameters['y-amount']);
|
|
147
|
-
parameters['x-amount'] = scaleAmount(parameters['x-amount']);
|
|
148
|
-
} else if (
|
|
149
|
-
parameters['x-amount'] !== undefined &&
|
|
150
|
-
parameters['x-amount'] !== null
|
|
151
|
-
) {
|
|
152
|
-
parameters['x-amount'] = scaleAmount(parameters['x-amount']);
|
|
153
|
-
} else if (parameters.dy !== undefined && parameters.dy !== null) {
|
|
154
|
-
parameters.dy = scaleAmount(parameters.dy);
|
|
155
|
-
}
|
|
156
|
-
} else {
|
|
157
|
-
console.warn(`No matching decimal found for tokenX: ${tokenXId}`);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
const functionArgs = constructFunctionArgs(
|
|
161
|
-
parameters,
|
|
162
|
-
functionArgsDefinition
|
|
163
|
-
);
|
|
164
|
-
|
|
165
|
-
const result = await fetchCallReadOnlyFunction({
|
|
166
|
-
contractAddress: contractDeployer,
|
|
167
|
-
contractName,
|
|
168
|
-
functionName,
|
|
169
|
-
functionArgs,
|
|
170
|
-
network,
|
|
171
|
-
client,
|
|
172
|
-
senderAddress: senderAddress,
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
const { rawResult, convertedResult } = handleResult(result);
|
|
176
|
-
|
|
177
|
-
try {
|
|
178
|
-
const tokenYDecimals = getTokenDecimals(tokenYId, context);
|
|
179
|
-
|
|
180
|
-
let tokenYMatchingDecimal:
|
|
181
|
-
| { tokenContract: string; tokenDecimals: number }
|
|
182
|
-
| undefined;
|
|
183
|
-
|
|
184
|
-
for (const key in parameters) {
|
|
185
|
-
if (typeof parameters[key] === 'object') {
|
|
186
|
-
for (const subKey in parameters[key]) {
|
|
187
|
-
const contractValue = parameters[key][subKey];
|
|
188
|
-
tokenYMatchingDecimal = tokenYDecimals.find(
|
|
189
|
-
(d) => d.tokenContract === contractValue
|
|
190
|
-
);
|
|
191
|
-
if (tokenYMatchingDecimal) break;
|
|
192
|
-
}
|
|
193
|
-
} else if (typeof parameters[key] === 'string') {
|
|
194
|
-
tokenYMatchingDecimal = tokenYDecimals.find(
|
|
195
|
-
(d) => d.tokenContract === parameters[key]
|
|
196
|
-
);
|
|
197
|
-
}
|
|
198
|
-
if (tokenYMatchingDecimal) break;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
if (!tokenYMatchingDecimal && swapData && swapData.parameters) {
|
|
202
|
-
const swapParameters = swapData.parameters;
|
|
203
|
-
for (const key in swapParameters) {
|
|
204
|
-
if (typeof swapParameters[key] === 'object') {
|
|
205
|
-
for (const subKey in swapParameters[key]) {
|
|
206
|
-
const contractValue = swapParameters[key][subKey];
|
|
207
|
-
tokenYMatchingDecimal = tokenYDecimals.find(
|
|
208
|
-
(d) => d.tokenContract === contractValue
|
|
209
|
-
);
|
|
210
|
-
if (tokenYMatchingDecimal) break;
|
|
211
|
-
}
|
|
212
|
-
} else if (typeof swapParameters[key] === 'string') {
|
|
213
|
-
tokenYMatchingDecimal = tokenYDecimals.find(
|
|
214
|
-
(d) => d.tokenContract === swapParameters[key]
|
|
215
|
-
);
|
|
216
|
-
}
|
|
217
|
-
if (tokenYMatchingDecimal) break;
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
if (tokenYMatchingDecimal && typeof convertedResult === 'number') {
|
|
222
|
-
const adjustedResult =
|
|
223
|
-
convertedResult / 10 ** tokenYMatchingDecimal.tokenDecimals;
|
|
224
|
-
return {
|
|
225
|
-
convertedResult: adjustedResult,
|
|
226
|
-
rawResult,
|
|
227
|
-
tokenXDecimals: tokenXMatchingDecimal?.tokenDecimals || 0,
|
|
228
|
-
tokenYDecimals: tokenYMatchingDecimal.tokenDecimals,
|
|
229
|
-
};
|
|
230
|
-
} else {
|
|
231
|
-
console.warn(
|
|
232
|
-
`No matching decimal found for tokenY: ${tokenYId} or result is not a number`
|
|
233
|
-
);
|
|
234
|
-
return {
|
|
235
|
-
convertedResult,
|
|
236
|
-
rawResult,
|
|
237
|
-
tokenXDecimals: tokenXMatchingDecimal?.tokenDecimals || 0,
|
|
238
|
-
tokenYDecimals: 0,
|
|
239
|
-
};
|
|
240
|
-
}
|
|
241
|
-
} catch (error) {
|
|
242
|
-
console.warn(`Couldn't apply decimal conversion: ${error}`);
|
|
243
|
-
console.warn('Using raw result without decimal conversion');
|
|
244
|
-
return {
|
|
245
|
-
convertedResult,
|
|
246
|
-
rawResult,
|
|
247
|
-
tokenXDecimals: tokenXMatchingDecimal?.tokenDecimals || 0,
|
|
248
|
-
tokenYDecimals: 0,
|
|
249
|
-
};
|
|
250
|
-
}
|
|
251
|
-
} catch (error) {
|
|
252
|
-
console.error(`Error calling read-only function ${functionName}:`, error);
|
|
253
|
-
throw error;
|
|
254
|
-
}
|
|
255
|
-
};
|
|
256
|
-
|
|
257
|
-
export const callReadOnlyFunctionHelperWithoutScaling = async (
|
|
258
|
-
contractDeployer: string,
|
|
259
|
-
contractName: string,
|
|
260
|
-
functionName: string,
|
|
261
|
-
parameters: any,
|
|
262
|
-
senderAddress: string,
|
|
263
|
-
tokenXId: string,
|
|
264
|
-
tokenYId: string,
|
|
265
|
-
swapData: any,
|
|
266
|
-
context: SwapContext
|
|
267
|
-
): Promise<{
|
|
268
|
-
convertedResult: number;
|
|
269
|
-
rawResult: number;
|
|
270
|
-
tokenXDecimals: number;
|
|
271
|
-
tokenYDecimals: number;
|
|
272
|
-
}> => {
|
|
273
|
-
const network = 'mainnet';
|
|
274
|
-
|
|
275
|
-
const client = {
|
|
276
|
-
baseUrl: configs.READONLY_CALL_API_HOST,
|
|
277
|
-
headers: getReadonlyHeaders(),
|
|
278
|
-
};
|
|
279
|
-
|
|
280
|
-
try {
|
|
281
|
-
const contractKey = `${contractDeployer}.${contractName}`;
|
|
282
|
-
let contractInterface = context.contractInterfaces[contractKey];
|
|
283
|
-
let functionArgsDefinition =
|
|
284
|
-
context.functionArgs[contractKey]?.[functionName];
|
|
285
|
-
|
|
286
|
-
if (!contractInterface || !functionArgsDefinition) {
|
|
287
|
-
const result = await getContractInterfaceAndFunction(
|
|
288
|
-
contractDeployer,
|
|
289
|
-
contractName,
|
|
290
|
-
functionName
|
|
291
|
-
);
|
|
292
|
-
|
|
293
|
-
if (!contractInterface) {
|
|
294
|
-
contractInterface = result.contractInterface;
|
|
295
|
-
context.contractInterfaces[contractKey] = contractInterface;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
if (!functionArgsDefinition) {
|
|
299
|
-
functionArgsDefinition = result.functionArgs;
|
|
300
|
-
if (!context.functionArgs[contractKey]) {
|
|
301
|
-
context.functionArgs[contractKey] = {};
|
|
302
|
-
}
|
|
303
|
-
context.functionArgs[contractKey][functionName] =
|
|
304
|
-
functionArgsDefinition;
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
const tokenXDecimals = getTokenDecimals(tokenXId, context);
|
|
309
|
-
let tokenXMatchingDecimal:
|
|
310
|
-
| { tokenContract: string; tokenDecimals: number }
|
|
311
|
-
| undefined;
|
|
312
|
-
|
|
313
|
-
// Attempt to find matching token decimals from parameters
|
|
314
|
-
for (const key in parameters) {
|
|
315
|
-
if (typeof parameters[key] === 'object') {
|
|
316
|
-
for (const subKey in parameters[key]) {
|
|
317
|
-
const contractValue = parameters[key][subKey];
|
|
318
|
-
tokenXMatchingDecimal = tokenXDecimals.find(
|
|
319
|
-
(d) => d.tokenContract === contractValue
|
|
320
|
-
);
|
|
321
|
-
if (tokenXMatchingDecimal) break;
|
|
322
|
-
}
|
|
323
|
-
} else if (typeof parameters[key] === 'string') {
|
|
324
|
-
tokenXMatchingDecimal = tokenXDecimals.find(
|
|
325
|
-
(d) => d.tokenContract === parameters[key]
|
|
326
|
-
);
|
|
327
|
-
}
|
|
328
|
-
if (tokenXMatchingDecimal) break;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
// If not found yet, also check swapData parameters
|
|
332
|
-
if (!tokenXMatchingDecimal && swapData && swapData.parameters) {
|
|
333
|
-
const swapParameters = swapData.parameters;
|
|
334
|
-
for (const key in swapParameters) {
|
|
335
|
-
if (typeof swapParameters[key] === 'object') {
|
|
336
|
-
for (const subKey in swapParameters[key]) {
|
|
337
|
-
const contractValue = swapParameters[key][subKey];
|
|
338
|
-
tokenXMatchingDecimal = tokenXDecimals.find(
|
|
339
|
-
(d) => d.tokenContract === contractValue
|
|
340
|
-
);
|
|
341
|
-
if (tokenXMatchingDecimal) break;
|
|
342
|
-
}
|
|
343
|
-
} else if (typeof swapParameters[key] === 'string') {
|
|
344
|
-
tokenXMatchingDecimal = tokenXDecimals.find(
|
|
345
|
-
(d) => d.tokenContract === swapParameters[key]
|
|
346
|
-
);
|
|
347
|
-
}
|
|
348
|
-
if (tokenXMatchingDecimal) break;
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
// Skip scaling and use raw input values
|
|
353
|
-
// Just convert any numerical values to BigInt to maintain type compatibility
|
|
354
|
-
if (parameters.dx !== undefined && parameters.dx !== null) {
|
|
355
|
-
parameters.dx = BigInt(Math.floor(parameters.dx));
|
|
356
|
-
} else if (parameters.amount !== undefined && parameters.amount !== null) {
|
|
357
|
-
parameters.amount = BigInt(Math.floor(parameters.amount));
|
|
358
|
-
} else if (
|
|
359
|
-
parameters['amt-in'] !== undefined &&
|
|
360
|
-
parameters['amt-in'] !== null
|
|
361
|
-
) {
|
|
362
|
-
parameters['amt-in'] = BigInt(Math.floor(parameters['amt-in']));
|
|
363
|
-
} else if (
|
|
364
|
-
parameters['amt-in-max'] !== undefined &&
|
|
365
|
-
parameters['amt-in-max'] !== null
|
|
366
|
-
) {
|
|
367
|
-
parameters['amt-in-max'] = BigInt(Math.floor(parameters['amt-in-max']));
|
|
368
|
-
} else if (
|
|
369
|
-
parameters['y-amount'] !== undefined &&
|
|
370
|
-
parameters['y-amount'] !== null
|
|
371
|
-
) {
|
|
372
|
-
parameters['y-amount'] = BigInt(Math.floor(parameters['y-amount']));
|
|
373
|
-
if (
|
|
374
|
-
parameters['x-amount'] !== undefined &&
|
|
375
|
-
parameters['x-amount'] !== null
|
|
376
|
-
) {
|
|
377
|
-
parameters['x-amount'] = BigInt(Math.floor(parameters['x-amount']));
|
|
378
|
-
}
|
|
379
|
-
} else if (
|
|
380
|
-
parameters['x-amount'] !== undefined &&
|
|
381
|
-
parameters['x-amount'] !== null
|
|
382
|
-
) {
|
|
383
|
-
parameters['x-amount'] = BigInt(Math.floor(parameters['x-amount']));
|
|
384
|
-
} else if (parameters.dy !== undefined && parameters.dy !== null) {
|
|
385
|
-
parameters.dy = BigInt(Math.floor(parameters.dy));
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
const functionArgs = constructFunctionArgs(
|
|
389
|
-
parameters,
|
|
390
|
-
functionArgsDefinition
|
|
391
|
-
);
|
|
392
|
-
|
|
393
|
-
const result = await fetchCallReadOnlyFunction({
|
|
394
|
-
contractAddress: contractDeployer,
|
|
395
|
-
contractName,
|
|
396
|
-
functionName,
|
|
397
|
-
functionArgs,
|
|
398
|
-
network,
|
|
399
|
-
client,
|
|
400
|
-
senderAddress: senderAddress,
|
|
401
|
-
});
|
|
402
|
-
|
|
403
|
-
const { rawResult, convertedResult } = handleResult(result);
|
|
404
|
-
|
|
405
|
-
try {
|
|
406
|
-
const tokenYDecimals = getTokenDecimals(tokenYId, context);
|
|
407
|
-
|
|
408
|
-
let tokenYMatchingDecimal:
|
|
409
|
-
| { tokenContract: string; tokenDecimals: number }
|
|
410
|
-
| undefined;
|
|
411
|
-
|
|
412
|
-
for (const key in parameters) {
|
|
413
|
-
if (typeof parameters[key] === 'object') {
|
|
414
|
-
for (const subKey in parameters[key]) {
|
|
415
|
-
const contractValue = parameters[key][subKey];
|
|
416
|
-
tokenYMatchingDecimal = tokenYDecimals.find(
|
|
417
|
-
(d) => d.tokenContract === contractValue
|
|
418
|
-
);
|
|
419
|
-
if (tokenYMatchingDecimal) break;
|
|
420
|
-
}
|
|
421
|
-
} else if (typeof parameters[key] === 'string') {
|
|
422
|
-
tokenYMatchingDecimal = tokenYDecimals.find(
|
|
423
|
-
(d) => d.tokenContract === parameters[key]
|
|
424
|
-
);
|
|
425
|
-
}
|
|
426
|
-
if (tokenYMatchingDecimal) break;
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
if (!tokenYMatchingDecimal && swapData && swapData.parameters) {
|
|
430
|
-
const swapParameters = swapData.parameters;
|
|
431
|
-
for (const key in swapParameters) {
|
|
432
|
-
if (typeof swapParameters[key] === 'object') {
|
|
433
|
-
for (const subKey in swapParameters[key]) {
|
|
434
|
-
const contractValue = swapParameters[key][subKey];
|
|
435
|
-
tokenYMatchingDecimal = tokenYDecimals.find(
|
|
436
|
-
(d) => d.tokenContract === contractValue
|
|
437
|
-
);
|
|
438
|
-
if (tokenYMatchingDecimal) break;
|
|
439
|
-
}
|
|
440
|
-
} else if (typeof swapParameters[key] === 'string') {
|
|
441
|
-
tokenYMatchingDecimal = tokenYDecimals.find(
|
|
442
|
-
(d) => d.tokenContract === swapParameters[key]
|
|
443
|
-
);
|
|
444
|
-
}
|
|
445
|
-
if (tokenYMatchingDecimal) break;
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
if (tokenYMatchingDecimal && typeof convertedResult === 'number') {
|
|
450
|
-
const adjustedResult =
|
|
451
|
-
convertedResult / 10 ** tokenYMatchingDecimal.tokenDecimals;
|
|
452
|
-
return {
|
|
453
|
-
convertedResult: adjustedResult,
|
|
454
|
-
rawResult,
|
|
455
|
-
tokenXDecimals: tokenXMatchingDecimal?.tokenDecimals || 0,
|
|
456
|
-
tokenYDecimals: tokenYMatchingDecimal.tokenDecimals,
|
|
457
|
-
};
|
|
458
|
-
} else {
|
|
459
|
-
console.warn(
|
|
460
|
-
`No matching decimal found for tokenY: ${tokenYId} or result is not a number`
|
|
461
|
-
);
|
|
462
|
-
return {
|
|
463
|
-
convertedResult,
|
|
464
|
-
rawResult,
|
|
465
|
-
tokenXDecimals: tokenXMatchingDecimal?.tokenDecimals || 0,
|
|
466
|
-
tokenYDecimals: 0,
|
|
467
|
-
};
|
|
468
|
-
}
|
|
469
|
-
} catch (error) {
|
|
470
|
-
console.warn(`Couldn't apply decimal conversion: ${error}`);
|
|
471
|
-
return {
|
|
472
|
-
convertedResult,
|
|
473
|
-
rawResult,
|
|
474
|
-
tokenXDecimals: tokenXMatchingDecimal?.tokenDecimals || 0,
|
|
475
|
-
tokenYDecimals: 0,
|
|
476
|
-
};
|
|
477
|
-
}
|
|
478
|
-
} catch (error) {
|
|
479
|
-
console.error(`Error calling read-only function ${functionName}:`, error);
|
|
480
|
-
throw error;
|
|
481
|
-
}
|
|
482
|
-
};
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { AnchorMode, PostConditionMode } from "@stacks/transactions";
|
|
2
|
-
import type { StacksProvider } from "@stacks/connect";
|
|
3
|
-
import { SwapContext } from "../types";
|
|
4
|
-
|
|
5
|
-
const loadStacksConnect = async () => {
|
|
6
|
-
if (typeof window === "undefined") {
|
|
7
|
-
throw new Error(
|
|
8
|
-
"Stacks Connect functionality is only available in browser environments"
|
|
9
|
-
);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
try {
|
|
13
|
-
const { openContractCall } = await import("@stacks/connect");
|
|
14
|
-
return { openContractCall };
|
|
15
|
-
} catch (error) {
|
|
16
|
-
console.error("Error loading Stacks Connect:", error);
|
|
17
|
-
throw new Error("Failed to load Stacks Connect dependencies");
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export const executeSwapHelper = async (
|
|
22
|
-
swapParams: {
|
|
23
|
-
functionArgs: any[];
|
|
24
|
-
postConditions: any[];
|
|
25
|
-
contractAddress: string;
|
|
26
|
-
contractName: string;
|
|
27
|
-
functionName: string;
|
|
28
|
-
},
|
|
29
|
-
senderAddress: string,
|
|
30
|
-
context: SwapContext,
|
|
31
|
-
stacksProvider: StacksProvider,
|
|
32
|
-
onFinish?: (data: any) => void,
|
|
33
|
-
onCancel?: () => void
|
|
34
|
-
): Promise<void> => {
|
|
35
|
-
const network = context.network;
|
|
36
|
-
|
|
37
|
-
try {
|
|
38
|
-
const { openContractCall } = await loadStacksConnect();
|
|
39
|
-
|
|
40
|
-
const txOptions = {
|
|
41
|
-
contractAddress: swapParams.contractAddress,
|
|
42
|
-
contractName: swapParams.contractName,
|
|
43
|
-
functionName: swapParams.functionName,
|
|
44
|
-
functionArgs: swapParams.functionArgs,
|
|
45
|
-
senderAddress,
|
|
46
|
-
network,
|
|
47
|
-
anchorMode: AnchorMode.Any,
|
|
48
|
-
postConditionMode: PostConditionMode.Deny,
|
|
49
|
-
postConditions: swapParams.postConditions,
|
|
50
|
-
onFinish:
|
|
51
|
-
onFinish ||
|
|
52
|
-
((data: any) => {
|
|
53
|
-
console.log("Transaction submitted:", data);
|
|
54
|
-
}),
|
|
55
|
-
onCancel:
|
|
56
|
-
onCancel ||
|
|
57
|
-
(() => {
|
|
58
|
-
console.log("Transaction canceled");
|
|
59
|
-
}),
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
await openContractCall({ ...txOptions }, stacksProvider);
|
|
63
|
-
} catch (error) {
|
|
64
|
-
console.error("Error executing swap:", error);
|
|
65
|
-
throw error;
|
|
66
|
-
}
|
|
67
|
-
};
|