diff --git a/.changeset/strange-countries-serve.md b/.changeset/strange-countries-serve.md new file mode 100644 index 0000000..843d5dc --- /dev/null +++ b/.changeset/strange-countries-serve.md @@ -0,0 +1,5 @@ +--- +"@thalalabs/router-sdk": major +--- + +Support multi-chains diff --git a/packages/thalaswap-router/README.md b/packages/thalaswap-router/README.md index a07c16a..fd89d61 100644 --- a/packages/thalaswap-router/README.md +++ b/packages/thalaswap-router/README.md @@ -11,7 +11,11 @@ $ npm i @thalalabs/router-sdk ## Examples ``` -const router = new ThalaswapRouter("https://fullnode.mainnet.aptoslabs.com/v1"); +const router = new ThalaswapRouter( + Network.MAINNET, + "https://fullnode.mainnet.aptoslabs.com/v1", + "0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af" +); const fromToken = "0x1::aptos_coin::AptosCoin"; const toToken = "0xec84c05cc40950c86d8a8bed19552f1e8ebb783196bb021c916161d22dc179f7::asset::USDC"; const amountIn = 0.1; diff --git a/packages/thalaswap-router/examples/examples.ts b/packages/thalaswap-router/examples/examples.ts index 85bfe75..20e853e 100644 --- a/packages/thalaswap-router/examples/examples.ts +++ b/packages/thalaswap-router/examples/examples.ts @@ -21,7 +21,11 @@ const account = Account.fromPrivateKey({ privateKey: new Ed25519PrivateKey(privateKey), }); -const router = new ThalaswapRouter("https://fullnode.mainnet.aptoslabs.com/v1"); +const router = new ThalaswapRouter( + Network.MAINNET, + "https://fullnode.mainnet.aptoslabs.com/v1", + "0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af", +); // Example 1: Exact input. 1 hop async function example1() { diff --git a/packages/thalaswap-router/src/PoolDataClient.ts b/packages/thalaswap-router/src/PoolDataClient.ts index a8dfd33..341588d 100644 --- a/packages/thalaswap-router/src/PoolDataClient.ts +++ b/packages/thalaswap-router/src/PoolDataClient.ts @@ -1,6 +1,5 @@ import { Coin, Pool, PoolData } from "./types"; import { Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk"; -import { THALASWAP_RESOURCE_ACCOUNT_ADDRESS } from "./constants"; import { uniq } from "lodash"; import { fp64ToFloat, parsePoolMetadata, scaleDown } from "./utils"; @@ -11,12 +10,15 @@ class PoolDataClient { private retryLimit = 3; private client: Aptos; private coins: Coin[] = []; + private resourceAddress: string; + + constructor(network: Network, fullnode: string, resourceAddress: string) { + this.resourceAddress = resourceAddress; - constructor(aptosRpc: string) { this.client = new Aptos( new AptosConfig({ - network: Network.MAINNET, - fullnode: aptosRpc, + network: network, + fullnode: fullnode, }), ); } @@ -27,16 +29,16 @@ class PoolDataClient { for (let i = 0; i < this.retryLimit; i++) { try { const resources = await this.client.getAccountResources({ - accountAddress: THALASWAP_RESOURCE_ACCOUNT_ADDRESS, + accountAddress: this.resourceAddress, }); const poolResources = resources.filter( (r) => r.type.startsWith( - `${THALASWAP_RESOURCE_ACCOUNT_ADDRESS}::weighted_pool::WeightedPool<`, + `${this.resourceAddress}::weighted_pool::WeightedPool<`, ) || r.type.startsWith( - `${THALASWAP_RESOURCE_ACCOUNT_ADDRESS}::stable_pool::StablePool<`, + `${this.resourceAddress}::stable_pool::StablePool<`, ), ) as { type: string; @@ -52,7 +54,10 @@ class PoolDataClient { const allCoinAddress = uniq( poolResources.reduce((acc, resource) => { - const metadata = parsePoolMetadata(resource.type); + const metadata = parsePoolMetadata( + resource.type, + this.resourceAddress, + ); metadata.coinAddresses.forEach((coin) => { coin && acc.push(coin); }); @@ -83,7 +88,10 @@ class PoolDataClient { const pools = poolResources.reduce((acc, resource) => { try { - const metadata = parsePoolMetadata(resource.type); + const metadata = parsePoolMetadata( + resource.type, + this.resourceAddress, + ); const [coin0, coin1, coin2, coin3] = metadata.coinAddresses.map( (addr) => this.coins.find((c) => c.address === addr), ); diff --git a/packages/thalaswap-router/src/ThalaswapRouter.ts b/packages/thalaswap-router/src/ThalaswapRouter.ts index 5c382b9..ebea43d 100644 --- a/packages/thalaswap-router/src/ThalaswapRouter.ts +++ b/packages/thalaswap-router/src/ThalaswapRouter.ts @@ -13,6 +13,7 @@ import { EntryPayload, createEntryPayload } from "@thalalabs/surf"; import { STABLE_POOL_SCRIPTS_ABI } from "./abi/stable_pool_scripts"; import { WEIGHTED_POOL_SCRIPTS_ABI } from "./abi/weighted_pool_scripts"; import { MULTIHOP_ROUTER_ABI } from "./abi/multihop_router"; +import { Network } from "@aptos-labs/ts-sdk"; const NULL_TYPE = `${STABLE_POOL_SCRIPTS_ABI.address}::base_pool::Null`; const NULL_4 = Array(4).fill(NULL_TYPE); @@ -62,8 +63,8 @@ class ThalaswapRouter { private graph: Graph | null = null; private coins: Coin[] | null = null; - constructor(dataURL: string) { - this.client = new PoolDataClient(dataURL); + constructor(network: Network, fullnode: string, resourceAddress: string) { + this.client = new PoolDataClient(network, fullnode, resourceAddress); } setPoolDataClient(client: PoolDataClient) { diff --git a/packages/thalaswap-router/src/constants.ts b/packages/thalaswap-router/src/constants.ts deleted file mode 100644 index dc9252b..0000000 --- a/packages/thalaswap-router/src/constants.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const THALASWAP_RESOURCE_ACCOUNT_ADDRESS = - "0x48271d39d0b05bd6efca2278f22277d6fcc375504f9839fd73f74ace240861af" as const; diff --git a/packages/thalaswap-router/src/utils.ts b/packages/thalaswap-router/src/utils.ts index 89d0aa2..bbc10f8 100644 --- a/packages/thalaswap-router/src/utils.ts +++ b/packages/thalaswap-router/src/utils.ts @@ -1,5 +1,4 @@ import BigNumber from "bignumber.js"; -import { THALASWAP_RESOURCE_ACCOUNT_ADDRESS } from "./constants"; import { LiquidityPoolMetadata } from "./types"; export const BN_TEN = new BigNumber(10); @@ -10,8 +9,16 @@ export function scaleDown(v: number | string, decimals: number): number { .toNumber(); } -export function parsePoolMetadata(poolType: string): LiquidityPoolMetadata { - const [liquidityPoolType, poolTypeArgs] = parseLiquidityPoolType(poolType); +export function parsePoolMetadata( + poolType: string, + resourceAddress: string, +): LiquidityPoolMetadata { + const NULL_PATTERN = new RegExp(`${resourceAddress}::base_pool::Null`); + + const [liquidityPoolType, poolTypeArgs] = parseLiquidityPoolType( + poolType, + resourceAddress, + ); // if first n coins are not dummycoin, then numCoins = n const nullIndex = poolTypeArgs @@ -37,7 +44,15 @@ export function parsePoolMetadata(poolType: string): LiquidityPoolMetadata { export function parseLiquidityPoolType( poolType: string, + resourceAddress: string, ): ["Weighted" | "Stable", string[]] { + const WEIGHTED_POOL_PATTERN = new RegExp( + `${resourceAddress}::weighted_pool::WeightedPool<(.*)>`, + ); + const STABLE_POOL_PATTERN = new RegExp( + `${resourceAddress}::stable_pool::StablePool<(.*)>`, + ); + const matchWeightedPool = poolType.match(WEIGHTED_POOL_PATTERN); if (matchWeightedPool) { return ["Weighted", matchWeightedPool[1].split(",").map((e) => e.trim())]; @@ -49,16 +64,6 @@ export function parseLiquidityPoolType( throw new Error(`Invalid poolType: ${poolType}`); } -const WEIGHTED_POOL_PATTERN = new RegExp( - `${THALASWAP_RESOURCE_ACCOUNT_ADDRESS}::weighted_pool::WeightedPool<(.*)>`, -); -const STABLE_POOL_PATTERN = new RegExp( - `${THALASWAP_RESOURCE_ACCOUNT_ADDRESS}::stable_pool::StablePool<(.*)>`, -); -const NULL_PATTERN = new RegExp( - `${THALASWAP_RESOURCE_ACCOUNT_ADDRESS}::base_pool::Null`, -); - // input cannot be larger the 2^31 // this should allow at least 6 digits precision in the fractional part // https://stackoverflow.com/questions/45929493/node-js-maximum-safe-floating-point-number diff --git a/packages/thalaswap-router/test/router.test.ts b/packages/thalaswap-router/test/router.test.ts index 29d240a..f122f39 100644 --- a/packages/thalaswap-router/test/router.test.ts +++ b/packages/thalaswap-router/test/router.test.ts @@ -1,5 +1,6 @@ import poolData from "./test-pools.json"; import { ThalaswapRouter } from "../src"; +import { Network } from "@aptos-labs/ts-sdk"; const coins = poolData.coins; const pools = poolData.pools.map((pool: any) => { @@ -23,7 +24,7 @@ const mockPoolDataClient = { }), }; -const router = new ThalaswapRouter("example-url"); +const router = new ThalaswapRouter(Network.MAINNET, "test", "0x123"); router.setPoolDataClient(mockPoolDataClient as any); test("Exact input 1 hop", async () => {