From c28b2134169b4b2f482988e919fcc2358a285e1f Mon Sep 17 00:00:00 2001 From: SamuelQZQ Date: Mon, 15 Jul 2024 18:29:48 +0800 Subject: [PATCH] thala-router support multi chains --- packages/thalaswap-router/README.md | 5 ++- .../thalaswap-router/examples/examples.ts | 5 ++- .../thalaswap-router/src/PoolDataClient.ts | 28 ++++++++++------ .../thalaswap-router/src/ThalaswapRouter.ts | 9 ++++-- packages/thalaswap-router/src/utils.ts | 32 +++++++++++-------- packages/thalaswap-router/test/router.test.ts | 3 +- 6 files changed, 55 insertions(+), 27 deletions(-) diff --git a/packages/thalaswap-router/README.md b/packages/thalaswap-router/README.md index a07c16a..6c64c34 100644 --- a/packages/thalaswap-router/README.md +++ b/packages/thalaswap-router/README.md @@ -11,7 +11,10 @@ $ 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" +); 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..be8d73e 100644 --- a/packages/thalaswap-router/examples/examples.ts +++ b/packages/thalaswap-router/examples/examples.ts @@ -21,7 +21,10 @@ 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", +); // 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..c1d0e8a 100644 --- a/packages/thalaswap-router/src/PoolDataClient.ts +++ b/packages/thalaswap-router/src/PoolDataClient.ts @@ -1,8 +1,8 @@ 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"; +import { THALASWAP_RESOURCE_ACCOUNT_ADDRESS } from "./constants"; class PoolDataClient { private poolData: PoolData | null = null; @@ -11,12 +11,16 @@ class PoolDataClient { private retryLimit = 3; private client: Aptos; private coins: Coin[] = []; + private resourceAddress: string; + + constructor(network: Network, fullnode: string, resourceAddress?: string) { + this.resourceAddress = + resourceAddress || THALASWAP_RESOURCE_ACCOUNT_ADDRESS; - constructor(aptosRpc: string) { this.client = new Aptos( new AptosConfig({ - network: Network.MAINNET, - fullnode: aptosRpc, + network: network, + fullnode: fullnode, }), ); } @@ -27,16 +31,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 +56,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 +90,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..ae7e8af 100644 --- a/packages/thalaswap-router/src/ThalaswapRouter.ts +++ b/packages/thalaswap-router/src/ThalaswapRouter.ts @@ -13,6 +13,8 @@ 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"; +import { THALASWAP_RESOURCE_ACCOUNT_ADDRESS } from "./constants"; const NULL_TYPE = `${STABLE_POOL_SCRIPTS_ABI.address}::base_pool::Null`; const NULL_4 = Array(4).fill(NULL_TYPE); @@ -61,9 +63,12 @@ class ThalaswapRouter { private client: PoolDataClient; private graph: Graph | null = null; private coins: Coin[] | null = null; + private resourceAddress: string; - constructor(dataURL: string) { - this.client = new PoolDataClient(dataURL); + constructor(network: Network, fullnode: string, resourceAddress?: string) { + this.resourceAddress = + resourceAddress || THALASWAP_RESOURCE_ACCOUNT_ADDRESS; + this.client = new PoolDataClient(network, fullnode); } setPoolDataClient(client: PoolDataClient) { diff --git a/packages/thalaswap-router/src/utils.ts b/packages/thalaswap-router/src/utils.ts index 89d0aa2..474c5d7 100644 --- a/packages/thalaswap-router/src/utils.ts +++ b/packages/thalaswap-router/src/utils.ts @@ -1,6 +1,6 @@ import BigNumber from "bignumber.js"; -import { THALASWAP_RESOURCE_ACCOUNT_ADDRESS } from "./constants"; import { LiquidityPoolMetadata } from "./types"; +import { THALASWAP_RESOURCE_ACCOUNT_ADDRESS } from "./constants"; export const BN_TEN = new BigNumber(10); @@ -10,8 +10,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 +45,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 +65,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..56f0902 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"); router.setPoolDataClient(mockPoolDataClient as any); test("Exact input 1 hop", async () => {