@7kprotocol/sdk-ts 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 (201) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +122 -0
  3. package/lib/cjs/buildTx.js +93 -0
  4. package/lib/cjs/constants/explorer.js +6 -0
  5. package/lib/cjs/constants/tokens.js +5 -0
  6. package/lib/cjs/estimateGasFee.js +52 -0
  7. package/lib/cjs/getQuote.js +22 -0
  8. package/lib/cjs/getSuiPrice.js +31 -0
  9. package/lib/cjs/index.js +37 -0
  10. package/lib/cjs/libs/getCoinOjectIdsByAmount.js +74 -0
  11. package/lib/cjs/libs/getSplitCoinForTx.js +55 -0
  12. package/lib/cjs/libs/groupSwapRoutes.js +62 -0
  13. package/lib/cjs/libs/protocols/aftermath/index.js +52 -0
  14. package/lib/cjs/libs/protocols/base.js +20 -0
  15. package/lib/cjs/libs/protocols/bluemove/index.js +36 -0
  16. package/lib/cjs/libs/protocols/cetus/index.js +56 -0
  17. package/lib/cjs/libs/protocols/constants.js +5 -0
  18. package/lib/cjs/libs/protocols/deepbook/index.js +96 -0
  19. package/lib/cjs/libs/protocols/flowx/index.js +31 -0
  20. package/lib/cjs/libs/protocols/index.js +21 -0
  21. package/lib/cjs/libs/protocols/kriya/index.js +42 -0
  22. package/lib/cjs/libs/protocols/suiswap/index.js +45 -0
  23. package/lib/cjs/libs/protocols/turbos/constants.js +7 -0
  24. package/lib/cjs/libs/protocols/turbos/index.js +53 -0
  25. package/lib/cjs/libs/protocols/utils.js +11 -0
  26. package/lib/cjs/libs/swapWithRoute.js +31 -0
  27. package/lib/cjs/suiClient.js +14 -0
  28. package/lib/cjs/types/aggregator.js +2 -0
  29. package/lib/cjs/types/buildTx.d.ts +4 -0
  30. package/lib/cjs/types/buildTx.d.ts.map +1 -0
  31. package/lib/cjs/types/constants/explorer.d.ts +4 -0
  32. package/lib/cjs/types/constants/explorer.d.ts.map +1 -0
  33. package/lib/cjs/types/constants/tokens.d.ts +3 -0
  34. package/lib/cjs/types/constants/tokens.d.ts.map +1 -0
  35. package/lib/cjs/types/estimateGasFee.d.ts +3 -0
  36. package/lib/cjs/types/estimateGasFee.d.ts.map +1 -0
  37. package/lib/cjs/types/getQuote.d.ts +9 -0
  38. package/lib/cjs/types/getQuote.d.ts.map +1 -0
  39. package/lib/cjs/types/getSuiPrice.d.ts +2 -0
  40. package/lib/cjs/types/getSuiPrice.d.ts.map +1 -0
  41. package/lib/cjs/types/index.d.ts +17 -0
  42. package/lib/cjs/types/index.d.ts.map +1 -0
  43. package/lib/cjs/types/libs/getCoinOjectIdsByAmount.d.ts +7 -0
  44. package/lib/cjs/types/libs/getCoinOjectIdsByAmount.d.ts.map +1 -0
  45. package/lib/cjs/types/libs/getSplitCoinForTx.d.ts +6 -0
  46. package/lib/cjs/types/libs/getSplitCoinForTx.d.ts.map +1 -0
  47. package/lib/cjs/types/libs/groupSwapRoutes.d.ts +3 -0
  48. package/lib/cjs/types/libs/groupSwapRoutes.d.ts.map +1 -0
  49. package/lib/cjs/types/libs/protocols/aftermath/index.d.ts +10 -0
  50. package/lib/cjs/types/libs/protocols/aftermath/index.d.ts.map +1 -0
  51. package/lib/cjs/types/libs/protocols/base.d.ts +37 -0
  52. package/lib/cjs/types/libs/protocols/base.d.ts.map +1 -0
  53. package/lib/cjs/types/libs/protocols/bluemove/index.d.ts +10 -0
  54. package/lib/cjs/types/libs/protocols/bluemove/index.d.ts.map +1 -0
  55. package/lib/cjs/types/libs/protocols/cetus/index.d.ts +10 -0
  56. package/lib/cjs/types/libs/protocols/cetus/index.d.ts.map +1 -0
  57. package/lib/cjs/types/libs/protocols/constants.d.ts +3 -0
  58. package/lib/cjs/types/libs/protocols/constants.d.ts.map +1 -0
  59. package/lib/cjs/types/libs/protocols/deepbook/index.d.ts +12 -0
  60. package/lib/cjs/types/libs/protocols/deepbook/index.d.ts.map +1 -0
  61. package/lib/cjs/types/libs/protocols/flowx/index.d.ts +10 -0
  62. package/lib/cjs/types/libs/protocols/flowx/index.d.ts.map +1 -0
  63. package/lib/cjs/types/libs/protocols/index.d.ts +19 -0
  64. package/lib/cjs/types/libs/protocols/index.d.ts.map +1 -0
  65. package/lib/cjs/types/libs/protocols/kriya/index.d.ts +10 -0
  66. package/lib/cjs/types/libs/protocols/kriya/index.d.ts.map +1 -0
  67. package/lib/cjs/types/libs/protocols/suiswap/index.d.ts +10 -0
  68. package/lib/cjs/types/libs/protocols/suiswap/index.d.ts.map +1 -0
  69. package/lib/cjs/types/libs/protocols/turbos/constants.d.ts +5 -0
  70. package/lib/cjs/types/libs/protocols/turbos/constants.d.ts.map +1 -0
  71. package/lib/cjs/types/libs/protocols/turbos/index.d.ts +10 -0
  72. package/lib/cjs/types/libs/protocols/turbos/index.d.ts.map +1 -0
  73. package/lib/cjs/types/libs/protocols/utils.d.ts +3 -0
  74. package/lib/cjs/types/libs/protocols/utils.d.ts.map +1 -0
  75. package/lib/cjs/types/libs/swapWithRoute.d.ts +10 -0
  76. package/lib/cjs/types/libs/swapWithRoute.d.ts.map +1 -0
  77. package/lib/cjs/types/sui.js +2 -0
  78. package/lib/cjs/types/suiClient.d.ts +4 -0
  79. package/lib/cjs/types/suiClient.d.ts.map +1 -0
  80. package/lib/cjs/types/token.js +2 -0
  81. package/lib/cjs/types/tx.js +2 -0
  82. package/lib/cjs/types/types/aggregator.d.ts +69 -0
  83. package/lib/cjs/types/types/aggregator.d.ts.map +1 -0
  84. package/lib/cjs/types/types/sui.d.ts +4 -0
  85. package/lib/cjs/types/types/sui.d.ts.map +1 -0
  86. package/lib/cjs/types/types/token.d.ts +30 -0
  87. package/lib/cjs/types/types/token.d.ts.map +1 -0
  88. package/lib/cjs/types/types/tx.d.ts +14 -0
  89. package/lib/cjs/types/types/tx.d.ts.map +1 -0
  90. package/lib/cjs/types/types/utilities.d.ts +5 -0
  91. package/lib/cjs/types/types/utilities.d.ts.map +1 -0
  92. package/lib/cjs/types/utilities.js +2 -0
  93. package/lib/cjs/types/utils/number.d.ts +4 -0
  94. package/lib/cjs/types/utils/number.d.ts.map +1 -0
  95. package/lib/cjs/types/utils/sui.d.ts +39 -0
  96. package/lib/cjs/types/utils/sui.d.ts.map +1 -0
  97. package/lib/cjs/types/utils/token.d.ts +6 -0
  98. package/lib/cjs/types/utils/token.d.ts.map +1 -0
  99. package/lib/cjs/utils/number.js +15 -0
  100. package/lib/cjs/utils/sui.js +180 -0
  101. package/lib/cjs/utils/token.js +36 -0
  102. package/lib/esm/buildTx.js +77 -0
  103. package/lib/esm/constants/explorer.js +3 -0
  104. package/lib/esm/constants/tokens.js +2 -0
  105. package/lib/esm/estimateGasFee.js +35 -0
  106. package/lib/esm/getQuote.js +8 -0
  107. package/lib/esm/getSuiPrice.js +13 -0
  108. package/lib/esm/index.mjs +15 -0
  109. package/lib/esm/libs/getCoinOjectIdsByAmount.js +61 -0
  110. package/lib/esm/libs/getSplitCoinForTx.js +39 -0
  111. package/lib/esm/libs/groupSwapRoutes.js +58 -0
  112. package/lib/esm/libs/protocols/aftermath/index.js +37 -0
  113. package/lib/esm/libs/protocols/base.js +18 -0
  114. package/lib/esm/libs/protocols/bluemove/index.js +21 -0
  115. package/lib/esm/libs/protocols/cetus/index.js +41 -0
  116. package/lib/esm/libs/protocols/constants.js +2 -0
  117. package/lib/esm/libs/protocols/deepbook/index.js +80 -0
  118. package/lib/esm/libs/protocols/flowx/index.js +16 -0
  119. package/lib/esm/libs/protocols/index.js +18 -0
  120. package/lib/esm/libs/protocols/kriya/index.js +27 -0
  121. package/lib/esm/libs/protocols/suiswap/index.js +30 -0
  122. package/lib/esm/libs/protocols/turbos/constants.js +4 -0
  123. package/lib/esm/libs/protocols/turbos/index.js +38 -0
  124. package/lib/esm/libs/protocols/utils.js +5 -0
  125. package/lib/esm/libs/swapWithRoute.js +17 -0
  126. package/lib/esm/suiClient.js +10 -0
  127. package/lib/esm/types/aggregator.js +1 -0
  128. package/lib/esm/types/buildTx.d.ts +4 -0
  129. package/lib/esm/types/buildTx.d.ts.map +1 -0
  130. package/lib/esm/types/constants/explorer.d.ts +4 -0
  131. package/lib/esm/types/constants/explorer.d.ts.map +1 -0
  132. package/lib/esm/types/constants/tokens.d.ts +3 -0
  133. package/lib/esm/types/constants/tokens.d.ts.map +1 -0
  134. package/lib/esm/types/estimateGasFee.d.ts +3 -0
  135. package/lib/esm/types/estimateGasFee.d.ts.map +1 -0
  136. package/lib/esm/types/getQuote.d.ts +9 -0
  137. package/lib/esm/types/getQuote.d.ts.map +1 -0
  138. package/lib/esm/types/getSuiPrice.d.ts +2 -0
  139. package/lib/esm/types/getSuiPrice.d.ts.map +1 -0
  140. package/lib/esm/types/index.d.ts +17 -0
  141. package/lib/esm/types/index.d.ts.map +1 -0
  142. package/lib/esm/types/libs/getCoinOjectIdsByAmount.d.ts +7 -0
  143. package/lib/esm/types/libs/getCoinOjectIdsByAmount.d.ts.map +1 -0
  144. package/lib/esm/types/libs/getSplitCoinForTx.d.ts +6 -0
  145. package/lib/esm/types/libs/getSplitCoinForTx.d.ts.map +1 -0
  146. package/lib/esm/types/libs/groupSwapRoutes.d.ts +3 -0
  147. package/lib/esm/types/libs/groupSwapRoutes.d.ts.map +1 -0
  148. package/lib/esm/types/libs/protocols/aftermath/index.d.ts +10 -0
  149. package/lib/esm/types/libs/protocols/aftermath/index.d.ts.map +1 -0
  150. package/lib/esm/types/libs/protocols/base.d.ts +37 -0
  151. package/lib/esm/types/libs/protocols/base.d.ts.map +1 -0
  152. package/lib/esm/types/libs/protocols/bluemove/index.d.ts +10 -0
  153. package/lib/esm/types/libs/protocols/bluemove/index.d.ts.map +1 -0
  154. package/lib/esm/types/libs/protocols/cetus/index.d.ts +10 -0
  155. package/lib/esm/types/libs/protocols/cetus/index.d.ts.map +1 -0
  156. package/lib/esm/types/libs/protocols/constants.d.ts +3 -0
  157. package/lib/esm/types/libs/protocols/constants.d.ts.map +1 -0
  158. package/lib/esm/types/libs/protocols/deepbook/index.d.ts +12 -0
  159. package/lib/esm/types/libs/protocols/deepbook/index.d.ts.map +1 -0
  160. package/lib/esm/types/libs/protocols/flowx/index.d.ts +10 -0
  161. package/lib/esm/types/libs/protocols/flowx/index.d.ts.map +1 -0
  162. package/lib/esm/types/libs/protocols/index.d.ts +19 -0
  163. package/lib/esm/types/libs/protocols/index.d.ts.map +1 -0
  164. package/lib/esm/types/libs/protocols/kriya/index.d.ts +10 -0
  165. package/lib/esm/types/libs/protocols/kriya/index.d.ts.map +1 -0
  166. package/lib/esm/types/libs/protocols/suiswap/index.d.ts +10 -0
  167. package/lib/esm/types/libs/protocols/suiswap/index.d.ts.map +1 -0
  168. package/lib/esm/types/libs/protocols/turbos/constants.d.ts +5 -0
  169. package/lib/esm/types/libs/protocols/turbos/constants.d.ts.map +1 -0
  170. package/lib/esm/types/libs/protocols/turbos/index.d.ts +10 -0
  171. package/lib/esm/types/libs/protocols/turbos/index.d.ts.map +1 -0
  172. package/lib/esm/types/libs/protocols/utils.d.ts +3 -0
  173. package/lib/esm/types/libs/protocols/utils.d.ts.map +1 -0
  174. package/lib/esm/types/libs/swapWithRoute.d.ts +10 -0
  175. package/lib/esm/types/libs/swapWithRoute.d.ts.map +1 -0
  176. package/lib/esm/types/sui.js +1 -0
  177. package/lib/esm/types/suiClient.d.ts +4 -0
  178. package/lib/esm/types/suiClient.d.ts.map +1 -0
  179. package/lib/esm/types/token.js +1 -0
  180. package/lib/esm/types/tx.js +1 -0
  181. package/lib/esm/types/types/aggregator.d.ts +69 -0
  182. package/lib/esm/types/types/aggregator.d.ts.map +1 -0
  183. package/lib/esm/types/types/sui.d.ts +4 -0
  184. package/lib/esm/types/types/sui.d.ts.map +1 -0
  185. package/lib/esm/types/types/token.d.ts +30 -0
  186. package/lib/esm/types/types/token.d.ts.map +1 -0
  187. package/lib/esm/types/types/tx.d.ts +14 -0
  188. package/lib/esm/types/types/tx.d.ts.map +1 -0
  189. package/lib/esm/types/types/utilities.d.ts +5 -0
  190. package/lib/esm/types/types/utilities.d.ts.map +1 -0
  191. package/lib/esm/types/utilities.js +1 -0
  192. package/lib/esm/types/utils/number.d.ts +4 -0
  193. package/lib/esm/types/utils/number.d.ts.map +1 -0
  194. package/lib/esm/types/utils/sui.d.ts +39 -0
  195. package/lib/esm/types/utils/sui.d.ts.map +1 -0
  196. package/lib/esm/types/utils/token.d.ts +6 -0
  197. package/lib/esm/types/utils/token.d.ts.map +1 -0
  198. package/lib/esm/utils/number.js +8 -0
  199. package/lib/esm/utils/sui.js +167 -0
  200. package/lib/esm/utils/token.js +19 -0
  201. package/package.json +70 -0
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.normalizeTokenType = normalizeTokenType;
13
+ exports.denormalizeTokenType = denormalizeTokenType;
14
+ exports.checkIsSui = checkIsSui;
15
+ exports.getSuiscanTokenMetadata = getSuiscanTokenMetadata;
16
+ const explorer_1 = require("../constants/explorer");
17
+ const tokens_1 = require("../constants/tokens");
18
+ function normalizeTokenType(type) {
19
+ return type === tokens_1.SUI_TYPE ? tokens_1.SUI_FULL_TYPE : type;
20
+ }
21
+ function denormalizeTokenType(type) {
22
+ return type === tokens_1.SUI_FULL_TYPE ? tokens_1.SUI_TYPE : type;
23
+ }
24
+ function checkIsSui(type) {
25
+ return type === tokens_1.SUI_FULL_TYPE || type === tokens_1.SUI_TYPE;
26
+ }
27
+ function getSuiscanTokenMetadata(type) {
28
+ return __awaiter(this, void 0, void 0, function* () {
29
+ const response = yield fetch(`${explorer_1.EXPLORER.ADDRESS}/api/sui-backend/mainnet/api/coins/${denormalizeTokenType(type)}`);
30
+ if (!response.ok) {
31
+ throw new Error("Failed to fetch token metadata");
32
+ }
33
+ const data = yield response.json();
34
+ return Object.assign(Object.assign({}, data), { type: normalizeTokenType(data.type || "") });
35
+ });
36
+ }
@@ -0,0 +1,77 @@
1
+ import { TransactionBlock, } from "@mysten/sui.js/transactions";
2
+ import BigNumber from "bignumber.js";
3
+ import { getSplitCoinForTx } from "./libs/getSplitCoinForTx";
4
+ import { groupSwapRoutes } from "./libs/groupSwapRoutes";
5
+ import { swapWithRoute } from "./libs/swapWithRoute";
6
+ import { denormalizeTokenType } from "./utils/token";
7
+ import { SuiUtils } from "./utils/sui";
8
+ const _7K_PACKAGE_ID = "0xd48e7cdc9e92bec69ce3baa75578010458a0c5b2733d661a84971e8cef6806bc";
9
+ const _7K_CONFIG = "0xc31272d90e0c36181b0153776c9d7c1516d4c1eca50fc2eb01f36d3f457ea90d";
10
+ export const buildTx = async ({ quoteResponse, accountAddress, slippage, tx: _tx, commission: _commission, }) => {
11
+ if (!accountAddress || !quoteResponse.routes)
12
+ return;
13
+ const tx = _tx || new TransactionBlock();
14
+ const routes = groupSwapRoutes(quoteResponse);
15
+ const splits = routes.map((group) => group[0]?.amount ?? "0");
16
+ const { coinData } = await getSplitCoinForTx(accountAddress, quoteResponse.swapAmountWithDecimal, splits, denormalizeTokenType(quoteResponse.tokenIn), tx);
17
+ const coinObjects = [];
18
+ await Promise.all(routes.map(async (route, index) => {
19
+ const inputCoinObject = coinData[index];
20
+ const coinRes = await swapWithRoute({
21
+ route,
22
+ inputCoinObject,
23
+ currentAccount: accountAddress,
24
+ tx,
25
+ });
26
+ if (coinRes) {
27
+ coinObjects.push(coinRes);
28
+ }
29
+ }));
30
+ if (coinObjects.length > 0) {
31
+ const mergeCoin = coinObjects.length > 1
32
+ ? SuiUtils.mergeCoins(coinObjects, tx)
33
+ : coinObjects[0];
34
+ const minReceived = new BigNumber(1)
35
+ .minus(slippage)
36
+ .multipliedBy(quoteResponse.returnAmountWithDecimal)
37
+ .toFixed(0);
38
+ const commission = getCommission(tx, _commission);
39
+ tx.moveCall({
40
+ target: `${_7K_PACKAGE_ID}::settle::settle`,
41
+ typeArguments: [quoteResponse.tokenIn, quoteResponse.tokenOut],
42
+ arguments: [
43
+ tx.object(_7K_CONFIG),
44
+ tx.pure.u64(quoteResponse.swapAmountWithDecimal),
45
+ mergeCoin,
46
+ tx.pure.u64(minReceived),
47
+ tx.pure.u64(quoteResponse.returnAmountWithDecimal),
48
+ commission,
49
+ ],
50
+ });
51
+ tx.transferObjects([mergeCoin], tx.pure.address(accountAddress));
52
+ }
53
+ return tx;
54
+ };
55
+ const getCommission = (tx, commission) => {
56
+ if (commission) {
57
+ const [commissionInner] = tx.moveCall({
58
+ target: `${_7K_PACKAGE_ID}::commission::new`,
59
+ typeArguments: [],
60
+ arguments: [
61
+ tx.pure.address(commission.partner),
62
+ tx.pure.u64(commission.commissionBps),
63
+ ],
64
+ });
65
+ const [result] = tx.moveCall({
66
+ target: "0x1::option::some",
67
+ typeArguments: [`${_7K_PACKAGE_ID}::commission::Commission`],
68
+ arguments: [commissionInner],
69
+ });
70
+ return result;
71
+ }
72
+ return tx.moveCall({
73
+ target: "0x1::option::none",
74
+ typeArguments: [`${_7K_PACKAGE_ID}::commission::Commission`],
75
+ arguments: [],
76
+ })[0];
77
+ };
@@ -0,0 +1,3 @@
1
+ export const EXPLORER = {
2
+ ADDRESS: `https://suiscan.xyz`,
3
+ };
@@ -0,0 +1,2 @@
1
+ export const SUI_TYPE = "0x2::sui::SUI";
2
+ export const SUI_FULL_TYPE = "0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI";
@@ -0,0 +1,35 @@
1
+ import BigNumber from "bignumber.js";
2
+ import { SUI_DECIMALS } from "@mysten/sui.js/utils";
3
+ import { buildTx } from "./buildTx";
4
+ import { formatBalance } from "./utils/number";
5
+ import { getSuiClient } from "./suiClient";
6
+ import { getSuiPrice } from "./getSuiPrice";
7
+ export async function estimateGasFee({ quoteResponse, accountAddress, slippage, suiPrice: _suiPrice, tx: _tx, commission, }) {
8
+ if (!accountAddress)
9
+ return 0;
10
+ const tx = await buildTx({
11
+ tx: _tx,
12
+ quoteResponse,
13
+ accountAddress,
14
+ slippage,
15
+ commission,
16
+ }).catch((err) => {
17
+ console.log("build tx error: ", err);
18
+ return undefined;
19
+ });
20
+ if (!tx)
21
+ return 0;
22
+ const suiPrice = _suiPrice || (await getSuiPrice());
23
+ const suiDecimals = SUI_DECIMALS;
24
+ const { effects: { gasUsed, status }, } = await getSuiClient().devInspectTransactionBlock({
25
+ sender: accountAddress,
26
+ transactionBlock: tx,
27
+ });
28
+ if (status.status !== "success")
29
+ return 0;
30
+ const fee = new BigNumber(gasUsed.computationCost)
31
+ .plus(gasUsed.storageCost)
32
+ .minus(gasUsed.storageRebate);
33
+ const feeUsd = new BigNumber(suiPrice).multipliedBy(formatBalance(fee, suiDecimals));
34
+ return feeUsd.toNumber();
35
+ }
@@ -0,0 +1,8 @@
1
+ import { normalizeTokenType } from "./utils/token";
2
+ export async function getQuote({ tokenIn, tokenOut, amountIn, }) {
3
+ const response = await fetch(`https://api.7k.ag/quote?amount=${amountIn}&from=${normalizeTokenType(tokenIn)}&to=${normalizeTokenType(tokenOut)}`);
4
+ if (!response.ok) {
5
+ throw new Error("Failed to fetch aggregator sor");
6
+ }
7
+ return response.json();
8
+ }
@@ -0,0 +1,13 @@
1
+ import BigNumber from "bignumber.js";
2
+ import { getSuiscanTokenMetadata } from "./utils/token";
3
+ import { SUI_TYPE } from "./constants/tokens";
4
+ export async function getSuiPrice() {
5
+ try {
6
+ const suiToken = await getSuiscanTokenMetadata(SUI_TYPE);
7
+ const suiPrice = suiToken?.tokenPrice ?? "0";
8
+ return new BigNumber(suiPrice).toNumber();
9
+ }
10
+ catch (error) {
11
+ return 0;
12
+ }
13
+ }
@@ -0,0 +1,15 @@
1
+ export * from "./types/aggregator";
2
+ import { getSuiClient, setSuiClient } from "./suiClient";
3
+ import { getQuote } from "./getQuote";
4
+ import { getSuiPrice } from "./getSuiPrice";
5
+ import { estimateGasFee } from "./estimateGasFee";
6
+ import { buildTx } from "./buildTx";
7
+ export { getSuiClient, setSuiClient, getQuote, getSuiPrice, estimateGasFee, buildTx, };
8
+ export default {
9
+ getSuiClient,
10
+ setSuiClient,
11
+ getQuote,
12
+ getSuiPrice,
13
+ estimateGasFee,
14
+ buildTx,
15
+ };
@@ -0,0 +1,61 @@
1
+ import BigNumber from "bignumber.js";
2
+ import { getSuiClient } from "../suiClient";
3
+ const orderByKey = (array, key, sortBy) => {
4
+ if (!array?.length) {
5
+ return;
6
+ }
7
+ let swapped;
8
+ const compareFunctionName = sortBy === "desc" ? "isLessThan" : "isGreaterThan";
9
+ do {
10
+ swapped = false;
11
+ for (let i = 0; i < array.length - 1; i++) {
12
+ if (new BigNumber(array[i][key])[compareFunctionName](array[i + 1][key])) {
13
+ const temp = array[i];
14
+ array[i] = array[i + 1];
15
+ array[i + 1] = temp;
16
+ swapped = true;
17
+ }
18
+ }
19
+ } while (swapped);
20
+ return array;
21
+ };
22
+ export const getCoinOjectIdsByAmount = async (address, amount, coinType) => {
23
+ let coinBalances = [];
24
+ let hasNextPage = true;
25
+ let nextCursor = undefined;
26
+ while (hasNextPage) {
27
+ try {
28
+ const coins = await getSuiClient().getCoins({
29
+ owner: address,
30
+ coinType,
31
+ cursor: nextCursor,
32
+ });
33
+ coinBalances = [...coinBalances, ...coins.data];
34
+ hasNextPage = coins.hasNextPage;
35
+ nextCursor = coins.nextCursor;
36
+ }
37
+ catch (error) {
38
+ console.error("Error fetching data:", error);
39
+ hasNextPage = false;
40
+ }
41
+ }
42
+ // sort coin balance before get object id
43
+ const coinObj = orderByKey(coinBalances.map((item) => {
44
+ return {
45
+ ...item,
46
+ balance: item.balance,
47
+ };
48
+ }), "balance", "desc");
49
+ let balance = "0";
50
+ const objectIds = [];
51
+ const objectCoins = [];
52
+ for (const coin of coinObj ?? []) {
53
+ balance = new BigNumber(coin.balance).plus(balance).toFixed();
54
+ objectIds.push(coin.coinObjectId);
55
+ objectCoins.push(coin);
56
+ if (new BigNumber(balance).isGreaterThanOrEqualTo(amount)) {
57
+ break;
58
+ }
59
+ }
60
+ return { objectIds, balance, objectCoins };
61
+ };
@@ -0,0 +1,39 @@
1
+ import { TransactionBlock, } from "@mysten/sui.js/transactions";
2
+ import { getCoinOjectIdsByAmount } from "./getCoinOjectIdsByAmount";
3
+ import BigNumber from "bignumber.js";
4
+ import { SUI_TYPE } from "../constants/tokens";
5
+ export const getSplitCoinForTx = async (account, amount, splits, coinType, inheritTx, inspecTransaction) => {
6
+ const tx = inheritTx ?? new TransactionBlock();
7
+ const { objectIds } = await getCoinOjectIdsByAmount(account, amount, coinType);
8
+ const coinObjectId = objectIds[0];
9
+ // TODO: find out why the tx.gas is limited at 950 sui
10
+ if (coinType === SUI_TYPE &&
11
+ new BigNumber(amount).lt(new BigNumber("950e9"))) {
12
+ const pureAmount = [];
13
+ for (const split of splits) {
14
+ pureAmount.push(tx.pure(split));
15
+ }
16
+ let coin;
17
+ if (inspecTransaction) {
18
+ if (objectIds.length > 1) {
19
+ tx.mergeCoins(tx.object(coinObjectId), objectIds.slice(1).map((item) => tx.object(item)));
20
+ }
21
+ coin = tx.splitCoins(tx.object(coinObjectId), pureAmount);
22
+ }
23
+ else {
24
+ coin = tx.splitCoins(tx.gas, pureAmount);
25
+ }
26
+ return { tx, coinData: coin };
27
+ }
28
+ if (objectIds.length > 1) {
29
+ tx.mergeCoins(tx.object(coinObjectId), objectIds.slice(1).map((item) => tx.object(item)));
30
+ }
31
+ //handle split coin
32
+ const pureAmount = [];
33
+ for (const split of splits) {
34
+ pureAmount.push(tx.pure(split));
35
+ }
36
+ // split correct amount to swap
37
+ const coinData = tx.splitCoins(tx.object(coinObjectId), pureAmount);
38
+ return { tx, coinData };
39
+ };
@@ -0,0 +1,58 @@
1
+ import BigNumber from "bignumber.js";
2
+ import { denormalizeTokenType } from "../utils/token";
3
+ export function groupSwapRoutes(quoteResponse) {
4
+ if (!quoteResponse.routes || !quoteResponse.swaps) {
5
+ return [];
6
+ }
7
+ const poolDetails = mapPoolIdsToDetails(quoteResponse.routes);
8
+ const items = getTxSorSwaps(quoteResponse.swaps, poolDetails);
9
+ const groupedItems = [];
10
+ let currentGroup = [];
11
+ for (let i = 0; i < items.length; i++) {
12
+ const item = items[i];
13
+ currentGroup.push(item);
14
+ const nextItem = items[i + 1];
15
+ if (!nextItem || new BigNumber(nextItem.amount).gt(0)) {
16
+ groupedItems.push(currentGroup);
17
+ currentGroup = [];
18
+ }
19
+ }
20
+ if (currentGroup.length > 0) {
21
+ groupedItems.push(currentGroup);
22
+ }
23
+ return groupedItems;
24
+ }
25
+ function mapPoolIdsToDetails(routes) {
26
+ const poolTypes = {};
27
+ routes.forEach((route) => {
28
+ route.hops.forEach((hop) => {
29
+ poolTypes[hop.poolId] = hop.pool;
30
+ });
31
+ });
32
+ return poolTypes;
33
+ }
34
+ function getTxSorSwaps(swaps, poolDetails) {
35
+ return swaps.map((swap) => {
36
+ const pool = poolDetails[swap.poolId];
37
+ const assetIn = denormalizeTokenType(swap.assetIn);
38
+ const assetOut = denormalizeTokenType(swap.assetOut);
39
+ const coinX = {
40
+ type: denormalizeTokenType(pool?.allTokens?.[0]?.address),
41
+ decimals: pool?.allTokens?.[0]?.decimal,
42
+ };
43
+ const coinY = {
44
+ type: denormalizeTokenType(pool?.allTokens?.[1]?.address),
45
+ decimals: pool?.allTokens?.[0]?.decimal,
46
+ };
47
+ const swapXtoY = assetIn === coinX.type;
48
+ return {
49
+ ...swap,
50
+ pool,
51
+ assetIn,
52
+ assetOut,
53
+ coinX,
54
+ coinY,
55
+ swapXtoY,
56
+ };
57
+ });
58
+ }
@@ -0,0 +1,37 @@
1
+ import { BaseContract } from "../base";
2
+ import { normalizeTokenType } from "../../../utils/token";
3
+ const PACKAGE_ID = "0xc4049b2d1cc0f6e017fda8260e4377cecd236bd7f56a54fee120816e72e2e0dd";
4
+ const MODULE_NAME = "swap";
5
+ const POOL_REGISTRY = "0xfcc774493db2c45c79f688f88d28023a3e7d98e4ee9f48bbf5c7990f651577ae";
6
+ const PROTOCOL_FEE_VAULT = "0xf194d9b1bcad972e45a7dd67dd49b3ee1e3357a00a50850c52cd51bb450e13b4";
7
+ const TREASURY = "0x28e499dff5e864a2eafe476269a4f5035f1c16f338da7be18b103499abf271ce";
8
+ const INSURANCE_FUND = "0xf0c40d67b078000e18032334c3325c47b9ec9f3d9ae4128be820d54663d14e3b";
9
+ const REFERRAL_VAULT = "0x35d35b0e5b177593d8c3a801462485572fc30861e6ce96a55af6dc4730709278";
10
+ export class AfterMathContract extends BaseContract {
11
+ async swap(tx) {
12
+ const poolId = this.swapInfo.poolId;
13
+ const returnAmount = this.swapInfo.returnAmount;
14
+ const coinInType = normalizeTokenType(this.swapInfo.assetIn);
15
+ const coinOutType = normalizeTokenType(this.swapInfo.assetOut);
16
+ const inputCoinObject = this.inputCoinObject;
17
+ const [lpCoinType] = this.getTypeParams();
18
+ if (!lpCoinType)
19
+ throw new Error("lpCoinType is not defined");
20
+ const [tokenOut] = tx.moveCall({
21
+ target: `${PACKAGE_ID}::${MODULE_NAME}::swap_exact_in`,
22
+ typeArguments: [lpCoinType, coinInType, coinOutType],
23
+ arguments: [
24
+ tx.object(poolId),
25
+ tx.object(POOL_REGISTRY),
26
+ tx.object(PROTOCOL_FEE_VAULT),
27
+ tx.object(TREASURY),
28
+ tx.object(INSURANCE_FUND),
29
+ tx.object(REFERRAL_VAULT),
30
+ inputCoinObject,
31
+ tx.pure(returnAmount),
32
+ tx.pure.u64("1000000000000000000"), // slippage
33
+ ],
34
+ });
35
+ return tokenOut;
36
+ }
37
+ }
@@ -0,0 +1,18 @@
1
+ import { normalizeStructTag, parseStructTag } from "@mysten/sui.js/utils";
2
+ import { SuiUtils } from "../../utils/sui";
3
+ export class BaseContract {
4
+ swapInfo;
5
+ inputCoinObject;
6
+ currentAccount;
7
+ constructor({ swapInfo, inputCoinObject, currentAccount, }) {
8
+ this.swapInfo = swapInfo;
9
+ this.inputCoinObject = inputCoinObject;
10
+ this.currentAccount = currentAccount;
11
+ }
12
+ getInputCoinValue(tx) {
13
+ return SuiUtils.getCoinValue(this.swapInfo.assetIn, this.inputCoinObject, tx);
14
+ }
15
+ getTypeParams() {
16
+ return parseStructTag(this.swapInfo.extra?.poolStructTag || "").typeParams.map(normalizeStructTag);
17
+ }
18
+ }
@@ -0,0 +1,21 @@
1
+ import { BaseContract } from "../base";
2
+ import { SuiUtils } from "../../../utils/sui";
3
+ const PACKAGE_ID = "0xb24b6789e088b876afabca733bed2299fbc9e2d6369be4d1acfa17d8145454d9";
4
+ const DEX_INFO_ID = "0x3f2d9f724f4a1ce5e71676448dc452be9a6243dac9c5b975a588c8c867066e92";
5
+ export class BluemoveContract extends BaseContract {
6
+ async swap(tx) {
7
+ const [coinOut] = tx.moveCall({
8
+ target: `${PACKAGE_ID}::router::swap_exact_input_`,
9
+ typeArguments: [this.swapInfo.coinX.type, this.swapInfo.coinY.type],
10
+ arguments: [
11
+ SuiUtils.getCoinValue(this.swapInfo.swapXtoY
12
+ ? this.swapInfo.coinX.type
13
+ : this.swapInfo.coinY.type, this.inputCoinObject, tx), // input amount
14
+ this.inputCoinObject, // input coin
15
+ tx.pure.u64(0), // min output amount
16
+ tx.object(DEX_INFO_ID),
17
+ ],
18
+ });
19
+ return coinOut;
20
+ }
21
+ }
@@ -0,0 +1,41 @@
1
+ import { BaseContract } from "../base";
2
+ import { SUI_CLOCK_OBJECT_ID } from "@mysten/sui.js/utils";
3
+ import { getDefaultSqrtPriceLimit } from "../utils";
4
+ import { SuiUtils } from "../../../utils/sui";
5
+ const GLOBAL_CONFIG_ID = "0xdaa46292632c3c4d8f31f23ea0f9b36a28ff3677e9684980e4438403a67a3d8f";
6
+ const INTEGRATE_PACKAGE_ID = "0x6f5e582ede61fe5395b50c4a449ec11479a54d7ff8e0158247adfda60d98970b";
7
+ export class CetusContract extends BaseContract {
8
+ async swap(tx) {
9
+ const sqrtPriceLimit = getDefaultSqrtPriceLimit(this.swapInfo.swapXtoY);
10
+ const typeArguments = [this.swapInfo.coinX.type, this.swapInfo.coinY.type];
11
+ const [zeroOut] = tx.moveCall({
12
+ target: "0x2::coin::zero",
13
+ typeArguments: [
14
+ this.swapInfo.swapXtoY
15
+ ? this.swapInfo.coinY.type
16
+ : this.swapInfo.coinX.type,
17
+ ],
18
+ });
19
+ const amountIn = SuiUtils.getCoinValue(this.swapInfo.swapXtoY
20
+ ? this.swapInfo.coinX.type
21
+ : this.swapInfo.coinY.type, this.inputCoinObject, tx);
22
+ const [receiveA, receiveB] = tx.moveCall({
23
+ target: `${INTEGRATE_PACKAGE_ID}::router::swap`,
24
+ typeArguments,
25
+ arguments: [
26
+ tx.object(GLOBAL_CONFIG_ID),
27
+ tx.object(this.swapInfo.poolId),
28
+ this.swapInfo.swapXtoY ? this.inputCoinObject : zeroOut, // coin A
29
+ this.swapInfo.swapXtoY ? zeroOut : this.inputCoinObject, // coin B
30
+ tx.pure(this.swapInfo.swapXtoY), // a to b or b to a
31
+ tx.pure(true), // exact in or out
32
+ amountIn, // swap amount
33
+ tx.pure.u128(sqrtPriceLimit.toString()), // sqrt price limit
34
+ tx.pure(false),
35
+ tx.object(SUI_CLOCK_OBJECT_ID),
36
+ ],
37
+ });
38
+ tx.transferObjects([this.swapInfo.swapXtoY ? receiveA : receiveB], tx.pure.address(this.currentAccount));
39
+ return this.swapInfo.swapXtoY ? receiveB : receiveA;
40
+ }
41
+ }
@@ -0,0 +1,2 @@
1
+ export const MIN_SQRT_PRICE = "4295048016";
2
+ export const MAX_SQRT_PRICE = "79226673515401279992447579055";
@@ -0,0 +1,80 @@
1
+ import { SUI_CLOCK_OBJECT_ID } from "@mysten/sui.js/utils";
2
+ import { BaseContract } from "../base";
3
+ const PACKAGE_ID = "0xdee9";
4
+ const MODULE_NAME = "clob_v2";
5
+ const _7K_PACKAGE_ID = "0xd48e7cdc9e92bec69ce3baa75578010458a0c5b2733d661a84971e8cef6806bc";
6
+ export class DeepBookContract extends BaseContract {
7
+ async swap(tx) {
8
+ const swapXtoY = this.swapInfo.swapXtoY;
9
+ const poolId = this.swapInfo.poolId;
10
+ const clientOrderId = Date.now();
11
+ const currentAddress = this.currentAccount;
12
+ const typeArgs = this.getTypeParams();
13
+ const lotSize = this.swapInfo.extra?.lotSize;
14
+ const [baseAsset, quoteAsset] = typeArgs;
15
+ const accountCap = this.createAccountCap(tx);
16
+ const amountIn = this.getInputCoinValue(tx);
17
+ let result;
18
+ if (swapXtoY) {
19
+ const amountInRound = tx.moveCall({
20
+ target: `${_7K_PACKAGE_ID}::math::m_round_down`,
21
+ arguments: [
22
+ amountIn, // input coin value
23
+ tx.pure.u64(lotSize), // lot size
24
+ ],
25
+ });
26
+ const [base_coin_ret, quote_coin_ret] = tx.moveCall({
27
+ target: `${PACKAGE_ID}::${MODULE_NAME}::swap_exact_base_for_quote`,
28
+ typeArguments: [baseAsset, quoteAsset],
29
+ arguments: [
30
+ tx.object(poolId),
31
+ tx.pure.u64(clientOrderId),
32
+ accountCap,
33
+ amountInRound,
34
+ this.inputCoinObject, // coin 0 ~ base
35
+ tx.moveCall({
36
+ typeArguments: [quoteAsset],
37
+ target: `0x2::coin::zero`,
38
+ arguments: [],
39
+ }), // coin 1 ~ quote
40
+ tx.object(SUI_CLOCK_OBJECT_ID),
41
+ ],
42
+ });
43
+ this.deleteAccountCap(tx, accountCap);
44
+ tx.transferObjects([base_coin_ret], currentAddress);
45
+ result = quote_coin_ret;
46
+ }
47
+ else {
48
+ const [base_coin_ret, quote_coin_ret] = tx.moveCall({
49
+ target: `${PACKAGE_ID}::${MODULE_NAME}::swap_exact_quote_for_base`,
50
+ typeArguments: [baseAsset, quoteAsset],
51
+ arguments: [
52
+ tx.object(poolId),
53
+ tx.pure.u64(clientOrderId),
54
+ accountCap,
55
+ amountIn,
56
+ tx.object(SUI_CLOCK_OBJECT_ID),
57
+ this.inputCoinObject, // coin 1 ~ quote
58
+ ],
59
+ });
60
+ this.deleteAccountCap(tx, accountCap);
61
+ tx.transferObjects([quote_coin_ret], currentAddress);
62
+ result = base_coin_ret;
63
+ }
64
+ return result;
65
+ }
66
+ createAccountCap(tx) {
67
+ const [cap] = tx.moveCall({
68
+ typeArguments: [],
69
+ target: `${PACKAGE_ID}::${MODULE_NAME}::create_account`,
70
+ arguments: [],
71
+ });
72
+ return cap;
73
+ }
74
+ deleteAccountCap(tx, accountCap) {
75
+ tx.moveCall({
76
+ target: `${PACKAGE_ID}::custodian_v2::delete_account_cap`,
77
+ arguments: [accountCap],
78
+ });
79
+ }
80
+ }
@@ -0,0 +1,16 @@
1
+ import { BaseContract } from "../base";
2
+ const PACKAGE_ID = "0xba153169476e8c3114962261d1edc70de5ad9781b83cc617ecc8c1923191cae0";
3
+ const MODULE_NAME = "router";
4
+ const CONTAINER_OBJECT_ID = "0xb65dcbf63fd3ad5d0ebfbf334780dc9f785eff38a4459e37ab08fa79576ee511";
5
+ export class FlowXContract extends BaseContract {
6
+ async swap(tx) {
7
+ const coinInType = this.swapInfo.assetIn;
8
+ const coinOutType = this.swapInfo.assetOut;
9
+ const [tokenOut] = tx.moveCall({
10
+ target: `${PACKAGE_ID}::${MODULE_NAME}::swap_exact_input_direct`,
11
+ typeArguments: [coinInType, coinOutType],
12
+ arguments: [tx.object(CONTAINER_OBJECT_ID), this.inputCoinObject],
13
+ });
14
+ return tokenOut;
15
+ }
16
+ }
@@ -0,0 +1,18 @@
1
+ import { FlowXContract } from "./flowx";
2
+ import { AfterMathContract } from "./aftermath";
3
+ import { CetusContract } from "./cetus";
4
+ import { DeepBookContract } from "./deepbook";
5
+ import { KriyaContract } from "./kriya";
6
+ import { TurbosContract } from "./turbos";
7
+ import { SuiswapContract } from "./suiswap";
8
+ import { BluemoveContract } from "./bluemove";
9
+ export const ProtocolContract = {
10
+ cetus: CetusContract,
11
+ turbos: TurbosContract,
12
+ bluemove: BluemoveContract,
13
+ kriya: KriyaContract,
14
+ suiswap: SuiswapContract,
15
+ aftermath: AfterMathContract,
16
+ deepbook: DeepBookContract,
17
+ flowx: FlowXContract,
18
+ };
@@ -0,0 +1,27 @@
1
+ import { BaseContract } from "../base";
2
+ import { normalizeTokenType } from "../../../utils/token";
3
+ const PACKAGE_ID = "0xa0eba10b173538c8fecca1dff298e488402cc9ff374f8a12ca7758eebe830b66";
4
+ const MODULE_NAME = "spot_dex";
5
+ export class KriyaContract extends BaseContract {
6
+ async swap(tx) {
7
+ const swapXtoY = this.swapInfo.swapXtoY;
8
+ const coinInType = normalizeTokenType(this.swapInfo.assetIn);
9
+ const coinOutType = normalizeTokenType(this.swapInfo.assetOut);
10
+ const poolId = this.swapInfo.poolId;
11
+ const inputCoinObject = this.inputCoinObject;
12
+ const [tokenOut] = tx.moveCall({
13
+ target: `${PACKAGE_ID}::${MODULE_NAME}::${swapXtoY ? "swap_token_x" : "swap_token_y"}`,
14
+ typeArguments: [
15
+ swapXtoY ? coinInType : coinOutType,
16
+ swapXtoY ? coinOutType : coinInType,
17
+ ],
18
+ arguments: [
19
+ tx.object(poolId),
20
+ inputCoinObject,
21
+ this.getInputCoinValue(tx),
22
+ tx.pure.u64(0),
23
+ ],
24
+ });
25
+ return tokenOut;
26
+ }
27
+ }
@@ -0,0 +1,30 @@
1
+ import { SUI_CLOCK_OBJECT_ID } from "@mysten/sui.js/utils";
2
+ import { BaseContract } from "../base";
3
+ const PACKAGE_ID = "0xd075d51486df71e750872b4edf82ea3409fda397ceecc0b6aedf573d923c54a0";
4
+ const MODULE_NAME = "pool";
5
+ export class SuiswapContract extends BaseContract {
6
+ async swap(tx) {
7
+ const poolId = this.swapInfo.poolId;
8
+ const swapXtoY = this.swapInfo.swapXtoY;
9
+ const inputCoin = this.inputCoinObject;
10
+ const typeArguments = [this.swapInfo.coinX.type, this.swapInfo.coinY.type];
11
+ const callFunc = swapXtoY
12
+ ? "do_swap_x_to_y_direct"
13
+ : "do_swap_y_to_x_direct";
14
+ const inputAmount = this.getInputCoinValue(tx);
15
+ const [tokenIn, tokenOut] = tx.moveCall({
16
+ target: `${PACKAGE_ID}::${MODULE_NAME}::${callFunc}`,
17
+ typeArguments,
18
+ arguments: [
19
+ tx.object(poolId),
20
+ tx.makeMoveVec({
21
+ objects: [inputCoin],
22
+ }),
23
+ inputAmount,
24
+ tx.object(SUI_CLOCK_OBJECT_ID),
25
+ ],
26
+ });
27
+ tx.transferObjects([tokenIn], this.currentAccount);
28
+ return tokenOut;
29
+ }
30
+ }
@@ -0,0 +1,4 @@
1
+ export const MAX_TICK_STEP = 100;
2
+ export const MAX_TICK_INDEX = 443636;
3
+ export const MIN_TICK_INDEX = -443636;
4
+ export const ONE_MINUTE = 60 * 1000;