@cetusprotocol/aggregator-sdk 0.0.0-experimental-20240719182939
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/.env.example +4 -0
- package/README.md +0 -0
- package/bun.lockb +0 -0
- package/dist/index.d.mts +267 -0
- package/dist/index.d.ts +267 -0
- package/dist/index.js +6824 -0
- package/dist/index.mjs +6745 -0
- package/dist/src/client.d.ts +88 -0
- package/dist/src/config.d.ts +26 -0
- package/dist/src/const.d.ts +75 -0
- package/dist/src/errors.d.ts +31 -0
- package/dist/src/index.d.ts +5 -0
- package/dist/src/math.d.ts +5 -0
- package/dist/src/test_data.test.d.ts +8 -0
- package/dist/src/transaction/aftermath.d.ts +24 -0
- package/dist/src/transaction/cetus.d.ts +39 -0
- package/dist/src/transaction/common.d.ts +12 -0
- package/dist/src/transaction/deepbook.d.ts +21 -0
- package/dist/src/transaction/flowx.d.ts +20 -0
- package/dist/src/transaction/index.d.ts +1 -0
- package/dist/src/transaction/kriya.d.ts +21 -0
- package/dist/src/transaction/router.d.ts +6 -0
- package/dist/src/transaction/swap.d.ts +5 -0
- package/dist/src/transaction/turbos.d.ts +22 -0
- package/dist/src/types/CoinAssist.d.ts +122 -0
- package/dist/src/types/sui.d.ts +112 -0
- package/dist/src/utils/account_cap.d.ts +7 -0
- package/dist/src/utils/coin.d.ts +4 -0
- package/dist/src/utils/coin.spec.d.ts +1 -0
- package/dist/src/utils/contracts.d.ts +16 -0
- package/dist/src/utils/index.d.ts +1 -0
- package/dist/src/utils/transaction.d.ts +3 -0
- package/dist/tests/router.test.d.ts +2 -0
- package/dist/tests/wallet.test.d.ts +1 -0
- package/jest.config.mjs +13 -0
- package/package.json +41 -0
- package/src/client.ts +393 -0
- package/src/config.ts +65 -0
- package/src/const.ts +126 -0
- package/src/errors.ts +44 -0
- package/src/index.ts +5 -0
- package/src/math.ts +37 -0
- package/src/test_data.test.ts +17 -0
- package/src/transaction/aftermath.ts +142 -0
- package/src/transaction/cetus.ts +281 -0
- package/src/transaction/common.ts +169 -0
- package/src/transaction/deepbook.ts +126 -0
- package/src/transaction/flowx.ts +97 -0
- package/src/transaction/index.ts +1 -0
- package/src/transaction/kriya.ts +77 -0
- package/src/transaction/router.ts +341 -0
- package/src/transaction/swap.ts +164 -0
- package/src/transaction/turbos.ts +114 -0
- package/src/types/CoinAssist.ts +217 -0
- package/src/types/sui.ts +148 -0
- package/src/utils/account_cap.ts +62 -0
- package/src/utils/coin.spec.ts +10 -0
- package/src/utils/coin.ts +61 -0
- package/src/utils/contracts.ts +136 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/transaction.ts +20 -0
- package/tests/router.test.ts +255 -0
- package/tests/wallet.test.ts +21 -0
- package/tsconfig.json +22 -0
- package/tsup.config.ts +23 -0
- package/version.mjs +28 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { parseTurbosPoolFeeType } from "./coin"
|
|
2
|
+
|
|
3
|
+
describe("Coin Utils", () => {
|
|
4
|
+
it("should fetch token infos by URL and return data", async () => {
|
|
5
|
+
const typeDate =
|
|
6
|
+
"0x91bfbc386a41afcfd9b2533058d7e915a1d3829089cc268ff4333d54d6339ca1::pool::Pool<0xc91acfb75009c5ff2fd57c54f3caaee12ad1fbe997681334adc0b574fc277a07::icorgi::ICORGI, 0x2::sui::SUI, 0x91bfbc386a41afcfd9b2533058d7e915a1d3829089cc268ff4333d54d6339ca1::fee10000bps::FEE10000BPS>"
|
|
7
|
+
const result = parseTurbosPoolFeeType(typeDate)
|
|
8
|
+
console.log("parse turbos pool type", result)
|
|
9
|
+
})
|
|
10
|
+
})
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export function completionCoin(s: string): string {
|
|
2
|
+
const index = s.indexOf("::")
|
|
3
|
+
if (index === -1) {
|
|
4
|
+
return s
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const prefix = s.substring(0, index)
|
|
8
|
+
const rest = s.substring(index)
|
|
9
|
+
|
|
10
|
+
if (!prefix.startsWith("0x")) {
|
|
11
|
+
return s
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const hexStr = prefix.substring(2)
|
|
15
|
+
|
|
16
|
+
if (hexStr.length > 64) {
|
|
17
|
+
return s
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const paddedHexStr = hexStr.padStart(64, "0")
|
|
21
|
+
|
|
22
|
+
return `0x${paddedHexStr}${rest}`
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function compareCoins(coinA: string, coinB: string): boolean {
|
|
26
|
+
coinA = completionCoin(coinA)
|
|
27
|
+
coinB = completionCoin(coinB)
|
|
28
|
+
const minLength = Math.min(coinA.length, coinB.length)
|
|
29
|
+
|
|
30
|
+
for (let i = 0; i < minLength; i++) {
|
|
31
|
+
if (coinA[i] > coinB[i]) {
|
|
32
|
+
return true
|
|
33
|
+
} else if (coinA[i] < coinB[i]) {
|
|
34
|
+
return false
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// If both strings are the same length and all characters are equal
|
|
39
|
+
return true // or coinB, they are equal
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function parseTurbosPoolFeeType(typeData: string) {
|
|
43
|
+
// "0x91bfbc386a41afcfd9b2533058d7e915a1d3829089cc268ff4333d54d6339ca1::pool::Pool<0xc91acfb75009c5ff2fd57c54f3caaee12ad1fbe997681334adc0b574fc277a07::icorgi::ICORGI, 0x2::sui::SUI, 0x91bfbc386a41afcfd9b2533058d7e915a1d3829089cc268ff4333d54d6339ca1::fee10000bps::FEE10000BPS>"
|
|
44
|
+
const regex = /,([^,>]*>)/g
|
|
45
|
+
const matches = [...typeData.matchAll(regex)]
|
|
46
|
+
if (matches.length > 0) {
|
|
47
|
+
const lastMatch = matches[matches.length - 1][1]
|
|
48
|
+
return lastMatch.substring(0, lastMatch.length - 1).trim()
|
|
49
|
+
}
|
|
50
|
+
return null
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function parseAftermathFeeType(typeData: string) {
|
|
54
|
+
// 0xefe170ec0be4d762196bedecd7a065816576198a6527c99282a2551aaa7da38c::pool::Pool<0xf66c5ba62888cd0694677bbfbd2332d08ead3b8a4332c40006c474e83b1a6786::af_lp::AF_LP>
|
|
55
|
+
// get 0xf66c5ba62888cd0694677bbfbd2332d08ead3b8a4332c40006c474e83b1a6786::af_lp::AF_LP
|
|
56
|
+
const regex = /<([^>]*)>/
|
|
57
|
+
const matches = typeData.match(regex)
|
|
58
|
+
if (matches) {
|
|
59
|
+
return matches[1]
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { normalizeSuiObjectId } from '@mysten/sui/utils'
|
|
2
|
+
import type { SuiAddress, SuiStructTag } from '../types/sui'
|
|
3
|
+
import { CoinUtils, GAS_TYPE_ARG, GAS_TYPE_ARG_LONG } from '../types/CoinAssist'
|
|
4
|
+
|
|
5
|
+
const EQUAL = 0
|
|
6
|
+
const LESS_THAN = 1
|
|
7
|
+
const GREATER_THAN = 2
|
|
8
|
+
|
|
9
|
+
function cmp(a: number, b: number) {
|
|
10
|
+
if (a === b) {
|
|
11
|
+
return EQUAL
|
|
12
|
+
}
|
|
13
|
+
if (a < b) {
|
|
14
|
+
return LESS_THAN
|
|
15
|
+
}
|
|
16
|
+
return GREATER_THAN
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function compare(symbolX: string, symbolY: string) {
|
|
20
|
+
let i = 0
|
|
21
|
+
|
|
22
|
+
const len = symbolX.length <= symbolY.length ? symbolX.length : symbolY.length
|
|
23
|
+
|
|
24
|
+
const lenCmp = cmp(symbolX.length, symbolY.length)
|
|
25
|
+
while (i < len) {
|
|
26
|
+
const elemCmp = cmp(symbolX.charCodeAt(i), symbolY.charCodeAt(i))
|
|
27
|
+
i += 1
|
|
28
|
+
if (elemCmp !== 0) {
|
|
29
|
+
return elemCmp
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return lenCmp
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function isSortedSymbols(symbolX: string, symbolY: string) {
|
|
37
|
+
return compare(symbolX, symbolY) === LESS_THAN
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function composeType(address: string, generics: SuiAddress[]): SuiAddress
|
|
41
|
+
export function composeType(address: string, struct: string, generics?: SuiAddress[]): SuiAddress
|
|
42
|
+
export function composeType(address: string, module: string, struct: string, generics?: SuiAddress[]): SuiAddress
|
|
43
|
+
export function composeType(address: string, ...args: unknown[]): SuiAddress {
|
|
44
|
+
const generics: string[] = Array.isArray(args[args.length - 1]) ? (args.pop() as string[]) : []
|
|
45
|
+
const chains = [address, ...args].filter(Boolean)
|
|
46
|
+
|
|
47
|
+
let result: string = chains.join('::')
|
|
48
|
+
|
|
49
|
+
if (generics && generics.length) {
|
|
50
|
+
result += `<${generics.join(', ')}>`
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return result
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function extractAddressFromType(type: string) {
|
|
57
|
+
return type.split('::')[0]
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function extractStructTagFromType(type: string): SuiStructTag {
|
|
61
|
+
try {
|
|
62
|
+
let _type = type.replace(/\s/g, '')
|
|
63
|
+
|
|
64
|
+
const genericsString = _type.match(/(<.+>)$/)
|
|
65
|
+
const generics = genericsString?.[0]?.match(/(\w+::\w+::\w+)(?:<.*?>(?!>))?/g)
|
|
66
|
+
if (generics) {
|
|
67
|
+
_type = _type.slice(0, _type.indexOf('<'))
|
|
68
|
+
const tag = extractStructTagFromType(_type)
|
|
69
|
+
const structTag: SuiStructTag = {
|
|
70
|
+
...tag,
|
|
71
|
+
type_arguments: generics.map((item) => extractStructTagFromType(item).source_address),
|
|
72
|
+
}
|
|
73
|
+
structTag.type_arguments = structTag.type_arguments.map((item) => {
|
|
74
|
+
return CoinUtils.isSuiCoin(item) ? item : extractStructTagFromType(item).source_address
|
|
75
|
+
})
|
|
76
|
+
structTag.source_address = composeType(structTag.full_address, structTag.type_arguments)
|
|
77
|
+
return structTag
|
|
78
|
+
}
|
|
79
|
+
const parts = _type.split('::')
|
|
80
|
+
|
|
81
|
+
const isSuiCoin = _type === GAS_TYPE_ARG || _type === GAS_TYPE_ARG_LONG
|
|
82
|
+
|
|
83
|
+
const structTag: SuiStructTag = {
|
|
84
|
+
full_address: _type,
|
|
85
|
+
address: isSuiCoin ? '0x2' : normalizeSuiObjectId(parts[0]),
|
|
86
|
+
module: parts[1],
|
|
87
|
+
name: parts[2],
|
|
88
|
+
type_arguments: [],
|
|
89
|
+
source_address: '',
|
|
90
|
+
}
|
|
91
|
+
structTag.full_address = `${structTag.address}::${structTag.module}::${structTag.name}`
|
|
92
|
+
structTag.source_address = composeType(structTag.full_address, structTag.type_arguments)
|
|
93
|
+
return structTag
|
|
94
|
+
} catch (error) {
|
|
95
|
+
return {
|
|
96
|
+
full_address: type,
|
|
97
|
+
address: '',
|
|
98
|
+
module: '',
|
|
99
|
+
name: '',
|
|
100
|
+
type_arguments: [],
|
|
101
|
+
source_address: type,
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function normalizeCoinType(coinType: string): string {
|
|
107
|
+
return extractStructTagFromType(coinType).source_address
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function fixSuiObjectId(value: string): string {
|
|
111
|
+
if (value.toLowerCase().startsWith('0x')) {
|
|
112
|
+
return normalizeSuiObjectId(value)
|
|
113
|
+
}
|
|
114
|
+
return value
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Recursively traverses the given data object and patches any string values that represent Sui object IDs.
|
|
119
|
+
*
|
|
120
|
+
* @param {any} data - The data object to be patched.
|
|
121
|
+
*/
|
|
122
|
+
export function patchFixSuiObjectId(data: any) {
|
|
123
|
+
for (const key in data) {
|
|
124
|
+
const type = typeof data[key]
|
|
125
|
+
if (type === 'object') {
|
|
126
|
+
patchFixSuiObjectId(data[key])
|
|
127
|
+
} else if (type === 'string') {
|
|
128
|
+
const value = data[key]
|
|
129
|
+
data[key] = fixSuiObjectId(value)
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export function createTarget(packageName: string, moduleName: string, functionName: string): `${string}::${string}::${string}` {
|
|
135
|
+
return `${packageName}::${moduleName}::${functionName}`
|
|
136
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './contracts'
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Transaction } from "@mysten/sui/transactions"
|
|
2
|
+
|
|
3
|
+
export async function printTransaction(tx: Transaction, isPrint = true) {
|
|
4
|
+
console.log(`inputs`, tx.getData().inputs)
|
|
5
|
+
let i = 0
|
|
6
|
+
|
|
7
|
+
tx.getData().commands.forEach((item, index) => {
|
|
8
|
+
if (isPrint && i < 15) {
|
|
9
|
+
console.log(`transaction ${index}: `, JSON.stringify(item, null, 2))
|
|
10
|
+
i++
|
|
11
|
+
}
|
|
12
|
+
})
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function checkInvalidSuiAddress(address: string): boolean {
|
|
16
|
+
if (!address.startsWith("0x") || address.length !== 66) {
|
|
17
|
+
return false
|
|
18
|
+
}
|
|
19
|
+
return true
|
|
20
|
+
}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { describe, expect, test } from "@jest/globals"
|
|
2
|
+
import dotenv from "dotenv"
|
|
3
|
+
import { AggregatorClient } from "~/client"
|
|
4
|
+
import { AggregatorConfig, ENV } from "~/config"
|
|
5
|
+
import {
|
|
6
|
+
M_CETUS,
|
|
7
|
+
M_HASUI,
|
|
8
|
+
M_NAVI,
|
|
9
|
+
M_SUI,
|
|
10
|
+
M_USDC,
|
|
11
|
+
M_VAPOR,
|
|
12
|
+
M_VSUI,
|
|
13
|
+
} from "../src/test_data.test"
|
|
14
|
+
import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519"
|
|
15
|
+
import { printTransaction } from "~/utils/transaction"
|
|
16
|
+
import BN from "bn.js"
|
|
17
|
+
import { fromHEX } from "@mysten/bcs"
|
|
18
|
+
|
|
19
|
+
dotenv.config()
|
|
20
|
+
|
|
21
|
+
export function buildTestAccount(): Ed25519Keypair {
|
|
22
|
+
const mnemonics = process.env.SUI_WALLET_MNEMONICS || ""
|
|
23
|
+
const testAccountObject = Ed25519Keypair.deriveKeypair(mnemonics)
|
|
24
|
+
return testAccountObject
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
describe("router module", () => {
|
|
28
|
+
let config: AggregatorConfig
|
|
29
|
+
let client: AggregatorClient
|
|
30
|
+
let keypair: Ed25519Keypair
|
|
31
|
+
|
|
32
|
+
beforeAll(() => {
|
|
33
|
+
const fullNodeURL = process.env.SUI_RPC!
|
|
34
|
+
const aggregatorURL = process.env.CETUS_AGGREGATOR!
|
|
35
|
+
const secret = process.env.SUI_WALLET_SECRET!
|
|
36
|
+
|
|
37
|
+
// const byte = Buffer.from(secret, "hex")
|
|
38
|
+
const byte = Buffer.from(secret, "base64")
|
|
39
|
+
const u8Array = new Uint8Array(byte)
|
|
40
|
+
// keypair = secret
|
|
41
|
+
// ? Ed25519Keypair.fromSecretKey(u8Array.slice(1, 33))
|
|
42
|
+
// : buildTestAccount()
|
|
43
|
+
|
|
44
|
+
keypair = Ed25519Keypair.fromSecretKey(fromHEX(secret))
|
|
45
|
+
|
|
46
|
+
const wallet = keypair.getPublicKey().toSuiAddress()
|
|
47
|
+
console.log("wallet", wallet)
|
|
48
|
+
// const wallet =
|
|
49
|
+
// "0x1d30e55c730f92a02a33dbdf6b052cd178e5d924aa58c5e2350a24852250ae58"
|
|
50
|
+
// const wallet = "0xaabf2fedcb36146db164bec930b74a47969c4df98216e049342a3c49b6d11580"
|
|
51
|
+
// const wallet = "0x410456cfc689666936b6bf80fbec958b69499b9f7183ecba07de577c17248a44"
|
|
52
|
+
// const wallet = "0xca171941521153181ff729d53489eaae7e99c3f4692884afd7cca61154e4cec4"
|
|
53
|
+
// console.log("wallet: ", wallet)
|
|
54
|
+
|
|
55
|
+
const aggregatorPackage = {
|
|
56
|
+
packageName: "aggregator",
|
|
57
|
+
packageId:
|
|
58
|
+
"0x640d44dbdc0ede165c7cc417d7f57f1b09648083109de7132c6b3fb15861f5ee",
|
|
59
|
+
publishedAt:
|
|
60
|
+
"0x640d44dbdc0ede165c7cc417d7f57f1b09648083109de7132c6b3fb15861f5ee",
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const integratePackage = {
|
|
64
|
+
packageName: "integrate",
|
|
65
|
+
packageId:
|
|
66
|
+
"0x996c4d9480708fb8b92aa7acf819fb0497b5ec8e65ba06601cae2fb6db3312c3",
|
|
67
|
+
publishedAt:
|
|
68
|
+
"0x8faab90228e4c4df91c41626bbaefa19fc25c514405ac64de54578dec9e6f5ee",
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
config = new AggregatorConfig(
|
|
72
|
+
aggregatorURL,
|
|
73
|
+
fullNodeURL,
|
|
74
|
+
wallet,
|
|
75
|
+
[aggregatorPackage, integratePackage],
|
|
76
|
+
ENV.MAINNET
|
|
77
|
+
)
|
|
78
|
+
client = new AggregatorClient(config)
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
test("Init aggregator client", () => {
|
|
82
|
+
expect(config.getAggregatorUrl().length > 0).toBe(true)
|
|
83
|
+
expect(config.getWallet().length > 0).toBe(true)
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
test("Get all coins", () => {
|
|
87
|
+
return client.getAllCoins().then((coins) => {
|
|
88
|
+
console.log(coins)
|
|
89
|
+
})
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
test("Downgrade swap in route", async () => {
|
|
93
|
+
const amount = 1000000
|
|
94
|
+
|
|
95
|
+
const res = await client.swapInPools({
|
|
96
|
+
from: M_NAVI,
|
|
97
|
+
target: M_SUI,
|
|
98
|
+
amount: new BN(amount),
|
|
99
|
+
byAmountIn: false,
|
|
100
|
+
pools: [
|
|
101
|
+
"0x0254747f5ca059a1972cd7f6016485d51392a3fde608107b93bbaebea550f703",
|
|
102
|
+
],
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
if (res != null) {
|
|
106
|
+
console.log(JSON.stringify(res, null, 2))
|
|
107
|
+
}
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
test("Find router", async () => {
|
|
111
|
+
const amount = "10000000000000000"
|
|
112
|
+
|
|
113
|
+
const res = await client.findRouter({
|
|
114
|
+
from: M_SUI,
|
|
115
|
+
target: M_USDC,
|
|
116
|
+
amount: new BN(amount),
|
|
117
|
+
byAmountIn: true,
|
|
118
|
+
depth: 1,
|
|
119
|
+
splitAlgorithm: null,
|
|
120
|
+
splitFactor: null,
|
|
121
|
+
splitCount: 1,
|
|
122
|
+
providers: [
|
|
123
|
+
// "AFTERMATH",
|
|
124
|
+
// "CETUS",
|
|
125
|
+
"DEEPBOOK",
|
|
126
|
+
// "KRIYA",
|
|
127
|
+
// "FLOWX",
|
|
128
|
+
// "AFTERMATH",
|
|
129
|
+
// "TRUBOS",
|
|
130
|
+
],
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
if (res != null) {
|
|
134
|
+
console.log(JSON.stringify(res, null, 2))
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
console.log("amount in", res?.amountIn.toString())
|
|
138
|
+
console.log("amount out", res?.amountOut.toString())
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
test("Build router tx", async () => {
|
|
142
|
+
const byAmountIn = true
|
|
143
|
+
const amount = 500000000
|
|
144
|
+
|
|
145
|
+
const from = M_SUI
|
|
146
|
+
const target = M_NAVI
|
|
147
|
+
|
|
148
|
+
const res = await client.findRouter({
|
|
149
|
+
from,
|
|
150
|
+
target,
|
|
151
|
+
amount: new BN(amount),
|
|
152
|
+
byAmountIn,
|
|
153
|
+
depth: 3,
|
|
154
|
+
splitAlgorithm: null,
|
|
155
|
+
splitFactor: null,
|
|
156
|
+
splitCount: null,
|
|
157
|
+
providers: ["CETUS", "DEEPBOOK", "KRIYA", "FLOWX", "AFTERMATH", "TURBOS"],
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
if (res != null) {
|
|
161
|
+
console.log(JSON.stringify(res, null, 2))
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
console.log("amount in", res?.amountIn.toString())
|
|
165
|
+
console.log("amount out", res?.amountOut.toString())
|
|
166
|
+
|
|
167
|
+
if (res != null) {
|
|
168
|
+
console.log(JSON.stringify(res, null, 2))
|
|
169
|
+
const routerTx = await client.routerSwap({
|
|
170
|
+
routers: res.routes,
|
|
171
|
+
amountIn: res.amountIn,
|
|
172
|
+
amountOut: res.amountOut,
|
|
173
|
+
byAmountIn,
|
|
174
|
+
slippage: 0.01,
|
|
175
|
+
fromCoinType: from,
|
|
176
|
+
targetCoinType: target,
|
|
177
|
+
partner: undefined,
|
|
178
|
+
isMergeTragetCoin: true,
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
printTransaction(routerTx)
|
|
182
|
+
|
|
183
|
+
let result = await client.devInspectTransactionBlock(routerTx, keypair)
|
|
184
|
+
|
|
185
|
+
if (result.effects.status.status === "success") {
|
|
186
|
+
console.log("Sim exec transaction success")
|
|
187
|
+
// const result = await client.signAndExecuteTransaction(routerTx, keypair)
|
|
188
|
+
// console.log("result", result)
|
|
189
|
+
} else {
|
|
190
|
+
console.log("result", result)
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}, 600000)
|
|
194
|
+
|
|
195
|
+
test("Test Multi Input", async () => {
|
|
196
|
+
const amounts = [1000000000, 2000000000, 10000000000000]
|
|
197
|
+
const froms = [M_USDC, M_SUI, M_CETUS, M_NAVI]
|
|
198
|
+
const tos = [M_SUI, M_USDC, M_USDC, M_SUI]
|
|
199
|
+
|
|
200
|
+
for (let i = 0; i < froms.length; i++) {
|
|
201
|
+
const from = froms[i]
|
|
202
|
+
const target = tos[i]
|
|
203
|
+
for (const amount of amounts) {
|
|
204
|
+
for (const byAmountIn of [true, false]) {
|
|
205
|
+
console.log({
|
|
206
|
+
from,
|
|
207
|
+
target,
|
|
208
|
+
amount,
|
|
209
|
+
byAmountIn,
|
|
210
|
+
})
|
|
211
|
+
const res = await client.findRouter({
|
|
212
|
+
from,
|
|
213
|
+
target,
|
|
214
|
+
amount: new BN(amount),
|
|
215
|
+
byAmountIn,
|
|
216
|
+
depth: null,
|
|
217
|
+
splitAlgorithm: null,
|
|
218
|
+
splitFactor: null,
|
|
219
|
+
splitCount: null,
|
|
220
|
+
providers: null,
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
if (res != null) {
|
|
224
|
+
const routerTx = await client.routerSwap({
|
|
225
|
+
routers: res.routes,
|
|
226
|
+
amountIn: res.amountIn,
|
|
227
|
+
amountOut: res.amountOut,
|
|
228
|
+
byAmountIn,
|
|
229
|
+
slippage: 0.01,
|
|
230
|
+
fromCoinType: from,
|
|
231
|
+
targetCoinType: target,
|
|
232
|
+
partner: undefined,
|
|
233
|
+
isMergeTragetCoin: false,
|
|
234
|
+
})
|
|
235
|
+
|
|
236
|
+
let result = await client.devInspectTransactionBlock(
|
|
237
|
+
routerTx,
|
|
238
|
+
keypair
|
|
239
|
+
)
|
|
240
|
+
// console.log('result', result)
|
|
241
|
+
|
|
242
|
+
if (result.effects.status.status === "success") {
|
|
243
|
+
console.log("Sim exec transaction success")
|
|
244
|
+
// const result = await client.signAndExecuteTransaction(routerTx, keypair)
|
|
245
|
+
// console.log('result', result)
|
|
246
|
+
} else {
|
|
247
|
+
console.log("Sim exec transaction failed")
|
|
248
|
+
// console.log('result', result)
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}, 60000000)
|
|
255
|
+
})
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519"
|
|
2
|
+
|
|
3
|
+
describe("router module", () => {
|
|
4
|
+
const keystoreSecret = [
|
|
5
|
+
"0xd36441c734b1967dd4e65956d0b3e7e5dccc8c92306ad71419e6741b4a7ce6c9",
|
|
6
|
+
]
|
|
7
|
+
|
|
8
|
+
test("Parse public key", () => {
|
|
9
|
+
for (const secret of keystoreSecret) {
|
|
10
|
+
const byte = Buffer.from(secret, "base64")
|
|
11
|
+
const u8Array = new Uint8Array(byte)
|
|
12
|
+
const keypair = Ed25519Keypair.fromSecretKey(u8Array.slice(1, 33))
|
|
13
|
+
console.log(
|
|
14
|
+
"\nsecret:",
|
|
15
|
+
secret,
|
|
16
|
+
"\nkeypair public key: ",
|
|
17
|
+
keypair.toSuiAddress()
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
})
|
|
21
|
+
})
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// tsconfig.json
|
|
2
|
+
{
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"target": "es6",
|
|
5
|
+
"module": "commonjs",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"esModuleInterop": true,
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
"rootDir": "./",
|
|
10
|
+
"baseUrl": ".",
|
|
11
|
+
"paths": {
|
|
12
|
+
"~/*": ["src/*"]
|
|
13
|
+
},
|
|
14
|
+
"allowJs": true,
|
|
15
|
+
"outDir": "dist/",
|
|
16
|
+
},
|
|
17
|
+
"include": ["src", "tests"],
|
|
18
|
+
"exclude": [
|
|
19
|
+
"node_modules/**/*",
|
|
20
|
+
"dist/**/*",
|
|
21
|
+
],
|
|
22
|
+
}
|
package/tsup.config.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { defineConfig } from 'tsup'
|
|
2
|
+
import { exec } from 'child_process'
|
|
3
|
+
|
|
4
|
+
export default defineConfig((options) => ({
|
|
5
|
+
entry: {
|
|
6
|
+
index: './src/index.ts',
|
|
7
|
+
},
|
|
8
|
+
format: ['esm', 'cjs'],
|
|
9
|
+
dts: false,
|
|
10
|
+
clean: !options.watch,
|
|
11
|
+
treeshake: true,
|
|
12
|
+
splitting: true,
|
|
13
|
+
onSuccess: async () => {
|
|
14
|
+
exec('tsc --emitDeclarationOnly --declaration', (err, stdout) => {
|
|
15
|
+
if (err) {
|
|
16
|
+
console.error(stdout)
|
|
17
|
+
if (!options.watch) {
|
|
18
|
+
process.exit(1)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
})
|
|
22
|
+
},
|
|
23
|
+
}))
|
package/version.mjs
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Don't sync to github
|
|
2
|
+
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
|
|
5
|
+
const packageJsonPath = './package.json';
|
|
6
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
7
|
+
|
|
8
|
+
const newVersion = `0.0.0-experimental-${getCurrentDateTimeString()}`;
|
|
9
|
+
packageJson.version = newVersion;
|
|
10
|
+
|
|
11
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2), 'utf-8');
|
|
12
|
+
|
|
13
|
+
console.log(`Version updated to ${newVersion}`);
|
|
14
|
+
|
|
15
|
+
function getCurrentDateTimeString() {
|
|
16
|
+
const now = new Date();
|
|
17
|
+
|
|
18
|
+
const year = now.getFullYear();
|
|
19
|
+
const month = String(now.getMonth() + 1).padStart(2, '0');
|
|
20
|
+
const day = String(now.getDate()).padStart(2, '0');
|
|
21
|
+
const hours = String(now.getHours()).padStart(2, '0');
|
|
22
|
+
const minutes = String(now.getMinutes()).padStart(2, '0');
|
|
23
|
+
const seconds = String(now.getSeconds()).padStart(2, '0');
|
|
24
|
+
|
|
25
|
+
const dateTimeString = `${year}${month}${day}${hours}${minutes}${seconds}`;
|
|
26
|
+
|
|
27
|
+
return dateTimeString;
|
|
28
|
+
}
|