@bitflowlabs/core-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.
Files changed (78) hide show
  1. package/README.md +205 -0
  2. package/dist/src/BitflowSDK.d.ts +14 -0
  3. package/dist/src/BitflowSDK.js +275 -0
  4. package/dist/src/BitflowSDK.js.map +1 -0
  5. package/dist/src/config.d.ts +3 -0
  6. package/dist/src/config.js +20 -0
  7. package/dist/src/config.js.map +1 -0
  8. package/dist/src/helpers/callGetSwapParams.d.ts +2 -0
  9. package/dist/src/helpers/callGetSwapParams.js +85 -0
  10. package/dist/src/helpers/callGetSwapParams.js.map +1 -0
  11. package/dist/src/helpers/callReadOnlyHelper.d.ts +8 -0
  12. package/dist/src/helpers/callReadOnlyHelper.js +191 -0
  13. package/dist/src/helpers/callReadOnlyHelper.js.map +1 -0
  14. package/dist/src/helpers/callSwapHelper.d.ts +9 -0
  15. package/dist/src/helpers/callSwapHelper.js +41 -0
  16. package/dist/src/helpers/callSwapHelper.js.map +1 -0
  17. package/dist/src/helpers/constructFunctionArgs.d.ts +1 -0
  18. package/dist/src/helpers/constructFunctionArgs.js +22 -0
  19. package/dist/src/helpers/constructFunctionArgs.js.map +1 -0
  20. package/dist/src/helpers/convertValuesHelper.d.ts +2 -0
  21. package/dist/src/helpers/convertValuesHelper.js +181 -0
  22. package/dist/src/helpers/convertValuesHelper.js.map +1 -0
  23. package/dist/src/helpers/fetchContractInterfaceHelper.d.ts +1 -0
  24. package/dist/src/helpers/fetchContractInterfaceHelper.js +20 -0
  25. package/dist/src/helpers/fetchContractInterfaceHelper.js.map +1 -0
  26. package/dist/src/helpers/fetchDataHelper.d.ts +2 -0
  27. package/dist/src/helpers/fetchDataHelper.js +44 -0
  28. package/dist/src/helpers/fetchDataHelper.js.map +1 -0
  29. package/dist/src/helpers/fetchPossibleSwap.d.ts +2 -0
  30. package/dist/src/helpers/fetchPossibleSwap.js +20 -0
  31. package/dist/src/helpers/fetchPossibleSwap.js.map +1 -0
  32. package/dist/src/helpers/getContractInterfaceAndFunction.d.ts +4 -0
  33. package/dist/src/helpers/getContractInterfaceAndFunction.js +15 -0
  34. package/dist/src/helpers/getContractInterfaceAndFunction.js.map +1 -0
  35. package/dist/src/helpers/getFunctionArgs.d.ts +1 -0
  36. package/dist/src/helpers/getFunctionArgs.js +12 -0
  37. package/dist/src/helpers/getFunctionArgs.js.map +1 -0
  38. package/dist/src/helpers/getTokenDecimalsHelper.d.ts +5 -0
  39. package/dist/src/helpers/getTokenDecimalsHelper.js +28 -0
  40. package/dist/src/helpers/getTokenDecimalsHelper.js.map +1 -0
  41. package/dist/src/helpers/getTokenNameHelper.d.ts +2 -0
  42. package/dist/src/helpers/getTokenNameHelper.js +22 -0
  43. package/dist/src/helpers/getTokenNameHelper.js.map +1 -0
  44. package/dist/src/helpers/handleResultHelper.d.ts +4 -0
  45. package/dist/src/helpers/handleResultHelper.js +80 -0
  46. package/dist/src/helpers/handleResultHelper.js.map +1 -0
  47. package/dist/src/helpers/postConditionsHelper.d.ts +2 -0
  48. package/dist/src/helpers/postConditionsHelper.js +135 -0
  49. package/dist/src/helpers/postConditionsHelper.js.map +1 -0
  50. package/dist/src/index.d.ts +2 -0
  51. package/dist/src/index.js +8 -0
  52. package/dist/src/index.js.map +1 -0
  53. package/dist/src/test/testMethods.d.ts +1 -0
  54. package/dist/src/test/testMethods.js +178 -0
  55. package/dist/src/test/testMethods.js.map +1 -0
  56. package/dist/src/types.d.ts +126 -0
  57. package/dist/src/types.js +3 -0
  58. package/dist/src/types.js.map +1 -0
  59. package/package.json +57 -0
  60. package/src/BitflowSDK.ts +385 -0
  61. package/src/config.ts +22 -0
  62. package/src/helpers/callGetSwapParams.ts +122 -0
  63. package/src/helpers/callReadOnlyHelper.ts +243 -0
  64. package/src/helpers/callSwapHelper.ts +53 -0
  65. package/src/helpers/constructFunctionArgs.ts +24 -0
  66. package/src/helpers/convertValuesHelper.ts +214 -0
  67. package/src/helpers/fetchContractInterfaceHelper.ts +19 -0
  68. package/src/helpers/fetchDataHelper.ts +41 -0
  69. package/src/helpers/fetchPossibleSwap.ts +18 -0
  70. package/src/helpers/getContractInterfaceAndFunction.ts +20 -0
  71. package/src/helpers/getFunctionArgs.ts +12 -0
  72. package/src/helpers/getTokenDecimalsHelper.ts +33 -0
  73. package/src/helpers/getTokenNameHelper.ts +26 -0
  74. package/src/helpers/handleResultHelper.ts +85 -0
  75. package/src/helpers/postConditionsHelper.ts +246 -0
  76. package/src/index.ts +2 -0
  77. package/src/test/testMethods.ts +227 -0
  78. package/src/types.ts +137 -0
@@ -0,0 +1,122 @@
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
+ };
@@ -0,0 +1,243 @@
1
+ import { callReadOnlyFunction } from "@stacks/transactions";
2
+ import { SwapContext } from "../types";
3
+ import { getTokenDecimals } from "./getTokenDecimalsHelper";
4
+ import { constructFunctionArgs } from "./constructFunctionArgs";
5
+ import { StacksMainnet } from "@stacks/network";
6
+ import { configs } from "../config";
7
+ import { getContractInterfaceAndFunction } from "./getContractInterfaceAndFunction";
8
+ import { handleResult } from "./handleResultHelper";
9
+
10
+ export const stringifyWithBigInt = (obj: any): string => {
11
+ return JSON.stringify(obj, (_, v) =>
12
+ typeof v === "bigint" ? v.toString() : v
13
+ );
14
+ };
15
+
16
+ export const callReadOnlyFunctionHelper = async (
17
+ contractDeployer: string,
18
+ contractName: string,
19
+ functionName: string,
20
+ parameters: any,
21
+ senderAddress: string,
22
+ tokenXId: string,
23
+ tokenYId: string,
24
+ swapData: any,
25
+ context: SwapContext
26
+ ): Promise<{
27
+ convertedResult: number;
28
+ rawResult: number;
29
+ tokenXDecimals: number;
30
+ tokenYDecimals: number;
31
+ }> => {
32
+ const network = new StacksMainnet({ url: configs.READONLY_CALL_API_HOST });
33
+
34
+ try {
35
+ const contractKey = `${contractDeployer}.${contractName}`;
36
+ let contractInterface = context.contractInterfaces[contractKey];
37
+ let functionArgsDefinition =
38
+ context.functionArgs[contractKey]?.[functionName];
39
+
40
+ if (!contractInterface || !functionArgsDefinition) {
41
+ const result = await getContractInterfaceAndFunction(
42
+ contractDeployer,
43
+ contractName,
44
+ functionName
45
+ );
46
+
47
+ if (!contractInterface) {
48
+ contractInterface = result.contractInterface;
49
+ context.contractInterfaces[contractKey] = contractInterface;
50
+ }
51
+
52
+ if (!functionArgsDefinition) {
53
+ functionArgsDefinition = result.functionArgs;
54
+ if (!context.functionArgs[contractKey]) {
55
+ context.functionArgs[contractKey] = {};
56
+ }
57
+ context.functionArgs[contractKey][functionName] =
58
+ functionArgsDefinition;
59
+ }
60
+ }
61
+
62
+ const tokenXDecimals = getTokenDecimals(tokenXId, context);
63
+ let tokenXMatchingDecimal:
64
+ | { tokenContract: string; tokenDecimals: number }
65
+ | undefined;
66
+
67
+ for (const key in parameters) {
68
+ if (typeof parameters[key] === "object") {
69
+ for (const subKey in parameters[key]) {
70
+ const contractValue = parameters[key][subKey];
71
+ tokenXMatchingDecimal = tokenXDecimals.find(
72
+ (d) => d.tokenContract === contractValue
73
+ );
74
+ if (tokenXMatchingDecimal) break;
75
+ }
76
+ } else if (typeof parameters[key] === "string") {
77
+ tokenXMatchingDecimal = tokenXDecimals.find(
78
+ (d) => d.tokenContract === parameters[key]
79
+ );
80
+ }
81
+ if (tokenXMatchingDecimal) break;
82
+ }
83
+
84
+ if (!tokenXMatchingDecimal && swapData && swapData.parameters) {
85
+ const swapParameters = swapData.parameters;
86
+ for (const key in swapParameters) {
87
+ if (typeof swapParameters[key] === "object") {
88
+ for (const subKey in swapParameters[key]) {
89
+ const contractValue = swapParameters[key][subKey];
90
+ tokenXMatchingDecimal = tokenXDecimals.find(
91
+ (d) => d.tokenContract === contractValue
92
+ );
93
+ if (tokenXMatchingDecimal) break;
94
+ }
95
+ } else if (typeof swapParameters[key] === "string") {
96
+ tokenXMatchingDecimal = tokenXDecimals.find(
97
+ (d) => d.tokenContract === swapParameters[key]
98
+ );
99
+ }
100
+ if (tokenXMatchingDecimal) break;
101
+ }
102
+ }
103
+
104
+ if (tokenXMatchingDecimal) {
105
+ const scaleAmount = (amount: number | string) => {
106
+ const scaledAmount =
107
+ parseFloat(amount.toString()) *
108
+ 10 ** tokenXMatchingDecimal!.tokenDecimals;
109
+ return BigInt(Math.floor(scaledAmount));
110
+ };
111
+
112
+ if (parameters.dx !== undefined && parameters.dx !== null) {
113
+ parameters.dx = scaleAmount(parameters.dx);
114
+ } else if (
115
+ parameters.amount !== undefined &&
116
+ parameters.amount !== null
117
+ ) {
118
+ parameters.amount = scaleAmount(parameters.amount);
119
+ } else if (
120
+ parameters["amt-in"] !== undefined &&
121
+ parameters["amt-in"] !== null
122
+ ) {
123
+ parameters["amt-in"] = scaleAmount(parameters["amt-in"]);
124
+ } else if (
125
+ parameters["amt-in-max"] !== undefined &&
126
+ parameters["amt-in-max"] !== null
127
+ ) {
128
+ parameters["amt-in-max"] = scaleAmount(parameters["amt-in-max"]);
129
+ } else if (
130
+ parameters["y-amount"] !== undefined &&
131
+ parameters["y-amount"] !== null
132
+ ) {
133
+ parameters["y-amount"] = scaleAmount(parameters["y-amount"]);
134
+ parameters["x-amount"] = scaleAmount(parameters["x-amount"]);
135
+ } else if (
136
+ parameters["x-amount"] !== undefined &&
137
+ parameters["x-amount"] !== null
138
+ ) {
139
+ parameters["x-amount"] = scaleAmount(parameters["x-amount"]);
140
+ } else if (parameters.dy !== undefined && parameters.dy !== null) {
141
+ parameters.dy = scaleAmount(parameters.dy);
142
+ }
143
+ } else {
144
+ console.warn(`No matching decimal found for tokenX: ${tokenXId}`);
145
+ }
146
+
147
+ const functionArgs = constructFunctionArgs(
148
+ parameters,
149
+ functionArgsDefinition
150
+ );
151
+
152
+ const result = await callReadOnlyFunction({
153
+ contractAddress: contractDeployer,
154
+ contractName,
155
+ functionName,
156
+ functionArgs,
157
+ senderAddress,
158
+ network,
159
+ });
160
+
161
+ const { rawResult, convertedResult } = handleResult(result);
162
+
163
+ try {
164
+ const tokenYDecimals = getTokenDecimals(tokenYId, context);
165
+
166
+ let tokenYMatchingDecimal:
167
+ | { tokenContract: string; tokenDecimals: number }
168
+ | undefined;
169
+
170
+ for (const key in parameters) {
171
+ if (typeof parameters[key] === "object") {
172
+ for (const subKey in parameters[key]) {
173
+ const contractValue = parameters[key][subKey];
174
+ tokenYMatchingDecimal = tokenYDecimals.find(
175
+ (d) => d.tokenContract === contractValue
176
+ );
177
+ if (tokenYMatchingDecimal) break;
178
+ }
179
+ } else if (typeof parameters[key] === "string") {
180
+ tokenYMatchingDecimal = tokenYDecimals.find(
181
+ (d) => d.tokenContract === parameters[key]
182
+ );
183
+ }
184
+ if (tokenYMatchingDecimal) break;
185
+ }
186
+
187
+ if (!tokenYMatchingDecimal && swapData && swapData.parameters) {
188
+ const swapParameters = swapData.parameters;
189
+ for (const key in swapParameters) {
190
+ if (typeof swapParameters[key] === "object") {
191
+ for (const subKey in swapParameters[key]) {
192
+ const contractValue = swapParameters[key][subKey];
193
+ tokenYMatchingDecimal = tokenYDecimals.find(
194
+ (d) => d.tokenContract === contractValue
195
+ );
196
+ if (tokenYMatchingDecimal) break;
197
+ }
198
+ } else if (typeof swapParameters[key] === "string") {
199
+ tokenYMatchingDecimal = tokenYDecimals.find(
200
+ (d) => d.tokenContract === swapParameters[key]
201
+ );
202
+ }
203
+ if (tokenYMatchingDecimal) break;
204
+ }
205
+ }
206
+
207
+ if (tokenYMatchingDecimal && typeof convertedResult === "number") {
208
+ const adjustedResult =
209
+ convertedResult / 10 ** tokenYMatchingDecimal.tokenDecimals;
210
+ return {
211
+ convertedResult: adjustedResult,
212
+ rawResult,
213
+ tokenXDecimals: tokenXMatchingDecimal?.tokenDecimals || 0,
214
+ tokenYDecimals: tokenYMatchingDecimal.tokenDecimals,
215
+ };
216
+ } else {
217
+ console.warn(
218
+ `No matching decimal found for tokenY: ${tokenYId} or result is not a number`
219
+ );
220
+
221
+ return {
222
+ convertedResult,
223
+ rawResult,
224
+ tokenXDecimals: tokenXMatchingDecimal?.tokenDecimals || 0,
225
+ tokenYDecimals: 0,
226
+ };
227
+ }
228
+ } catch (error) {
229
+ console.warn(`Couldn't apply decimal conversion: ${error}`);
230
+ console.warn("Using raw result without decimal conversion");
231
+
232
+ return {
233
+ convertedResult,
234
+ rawResult,
235
+ tokenXDecimals: tokenXMatchingDecimal?.tokenDecimals || 0,
236
+ tokenYDecimals: 0,
237
+ };
238
+ }
239
+ } catch (error) {
240
+ console.error(`Error calling read-only function ${functionName}:`, error);
241
+ throw error;
242
+ }
243
+ };
@@ -0,0 +1,53 @@
1
+ import { AnchorMode, PostConditionMode } from "@stacks/transactions";
2
+ import { openContractCall, StacksProvider } from "@stacks/connect";
3
+ import { SwapContext } from "../types";
4
+
5
+ export const executeSwapHelper = async (
6
+ swapParams: {
7
+ functionArgs: any[];
8
+ postConditions: any[];
9
+ contractAddress: string;
10
+ contractName: string;
11
+ functionName: string;
12
+ },
13
+ senderAddress: string,
14
+ context: SwapContext,
15
+ stacksProvider?: StacksProvider,
16
+ onFinish?: (data: any) => void,
17
+ onCancel?: () => void
18
+ ): Promise<void> => {
19
+ const network = context.network;
20
+
21
+ try {
22
+ const txOptions = {
23
+ contractAddress: swapParams.contractAddress,
24
+ contractName: swapParams.contractName,
25
+ functionName: swapParams.functionName,
26
+ functionArgs: swapParams.functionArgs,
27
+ senderAddress,
28
+ network,
29
+ anchorMode: AnchorMode.Any,
30
+ postConditionMode: PostConditionMode.Deny,
31
+ postConditions: swapParams.postConditions,
32
+ onFinish:
33
+ onFinish ||
34
+ ((data: any) => {
35
+ console.log("Transaction submitted:", data);
36
+ }),
37
+ onCancel:
38
+ onCancel ||
39
+ (() => {
40
+ console.log("Transaction canceled");
41
+ }),
42
+ };
43
+
44
+ if (stacksProvider) {
45
+ await openContractCall(txOptions, stacksProvider);
46
+ } else {
47
+ await openContractCall(txOptions);
48
+ }
49
+ } catch (error) {
50
+ console.error("Error executing swap:", error);
51
+ throw error;
52
+ }
53
+ };
@@ -0,0 +1,24 @@
1
+ import { stringifyWithBigInt } from "./callReadOnlyHelper";
2
+ import { convertValue } from "./convertValuesHelper";
3
+
4
+ export const constructFunctionArgs = (
5
+ parameters: any,
6
+ functionArgsDefinition: any[]
7
+ ) => {
8
+ return functionArgsDefinition.map((arg) => {
9
+ const value = parameters[arg.name];
10
+
11
+ if (value === undefined || value === null) {
12
+ console.warn(`Value for ${arg.name} is ${value}`);
13
+ }
14
+
15
+ try {
16
+ const convertedValue = convertValue(value, arg.type);
17
+
18
+ return convertedValue;
19
+ } catch (error) {
20
+ console.error(`Error converting value for ${arg.name}:`, error);
21
+ throw error;
22
+ }
23
+ });
24
+ };
@@ -0,0 +1,214 @@
1
+ import {
2
+ boolCV,
3
+ bufferCV,
4
+ ClarityValue,
5
+ contractPrincipalCV,
6
+ intCV,
7
+ listCV,
8
+ noneCV,
9
+ responseErrorCV,
10
+ responseOkCV,
11
+ someCV,
12
+ standardPrincipalCV,
13
+ stringAsciiCV,
14
+ stringUtf8CV,
15
+ tupleCV,
16
+ uintCV,
17
+ } from "@stacks/transactions";
18
+
19
+ export const convertValue = (value: any, type: any): ClarityValue => {
20
+ if (value === null || value === undefined) {
21
+ console.warn(
22
+ `Received null or undefined value for type ${JSON.stringify(
23
+ type
24
+ )}. Using default value.`
25
+ );
26
+ return getDefaultValue(type);
27
+ }
28
+
29
+ if (typeof type === "object") {
30
+ return handleObjectType(value, type);
31
+ }
32
+
33
+ switch (type) {
34
+ case "uint128":
35
+ case "uint":
36
+ return handleUintType(value);
37
+ case "int128":
38
+ case "int":
39
+ return handleIntType(value);
40
+ case "bool":
41
+ return handleBoolType(value);
42
+ case "principal":
43
+ return handlePrincipalType(value);
44
+ case "trait_reference":
45
+ return handleTraitReferenceType(value);
46
+ case "optional":
47
+ return handleOptionalType(value);
48
+ case "response":
49
+ return handleResponseType(value);
50
+ case "string-ascii":
51
+ return stringAsciiCV(value);
52
+ case "string-utf8":
53
+ return stringUtf8CV(value);
54
+ case "list":
55
+ return handleListType(value);
56
+ case "buffer":
57
+ return bufferCV(Buffer.from(value));
58
+ default:
59
+ if (typeof value === "object") {
60
+ return handleTupleType(value);
61
+ }
62
+ throw new Error(`Unsupported argument type: ${type}`);
63
+ }
64
+ };
65
+
66
+ const getDefaultValue = (type: any): ClarityValue => {
67
+ if (typeof type === "object") {
68
+ if (
69
+ type.type === "uint128" ||
70
+ (type.optional && type.optional === "uint128")
71
+ ) {
72
+ return noneCV();
73
+ }
74
+ if (type.tuple) {
75
+ return tupleCV({});
76
+ }
77
+ if (type.list) {
78
+ return listCV([]);
79
+ }
80
+ }
81
+ switch (type) {
82
+ case "uint128":
83
+ case "uint":
84
+ return uintCV(0);
85
+ case "int128":
86
+ case "int":
87
+ return intCV(0);
88
+ case "bool":
89
+ return boolCV(false);
90
+ case "optional":
91
+ case "optional(uint128)":
92
+ return noneCV();
93
+ case "string-ascii":
94
+ case "string-utf8":
95
+ return stringAsciiCV("");
96
+ case "buffer":
97
+ return bufferCV(Buffer.alloc(0));
98
+ case "list":
99
+ return listCV([]);
100
+ default:
101
+ throw new Error(
102
+ `Cannot provide default value for type: ${JSON.stringify(type)}`
103
+ );
104
+ }
105
+ };
106
+
107
+ const handleObjectType = (value: any, type: any): ClarityValue => {
108
+ if (type.type === "uint128") {
109
+ return uintCV(value);
110
+ }
111
+ if (type.optional === "uint128") {
112
+ return someCV(uintCV(value));
113
+ }
114
+ if (type.tuple) {
115
+ return handleTupleType(value, type.tuple);
116
+ }
117
+ if (type.list) {
118
+ return handleListType(value, type.list.type);
119
+ }
120
+ throw new Error(`Unsupported object-based type: ${JSON.stringify(type)}`);
121
+ };
122
+
123
+ const handleUintType = (value: any): ClarityValue => {
124
+ if (typeof value === "number" || typeof value === "bigint") {
125
+ return uintCV(value);
126
+ } else if (typeof value === "string") {
127
+ if (/^\d+$/.test(value)) {
128
+ return uintCV(value);
129
+ } else if (/^0x[0-9A-Fa-f]+$/.test(value)) {
130
+ return uintCV(BigInt(value));
131
+ }
132
+ } else if (value instanceof Uint8Array) {
133
+ return uintCV(value);
134
+ }
135
+ throw new Error(`Invalid uint128 value: ${value} (type: ${typeof value})`);
136
+ };
137
+
138
+ const handleIntType = (value: any): ClarityValue => {
139
+ if (
140
+ typeof value === "number" ||
141
+ typeof value === "bigint" ||
142
+ (typeof value === "string" && /^-?\d+$/.test(value))
143
+ ) {
144
+ return intCV(value);
145
+ }
146
+ throw new Error(`Invalid int128 value: ${value} (type: ${typeof value})`);
147
+ };
148
+
149
+ const handleBoolType = (value: any): ClarityValue => {
150
+ if (typeof value === "boolean") {
151
+ return boolCV(value);
152
+ }
153
+ throw new Error(`Invalid boolean value: ${value} (type: ${typeof value})`);
154
+ };
155
+
156
+ const handlePrincipalType = (value: string): ClarityValue => {
157
+ if (value.includes(".")) {
158
+ const [addr, name] = value.split(".");
159
+ return contractPrincipalCV(addr, name);
160
+ } else {
161
+ return standardPrincipalCV(value);
162
+ }
163
+ };
164
+
165
+ const handleTraitReferenceType = (value: string): ClarityValue => {
166
+ const [addr, name] = value.split(".");
167
+ return contractPrincipalCV(addr, name);
168
+ };
169
+
170
+ const handleOptionalType = (value: any): ClarityValue => {
171
+ return value !== null && value !== undefined
172
+ ? someCV(convertValue(value, "uint128"))
173
+ : noneCV();
174
+ };
175
+
176
+ const handleResponseType = (value: any): ClarityValue => {
177
+ if (
178
+ value &&
179
+ typeof value === "object" &&
180
+ ("ok" in value || "error" in value)
181
+ ) {
182
+ return "ok" in value
183
+ ? responseOkCV(convertValue(value.ok, typeof value.ok))
184
+ : responseErrorCV(convertValue(value.error, typeof value.error));
185
+ }
186
+ throw new Error(`Invalid response value: ${JSON.stringify(value)}`);
187
+ };
188
+
189
+ const handleListType = (value: any[], itemType?: any): ClarityValue => {
190
+ if (Array.isArray(value)) {
191
+ return listCV(
192
+ value.map((item) => convertValue(item, itemType || typeof item))
193
+ );
194
+ }
195
+ throw new Error(`Invalid list value: ${JSON.stringify(value)}`);
196
+ };
197
+
198
+ const handleTupleType = (value: any, tupleTypes?: any[]): ClarityValue => {
199
+ const tupleValues: { [key: string]: ClarityValue } = {};
200
+ if (tupleTypes) {
201
+ tupleTypes.forEach((item: { name: string; type: any }) => {
202
+ if (value && value[item.name] !== undefined) {
203
+ tupleValues[item.name] = convertValue(value[item.name], item.type);
204
+ } else {
205
+ tupleValues[item.name] = getDefaultValue(item.type);
206
+ }
207
+ });
208
+ } else {
209
+ for (const [key, val] of Object.entries(value)) {
210
+ tupleValues[key] = convertValue(val, typeof val);
211
+ }
212
+ }
213
+ return tupleCV(tupleValues);
214
+ };
@@ -0,0 +1,19 @@
1
+ import { configs } from "../config";
2
+
3
+ export const fetchContractInterface = async (
4
+ contractDeployer: string,
5
+ contractName: string
6
+ ): Promise<any> => {
7
+ const url = `${configs.READONLY_CALL_API_HOST}/v2/contracts/interface/${contractDeployer}/${contractName}`;
8
+
9
+ try {
10
+ const response = await fetch(url);
11
+ if (!response.ok) {
12
+ throw new Error(`HTTP error! status: ${response.status}`);
13
+ }
14
+ return await response.json();
15
+ } catch (error) {
16
+ console.error(`Error fetching contract interface from ${url}:`, error);
17
+ throw error;
18
+ }
19
+ };