@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.
Files changed (64) hide show
  1. package/dist/src/BitflowSDK.d.ts +23 -2
  2. package/dist/src/BitflowSDK.js +536 -82
  3. package/dist/src/BitflowSDK.js.map +1 -1
  4. package/dist/src/config.d.ts +1 -1
  5. package/dist/src/config.js +6 -4
  6. package/dist/src/config.js.map +1 -1
  7. package/dist/src/helpers/callReadOnlyHelper.js +10 -4
  8. package/dist/src/helpers/callReadOnlyHelper.js.map +1 -1
  9. package/dist/src/helpers/callSwapHelper.d.ts +2 -2
  10. package/dist/src/helpers/callSwapHelper.js +48 -7
  11. package/dist/src/helpers/callSwapHelper.js.map +1 -1
  12. package/dist/src/helpers/fetchDataHelper.d.ts +1 -1
  13. package/dist/src/helpers/fetchDataHelper.js +50 -17
  14. package/dist/src/helpers/fetchDataHelper.js.map +1 -1
  15. package/dist/src/helpers/fetchPossibleSwap.d.ts +2 -2
  16. package/dist/src/helpers/fetchPossibleSwap.js +10 -2
  17. package/dist/src/helpers/fetchPossibleSwap.js.map +1 -1
  18. package/dist/src/helpers/handleResultHelper.js +15 -15
  19. package/dist/src/helpers/handleResultHelper.js.map +1 -1
  20. package/dist/src/helpers/newPostConditionsHelper.d.ts +2 -0
  21. package/dist/src/helpers/newPostConditionsHelper.js +145 -0
  22. package/dist/src/helpers/newPostConditionsHelper.js.map +1 -0
  23. package/dist/src/helpers/postConditionsHelper.js +38 -13
  24. package/dist/src/helpers/postConditionsHelper.js.map +1 -1
  25. package/dist/src/index.d.ts +3 -2
  26. package/dist/src/index.js +1 -0
  27. package/dist/src/index.js.map +1 -1
  28. package/dist/src/keeper/keeperAPI.d.ts +10 -0
  29. package/dist/src/keeper/keeperAPI.js +332 -0
  30. package/dist/src/keeper/keeperAPI.js.map +1 -0
  31. package/dist/src/keeper/types.d.ts +253 -0
  32. package/dist/src/keeper/types.js +65 -0
  33. package/dist/src/keeper/types.js.map +1 -0
  34. package/dist/src/test-keeper-routes.d.ts +1 -0
  35. package/dist/src/test-keeper-routes.js +67 -0
  36. package/dist/src/test-keeper-routes.js.map +1 -0
  37. package/dist/src/test-raw-token-response.d.ts +1 -0
  38. package/dist/src/test-raw-token-response.js +79 -0
  39. package/dist/src/test-raw-token-response.js.map +1 -0
  40. package/dist/src/test-sdk.d.ts +1 -0
  41. package/dist/src/test-sdk.js +229 -0
  42. package/dist/src/test-sdk.js.map +1 -0
  43. package/dist/src/test-token.fetch.d.ts +1 -0
  44. package/dist/src/test-token.fetch.js +63 -0
  45. package/dist/src/test-token.fetch.js.map +1 -0
  46. package/dist/src/types.d.ts +27 -2
  47. package/package.json +6 -5
  48. package/src/BitflowSDK.ts +675 -97
  49. package/src/config.ts +9 -6
  50. package/src/helpers/callReadOnlyHelper.ts +12 -7
  51. package/src/helpers/callSwapHelper.ts +21 -7
  52. package/src/helpers/fetchDataHelper.ts +58 -19
  53. package/src/helpers/fetchPossibleSwap.ts +18 -4
  54. package/src/helpers/handleResultHelper.ts +17 -16
  55. package/src/helpers/newPostConditionsHelper.ts +172 -0
  56. package/src/helpers/postConditionsHelper.ts +71 -19
  57. package/src/index.ts +3 -2
  58. package/src/keeper/keeperAPI.ts +435 -0
  59. package/src/keeper/types.ts +293 -0
  60. package/src/test-keeper-routes.ts +76 -0
  61. package/src/test-raw-token-response.ts +124 -0
  62. package/src/test-sdk.ts +262 -0
  63. package/src/test-token.fetch.ts +72 -0
  64. package/src/types.ts +29 -2
package/src/config.ts CHANGED
@@ -1,13 +1,17 @@
1
- import { BitflowSDKConfig } from './types';
1
+ import { BitflowSDKConfig } from "./types";
2
2
 
3
3
  export const configs: BitflowSDKConfig = {
4
4
  BITFLOW_API_HOST:
5
- process.env.NEXT_PUBLIC_BITFLOW_API_HOST ?? process.env.BITFLOW_API_HOST,
5
+ (process.env.NEXT_PUBLIC_BITFLOW_API_HOST ??
6
+ process.env.BITFLOW_API_HOST) ||
7
+ "",
6
8
  BITFLOW_API_KEY:
7
- process.env.NEXT_PUBLIC_BITFLOW_API_KEY ?? process.env.BITFLOW_API_KEY,
9
+ (process.env.NEXT_PUBLIC_BITFLOW_API_KEY ?? process.env.BITFLOW_API_KEY) ||
10
+ "",
8
11
  READONLY_CALL_API_HOST:
9
- process.env.NEXT_PUBLIC_READONLY_CALL_API_HOST ??
10
- process.env.READONLY_CALL_API_HOST,
12
+ (process.env.NEXT_PUBLIC_READONLY_CALL_API_HOST ??
13
+ process.env.READONLY_CALL_API_HOST) ||
14
+ "",
11
15
  };
12
16
 
13
17
  export function validateConfig() {
@@ -15,7 +19,6 @@ export function validateConfig() {
15
19
 
16
20
  for (const envVar of requiredEnvVars) {
17
21
  if (!configs[envVar]) {
18
- console.error(`Missing required configuration: ${envVar}`);
19
22
  throw new Error(`Missing required configuration: ${envVar}`);
20
23
  }
21
24
  }
@@ -1,8 +1,7 @@
1
- import { callReadOnlyFunction } from "@stacks/transactions";
1
+ import { fetchCallReadOnlyFunction } from "@stacks/transactions";
2
2
  import { SwapContext } from "../types";
3
3
  import { getTokenDecimals } from "./getTokenDecimalsHelper";
4
4
  import { constructFunctionArgs } from "./constructFunctionArgs";
5
- import { StacksMainnet } from "@stacks/network";
6
5
  import { configs } from "../config";
7
6
  import { getContractInterfaceAndFunction } from "./getContractInterfaceAndFunction";
8
7
  import { handleResult } from "./handleResultHelper";
@@ -29,7 +28,11 @@ export const callReadOnlyFunctionHelper = async (
29
28
  tokenXDecimals: number;
30
29
  tokenYDecimals: number;
31
30
  }> => {
32
- const network = new StacksMainnet({ url: configs.READONLY_CALL_API_HOST });
31
+ const network = "mainnet";
32
+
33
+ const client = {
34
+ baseUrl: configs.READONLY_CALL_API_HOST,
35
+ };
33
36
 
34
37
  try {
35
38
  const contractKey = `${contractDeployer}.${contractName}`;
@@ -64,6 +67,7 @@ export const callReadOnlyFunctionHelper = async (
64
67
  | { tokenContract: string; tokenDecimals: number }
65
68
  | undefined;
66
69
 
70
+ // Attempt to find matching token decimals from parameters
67
71
  for (const key in parameters) {
68
72
  if (typeof parameters[key] === "object") {
69
73
  for (const subKey in parameters[key]) {
@@ -81,6 +85,7 @@ export const callReadOnlyFunctionHelper = async (
81
85
  if (tokenXMatchingDecimal) break;
82
86
  }
83
87
 
88
+ // If not found yet, also check swapData parameters
84
89
  if (!tokenXMatchingDecimal && swapData && swapData.parameters) {
85
90
  const swapParameters = swapData.parameters;
86
91
  for (const key in swapParameters) {
@@ -101,6 +106,7 @@ export const callReadOnlyFunctionHelper = async (
101
106
  }
102
107
  }
103
108
 
109
+ // Scale parameters if we find a matching decimal for tokenX
104
110
  if (tokenXMatchingDecimal) {
105
111
  const scaleAmount = (amount: number | string) => {
106
112
  const scaledAmount =
@@ -149,13 +155,14 @@ export const callReadOnlyFunctionHelper = async (
149
155
  functionArgsDefinition
150
156
  );
151
157
 
152
- const result = await callReadOnlyFunction({
158
+ const result = await fetchCallReadOnlyFunction({
153
159
  contractAddress: contractDeployer,
154
160
  contractName,
155
161
  functionName,
156
162
  functionArgs,
157
- senderAddress,
158
163
  network,
164
+ client,
165
+ senderAddress: senderAddress,
159
166
  });
160
167
 
161
168
  const { rawResult, convertedResult } = handleResult(result);
@@ -217,7 +224,6 @@ export const callReadOnlyFunctionHelper = async (
217
224
  console.warn(
218
225
  `No matching decimal found for tokenY: ${tokenYId} or result is not a number`
219
226
  );
220
-
221
227
  return {
222
228
  convertedResult,
223
229
  rawResult,
@@ -228,7 +234,6 @@ export const callReadOnlyFunctionHelper = async (
228
234
  } catch (error) {
229
235
  console.warn(`Couldn't apply decimal conversion: ${error}`);
230
236
  console.warn("Using raw result without decimal conversion");
231
-
232
237
  return {
233
238
  convertedResult,
234
239
  rawResult,
@@ -1,7 +1,23 @@
1
1
  import { AnchorMode, PostConditionMode } from "@stacks/transactions";
2
- import { openContractCall, StacksProvider } from "@stacks/connect";
2
+ import type { StacksProvider } from "@stacks/connect";
3
3
  import { SwapContext } from "../types";
4
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
+
5
21
  export const executeSwapHelper = async (
6
22
  swapParams: {
7
23
  functionArgs: any[];
@@ -12,13 +28,15 @@ export const executeSwapHelper = async (
12
28
  },
13
29
  senderAddress: string,
14
30
  context: SwapContext,
15
- stacksProvider?: StacksProvider,
31
+ stacksProvider: StacksProvider,
16
32
  onFinish?: (data: any) => void,
17
33
  onCancel?: () => void
18
34
  ): Promise<void> => {
19
35
  const network = context.network;
20
36
 
21
37
  try {
38
+ const { openContractCall } = await loadStacksConnect();
39
+
22
40
  const txOptions = {
23
41
  contractAddress: swapParams.contractAddress,
24
42
  contractName: swapParams.contractName,
@@ -41,11 +59,7 @@ export const executeSwapHelper = async (
41
59
  }),
42
60
  };
43
61
 
44
- if (stacksProvider) {
45
- await openContractCall(txOptions, stacksProvider);
46
- } else {
47
- await openContractCall(txOptions);
48
- }
62
+ await openContractCall({ ...txOptions }, stacksProvider);
49
63
  } catch (error) {
50
64
  console.error("Error executing swap:", error);
51
65
  throw error;
@@ -1,5 +1,5 @@
1
- import { configs } from '../config';
2
- import { Token } from '../types';
1
+ import { configs } from "../config";
2
+ import { Token, LayerOneAsset, PriceData } from "../types";
3
3
 
4
4
  export const fetchAllTokensFromAPI = async (): Promise<Token[]> => {
5
5
  const url = `${configs.BITFLOW_API_HOST}/getAllTokensAndPools?key=${configs.BITFLOW_API_KEY}`;
@@ -10,30 +10,69 @@ export const fetchAllTokensFromAPI = async (): Promise<Token[]> => {
10
10
  }
11
11
  const data = await response.json();
12
12
  if (!data.tokens || !Array.isArray(data.tokens)) {
13
- console.error('Unexpected data structure returned by API:', data);
14
- throw new Error('Unexpected data structure returned by API');
13
+ console.error("Unexpected data structure returned by API:", data);
14
+ throw new Error("Unexpected data structure returned by API");
15
15
  }
16
16
 
17
- return data.tokens.map((token: any) => ({
18
- icon: token.icon,
19
- name: token.name,
20
- status: token.status,
21
- symbol: token.symbol,
22
- tokenId: token['token-id'],
23
- tokenContract: token.tokenContract,
24
- tokenDecimals: token.tokenDecimals,
25
- tokenName: token.tokenName,
26
- wrapTokens: token.wrapTokens
27
- ? Object.keys(token.wrapTokens).reduce((acc: any, key: string) => {
17
+ return data.tokens.map((token: any) => {
18
+ // Basic token properties
19
+ const mappedToken: Token = {
20
+ icon: token.icon || "",
21
+ name: token.name || "",
22
+ status: token.status || "",
23
+ symbol: token.symbol || "",
24
+ "token-id": token["token-id"] || "",
25
+ tokenId: token["token-id"] || "", // Duplicate for compatibility
26
+ tokenContract: token.tokenContract || null,
27
+ tokenDecimals: token.tokenDecimals || 0,
28
+ tokenName: token.tokenName || null,
29
+ wrapTokens: null,
30
+ base: token.base || "",
31
+ type: token.type || "",
32
+ isKeeperToken: token.isKeeperToken || false,
33
+ bridge: token.bridge || "FALSE",
34
+ layerOneAsset: token.layerOneAsset || null,
35
+ priceData: token.priceData || {
36
+ "1h_change": null,
37
+ "1yr_change": null,
38
+ "24h_change": null,
39
+ "30d_change": null,
40
+ "7d_change": null,
41
+ last_price: null,
42
+ last_updated: null,
43
+ },
44
+ };
45
+
46
+ // Handle wrapTokens if present
47
+ if (token.wrapTokens) {
48
+ mappedToken.wrapTokens = Object.keys(token.wrapTokens).reduce(
49
+ (acc: any, key: string) => {
28
50
  acc[key] = {
29
51
  tokenContract: token.wrapTokens[key].tokenContract,
30
52
  tokenDecimals: token.wrapTokens[key].tokenDecimals,
31
- tokenName: token.wrapTokens[key].tokenName,
53
+ tokenName: token.wrapTokens[key].tokenName || null,
32
54
  };
33
55
  return acc;
34
- }, {})
35
- : null,
36
- }));
56
+ },
57
+ {}
58
+ );
59
+ }
60
+
61
+ // Handle layerOneAsset if present
62
+ if (token.layerOneAsset && Object.keys(token.layerOneAsset).length > 0) {
63
+ mappedToken.layerOneAsset = {
64
+ address: token.layerOneAsset.address || "",
65
+ divisibility: token.layerOneAsset.divisibility || 0,
66
+ icon: token.layerOneAsset.icon || "",
67
+ isBitcoin: token.layerOneAsset.isBitcoin || false,
68
+ runeid: token.layerOneAsset.runeid || "",
69
+ spacedRune: token.layerOneAsset.spacedRune || "",
70
+ symbol: token.layerOneAsset.symbol || null,
71
+ };
72
+ }
73
+
74
+ return mappedToken;
75
+ });
37
76
  } catch (error) {
38
77
  console.error(`Error fetching data from ${url}:`, error);
39
78
  throw error;
@@ -1,10 +1,24 @@
1
- import { configs } from '../config';
2
- import { SwapOptions } from '../types';
1
+ import { configs } from "../config";
2
+ import { SwapOptions } from "../types";
3
3
 
4
4
  export const fetchPossibleSwapsFromAPI = async (
5
- tokenX: string
5
+ tokenX: string,
6
+ page?: "KEEPER"
6
7
  ): Promise<SwapOptions> => {
7
- const url = `${configs.BITFLOW_API_HOST}/getAllRoutes?key=${configs.BITFLOW_API_KEY}&tokenX=${tokenX}&depth=4`;
8
+ const queryParams = new URLSearchParams({
9
+ key: configs.BITFLOW_API_KEY,
10
+ tokenX: tokenX,
11
+ depth: "4",
12
+ });
13
+
14
+ if (page) {
15
+ queryParams.append("page", page);
16
+ }
17
+
18
+ const url = `${
19
+ configs.BITFLOW_API_HOST
20
+ }/getAllRoutes?${queryParams.toString()}`;
21
+
8
22
  try {
9
23
  const response = await fetch(url);
10
24
  if (!response.ok) {
@@ -1,3 +1,5 @@
1
+ import { ClarityType } from "@stacks/transactions";
2
+
1
3
  export const handleResult = (
2
4
  result: any
3
5
  ): { rawResult: any; convertedResult: any } => {
@@ -10,53 +12,52 @@ export const handleResult = (
10
12
 
11
13
  // Check if the result has a 'data' property and use it if present
12
14
  const value = result.data !== undefined ? result.data : result.value;
13
-
14
15
  switch (result.type) {
15
- case 0:
16
+ case "int":
16
17
  rawResult = BigInt(result.value);
17
18
  convertedResult = Number(rawResult);
18
19
  break;
19
- case 1:
20
+ case "uint":
20
21
  rawResult = BigInt(result.value);
21
22
  convertedResult = Number(rawResult);
22
23
  break;
23
- case 2:
24
+ case "buffer":
24
25
  rawResult = Buffer.from(result.value);
25
26
  convertedResult = rawResult.toString("hex");
26
27
  break;
27
- case 3:
28
+ case "true":
28
29
  rawResult = true;
29
30
  convertedResult = true;
30
31
  break;
31
- case 4:
32
+ case "false":
32
33
  rawResult = false;
33
34
  convertedResult = false;
34
35
  break;
35
- case 5:
36
+ case "address":
36
37
  rawResult = result.value;
37
38
  convertedResult = result.value;
38
39
  break;
39
- case 6:
40
+ case "contract":
40
41
  rawResult = `${result.value.address}.${result.value.contractName}`;
41
42
  convertedResult = rawResult;
42
43
  break;
43
- case 7:
44
+ case "ok":
44
45
  return handleResult(result.value);
45
- case 8:
46
+ case "err":
46
47
  return handleResult(result.value);
47
- case 9:
48
+ case "none":
48
49
  rawResult = null;
49
50
  convertedResult = null;
50
51
  break;
51
- case 10:
52
+ case "some":
52
53
  return handleResult(result.value);
53
- case 11:
54
+ case "list":
54
55
  rawResult = result.value.map((item: any) => handleResult(item).rawResult);
55
56
  convertedResult = result.value.map(
56
57
  (item: any) => handleResult(item).convertedResult
57
58
  );
58
59
  break;
59
- case 12: // tuple
60
+ case "tuple":
60
61
  if (typeof value !== "object" || value === null) {
61
62
  console.error("Tuple value is not an object:", value);
62
63
  return { rawResult: null, convertedResult: null };
@@ -69,11 +70,11 @@ export const handleResult = (
69
70
  const lastKey = sortedKeys[0];
70
71
 
71
72
  return handleResult(value[lastKey]);
72
- case 13:
73
+ case "ascii":
73
74
  rawResult = result.value;
74
75
  convertedResult = result.value;
75
76
  break;
76
- case 14:
77
+ case "utf8":
77
78
  rawResult = result.value;
78
79
  convertedResult = result.value;
79
80
  break;
@@ -0,0 +1,172 @@
1
+ import { Pc, PostCondition } from "@stacks/transactions";
2
+
3
+ const isWSTXv2Token = (value: any): boolean =>
4
+ typeof value === "string" &&
5
+ value.includes("SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.token-wstx-v2");
6
+
7
+ const checkForWSTXv2 = (obj: any): boolean => {
8
+ if (typeof obj !== "object" || obj === null) {
9
+ return false;
10
+ }
11
+
12
+ for (const key in obj) {
13
+ if (isWSTXv2Token(obj[key])) {
14
+ return true;
15
+ }
16
+ if (typeof obj[key] === "object" && checkForWSTXv2(obj[key])) {
17
+ return true;
18
+ }
19
+ }
20
+
21
+ return false;
22
+ };
23
+
24
+ export const createSwapPostConditions = async (
25
+ functionArgs: any,
26
+ postConditionsData: any,
27
+ senderAddress: string,
28
+ tokenXDecimals: number,
29
+ tokenYDecimals: number
30
+ ): Promise<PostCondition[]> => {
31
+ const postConditions: PostCondition[] = [];
32
+ const postConditionKeys = Object.keys(postConditionsData);
33
+
34
+ const isWSTXv2Involved = checkForWSTXv2(functionArgs);
35
+
36
+ for (let i = 0; i < postConditionKeys.length; i++) {
37
+ const key = postConditionKeys[i];
38
+ const pcData = postConditionsData[key];
39
+ const isFirst = i === 0;
40
+ const isLast = i === postConditionKeys.length - 1;
41
+ const isTxSender = pcData.senderAddress === "tx-sender";
42
+ const isSTX =
43
+ pcData.tokenContract === "token-stx" || pcData.tokenName === "token-stx";
44
+ const isAutoAlexV3OrLqstx =
45
+ pcData.tokenName === "auto-alex-v3" || pcData.tokenName === "lqstx";
46
+
47
+ let postConditionAmount: bigint;
48
+ let conditionCode: string;
49
+
50
+ if (isAutoAlexV3OrLqstx && (isFirst || isLast)) {
51
+ postConditionAmount = BigInt(0);
52
+ conditionCode = "willSendGte";
53
+ } else {
54
+ if (isFirst) {
55
+ postConditionAmount = functionArgs.dx;
56
+ conditionCode = "willSendEq";
57
+ } else if (isLast) {
58
+ postConditionAmount = functionArgs["min-dy"];
59
+ conditionCode = "willSendGte";
60
+ } else {
61
+ postConditionAmount = BigInt(0);
62
+ conditionCode = "willSendGte";
63
+ }
64
+ }
65
+
66
+ if (isSTX && isWSTXv2Involved) {
67
+ postConditionAmount = postConditionAmount / BigInt(100);
68
+ } else if (!isSTX && (isFirst || isLast)) {
69
+ let decimalDifference: number;
70
+ if (isFirst) {
71
+ decimalDifference = tokenXDecimals - pcData.tokenDecimals;
72
+ } else {
73
+ decimalDifference = tokenYDecimals - pcData.tokenDecimals;
74
+ }
75
+
76
+ if (decimalDifference > 0) {
77
+ postConditionAmount =
78
+ postConditionAmount / BigInt(10 ** decimalDifference);
79
+ } else if (decimalDifference < 0) {
80
+ postConditionAmount =
81
+ postConditionAmount * BigInt(10 ** Math.abs(decimalDifference));
82
+ }
83
+ }
84
+
85
+ try {
86
+ if (isTxSender) {
87
+ if (isSTX) {
88
+ postConditions.push(
89
+ conditionCode === "willSendEq"
90
+ ? Pc.principal(senderAddress)
91
+ .willSendEq(postConditionAmount)
92
+ .ustx()
93
+ : Pc.principal(senderAddress)
94
+ .willSendGte(postConditionAmount)
95
+ .ustx()
96
+ );
97
+ } else {
98
+ postConditions.push(
99
+ conditionCode === "willSendEq"
100
+ ? Pc.principal(senderAddress)
101
+ .willSendEq(postConditionAmount)
102
+ .ft(pcData.tokenContract, pcData.tokenName)
103
+ : Pc.principal(senderAddress)
104
+ .willSendGte(postConditionAmount)
105
+ .ft(pcData.tokenContract, pcData.tokenName)
106
+ );
107
+ }
108
+ } else {
109
+ if (isSTX) {
110
+ postConditions.push(
111
+ conditionCode === "willSendEq"
112
+ ? Pc.principal(pcData.senderAddress)
113
+ .willSendEq(postConditionAmount)
114
+ .ustx()
115
+ : Pc.principal(pcData.senderAddress)
116
+ .willSendGte(postConditionAmount)
117
+ .ustx()
118
+ );
119
+ } else {
120
+ postConditions.push(
121
+ conditionCode === "willSendEq"
122
+ ? Pc.principal(pcData.senderAddress)
123
+ .willSendEq(postConditionAmount)
124
+ .ft(pcData.tokenContract, pcData.tokenName)
125
+ : Pc.principal(pcData.senderAddress)
126
+ .willSendGte(postConditionAmount)
127
+ .ft(pcData.tokenContract, pcData.tokenName)
128
+ );
129
+ }
130
+ }
131
+
132
+ if (pcData.shareFeeContract !== null) {
133
+ if (isSTX) {
134
+ postConditions.push(
135
+ Pc.principal(pcData.shareFeeContract).willSendGte(0).ustx()
136
+ );
137
+ } else {
138
+ postConditions.push(
139
+ Pc.principal(pcData.shareFeeContract)
140
+ .willSendGte(0)
141
+ .ft(pcData.tokenContract, pcData.tokenName)
142
+ );
143
+ }
144
+ }
145
+
146
+ if (pcData.dikoStx !== null) {
147
+ if (isTxSender) {
148
+ postConditions.push(
149
+ Pc.principal(senderAddress)
150
+ .willSendGte(0)
151
+ .ft(pcData.dikoStx, "wstx")
152
+ );
153
+ } else {
154
+ postConditions.push(
155
+ Pc.principal(pcData.senderAddress)
156
+ .willSendGte(0)
157
+ .ft(pcData.dikoStx, "wstx")
158
+ );
159
+ }
160
+ }
161
+ } catch (error) {
162
+ console.error(`Error creating post condition for ${key}:`, error);
163
+ throw new Error(
164
+ `Failed to create post condition for ${key}: ${
165
+ (error as Error).message
166
+ }`
167
+ );
168
+ }
169
+ }
170
+
171
+ return postConditions;
172
+ };
@@ -1,12 +1,4 @@
1
- import {
2
- FungibleConditionCode,
3
- makeStandardFungiblePostCondition,
4
- makeStandardSTXPostCondition,
5
- makeContractFungiblePostCondition,
6
- makeContractSTXPostCondition,
7
- createAssetInfo,
8
- PostCondition,
9
- } from "@stacks/transactions";
1
+ import { FungibleConditionCode, Pc, PostCondition } from "@stacks/transactions";
10
2
 
11
3
  const isWSTXv2Token = (value: any): boolean =>
12
4
  typeof value === "string" &&
@@ -34,17 +26,77 @@ const createSafeAssetInfo = (
34
26
  contractName: string,
35
27
  assetName: string
36
28
  ) => {
37
- try {
38
- return createAssetInfo(contractAddress, contractName, assetName);
39
- } catch (error) {
40
- console.error(
41
- `Failed to create asset info for ${contractAddress}.${contractName}::${assetName}`,
42
- error
43
- );
44
- throw new Error(
45
- `Invalid asset info: ${contractAddress}.${contractName}::${assetName}`
46
- );
29
+ return {
30
+ contract: `${contractAddress}.${contractName}` as `${string}.${string}`,
31
+ tokenName: `${assetName}`,
32
+ };
33
+ };
34
+
35
+ const makeStandardSTXPostCondition = (
36
+ senderAddress: string,
37
+ conditionCode:
38
+ | FungibleConditionCode.Equal
39
+ | FungibleConditionCode.GreaterEqual,
40
+ postConditionAmount: bigint
41
+ ) => {
42
+ let initialPostCondition = Pc.principal(senderAddress);
43
+ let postCondition;
44
+ if (conditionCode === FungibleConditionCode.Equal) {
45
+ postCondition = initialPostCondition.willSendEq(postConditionAmount);
46
+ } else {
47
+ postCondition = initialPostCondition.willSendGte(postConditionAmount);
48
+ }
49
+ return postCondition.ustx();
50
+ };
51
+
52
+ const makeStandardFungiblePostCondition = (
53
+ senderAddress: string,
54
+ conditionCode:
55
+ | FungibleConditionCode.Equal
56
+ | FungibleConditionCode.GreaterEqual,
57
+ postConditionAmount: bigint,
58
+ asset: { contract: `${string}.${string}`; tokenName: string }
59
+ ) => {
60
+ let initialPostCondition = Pc.principal(senderAddress);
61
+ let postCondition;
62
+ if (conditionCode === FungibleConditionCode.Equal) {
63
+ postCondition = initialPostCondition.willSendEq(postConditionAmount);
64
+ } else {
65
+ postCondition = initialPostCondition.willSendGte(postConditionAmount);
47
66
  }
67
+ return postCondition.ft(asset.contract, asset.tokenName);
68
+ };
69
+
70
+ const makeContractSTXPostCondition = (
71
+ contractAddress: string,
72
+ contractName: string,
73
+ conditionCode:
74
+ | FungibleConditionCode.Equal
75
+ | FungibleConditionCode.GreaterEqual,
76
+ postConditionAmount: bigint
77
+ ) => {
78
+ return makeStandardSTXPostCondition(
79
+ `${contractAddress}.${contractName}`,
80
+ conditionCode,
81
+ postConditionAmount
82
+ );
83
+ };
84
+
85
+ const makeContractFungiblePostCondition = (
86
+ contractAddress: string,
87
+ contractName: string,
88
+ conditionCode:
89
+ | FungibleConditionCode.Equal
90
+ | FungibleConditionCode.GreaterEqual,
91
+ postConditionAmount: bigint,
92
+ asset: { contract: `${string}.${string}`; tokenName: string }
93
+ ) => {
94
+ return makeStandardFungiblePostCondition(
95
+ `${contractAddress}.${contractName}`,
96
+ conditionCode,
97
+ postConditionAmount,
98
+ asset
99
+ );
48
100
  };
49
101
 
50
102
  export const createSwapPostConditions = async (
package/src/index.ts CHANGED
@@ -1,2 +1,3 @@
1
- export { BitflowSDK } from './BitflowSDK';
2
- export * from './types';
1
+ export { BitflowSDK } from "./BitflowSDK";
2
+ export * from "./types";
3
+ export * from "./keeper/types";