From defdff6cd26c9b0aa497a7719cb7469ab0f53a2e Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 7 Apr 2025 13:11:14 -0400 Subject: [PATCH 1/4] Move to iris --- package-lock.json | 19 +- package.json | 3 +- src/dex/api/base-api.ts | 16 - src/dex/api/minswap-api.ts | 190 ----------- src/dex/api/muesliswap-api.ts | 64 ---- src/dex/api/splash-api.ts | 77 ----- src/dex/api/sundaeswap-v1-api.ts | 113 ------- src/dex/api/sundaeswap-v3-api.ts | 75 ----- src/dex/api/vyfinance-api.ts | 77 ----- src/dex/api/wingriders-api.ts | 94 ------ src/dex/base-dex.ts | 33 +- .../{minswap => minswap-v1}/order.ts | 0 .../{minswap => minswap-v1}/pool.ts | 0 .../{wingriders => wingriders-v1}/order.ts | 0 .../{wingriders => wingriders-v1}/pool.ts | 0 src/dex/minswap-v2.ts | 151 ++------- src/dex/minswap.ts | 156 ++------- src/dex/models/asset.ts | 33 -- src/dex/models/liquidity-pool.ts | 64 ---- src/dex/muesliswap.ts | 129 +------- src/dex/splash.ts | 139 +------- src/dex/sundaeswap-v3.ts | 117 +------ src/dex/{sundaeswap-v1.ts => sundaeswap.ts} | 128 +------- src/dex/vyfinance.ts | 63 ++-- src/dex/wingriders-v2.ts | 153 +-------- src/dex/wingriders.ts | 156 ++------- src/dexter.ts | 47 +-- src/index.ts | 14 +- .../asset-metadata/base-metadata-provider.ts | 11 - .../asset-metadata/token-registry-provider.ts | 44 --- src/providers/data/base-data-provider.ts | 2 +- src/providers/data/blockfrost-provider.ts | 2 +- src/providers/data/kupo-provider.ts | 2 +- src/providers/data/mock-data-provider.ts | 2 +- src/requests/fetch-request.ts | 302 ------------------ src/requests/split-swap-request.ts | 7 +- src/requests/swap-request.ts | 24 +- src/types.ts | 3 +- src/utils.ts | 11 +- tests/dex-transaction.test.ts | 80 ----- tests/minswap.test.ts | 147 --------- tests/muesliswap.test.ts | 147 --------- tests/split-swap-request.test.ts | 127 -------- tests/sundaeswap-v1.test.ts | 150 --------- tests/swap-request.test.ts | 111 ------- tests/vyfinance.test.ts | 185 ----------- tests/wingriders.test.ts | 166 ---------- 47 files changed, 224 insertions(+), 3410 deletions(-) delete mode 100644 src/dex/api/base-api.ts delete mode 100644 src/dex/api/minswap-api.ts delete mode 100644 src/dex/api/muesliswap-api.ts delete mode 100644 src/dex/api/splash-api.ts delete mode 100644 src/dex/api/sundaeswap-v1-api.ts delete mode 100644 src/dex/api/sundaeswap-v3-api.ts delete mode 100644 src/dex/api/vyfinance-api.ts delete mode 100644 src/dex/api/wingriders-api.ts rename src/dex/definitions/{minswap => minswap-v1}/order.ts (100%) rename src/dex/definitions/{minswap => minswap-v1}/pool.ts (100%) rename src/dex/definitions/{wingriders => wingriders-v1}/order.ts (100%) rename src/dex/definitions/{wingriders => wingriders-v1}/pool.ts (100%) delete mode 100644 src/dex/models/asset.ts delete mode 100644 src/dex/models/liquidity-pool.ts rename src/dex/{sundaeswap-v1.ts => sundaeswap.ts} (67%) delete mode 100644 src/providers/asset-metadata/base-metadata-provider.ts delete mode 100644 src/providers/asset-metadata/token-registry-provider.ts delete mode 100644 src/requests/fetch-request.ts delete mode 100644 tests/dex-transaction.test.ts delete mode 100644 tests/minswap.test.ts delete mode 100644 tests/muesliswap.test.ts delete mode 100644 tests/split-swap-request.test.ts delete mode 100644 tests/sundaeswap-v1.test.ts delete mode 100644 tests/swap-request.test.ts delete mode 100644 tests/vyfinance.test.ts delete mode 100644 tests/wingriders.test.ts diff --git a/package-lock.json b/package-lock.json index 6adb7df..a5829e1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,14 +1,15 @@ { "name": "@indigo-labs/dexter", - "version": "5.4.9", + "version": "5.4.10", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@indigo-labs/dexter", - "version": "5.4.9", + "version": "5.4.10", "license": "MIT", "dependencies": { + "@indigo-labs/iris-sdk": "file:../iris-sdk", "@types/blake2b": "^2.1.3", "@types/crypto-js": "^4.1.1", "axios": "^0.26.1", @@ -36,6 +37,16 @@ "typescript": "^5.0.3" } }, + "../iris-sdk": { + "version": "1.0.3", + "license": "MIT", + "dependencies": { + "axios": "^1.6.2" + }, + "devDependencies": { + "typescript": "^5.3.3" + } + }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -1730,6 +1741,10 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@indigo-labs/iris-sdk": { + "resolved": "../iris-sdk", + "link": true + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", diff --git a/package.json b/package.json index ec6e1df..1d7efd5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@indigo-labs/dexter", - "version": "5.4.9", + "version": "5.4.10", "license": "MIT", "author": "Zachary Sluder", "keywords": [ @@ -22,6 +22,7 @@ "prepublishOnly": "npm run test" }, "dependencies": { + "@indigo-labs/iris-sdk": "file:../iris-sdk", "@types/blake2b": "^2.1.3", "@types/crypto-js": "^4.1.1", "axios": "^0.26.1", diff --git a/src/dex/api/base-api.ts b/src/dex/api/base-api.ts deleted file mode 100644 index f390c4f..0000000 --- a/src/dex/api/base-api.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Token } from '../models/asset'; -import { LiquidityPool } from '../models/liquidity-pool'; -import { BaseDex } from '../base-dex'; -import { AxiosInstance } from 'axios'; - -export abstract class BaseApi { - - protected abstract readonly api: AxiosInstance; - protected abstract readonly dex: BaseDex; - - /** - * Fetch all liquidity pools matching assetA & assetB. - */ - abstract liquidityPools(assetA?: Token, assetB?: Token): Promise; - -} diff --git a/src/dex/api/minswap-api.ts b/src/dex/api/minswap-api.ts deleted file mode 100644 index a2b2424..0000000 --- a/src/dex/api/minswap-api.ts +++ /dev/null @@ -1,190 +0,0 @@ -import { BaseApi } from './base-api'; -import { Asset, Token } from '../models/asset'; -import { LiquidityPool } from '../models/liquidity-pool'; -import axios, { AxiosInstance } from 'axios'; -import { Minswap } from '../minswap'; -import { RequestConfig } from '@app/types'; -import AES from 'crypto-js/aes'; -import Utf8 from 'crypto-js/enc-utf8'; -import { appendSlash } from '@app/utils'; - -const AES_KEY: string = '22eaca439bfd89cf125827a7a33fe3970d735dbfd5d84f19dd95820781fc47be'; - -export class MinswapApi extends BaseApi { - - protected readonly api: AxiosInstance; - protected readonly dex: Minswap; - - constructor(dex: Minswap, requestConfig: RequestConfig) { - super(); - - this.dex = dex; - - this.api = axios.create({ - timeout: requestConfig.timeout, - baseURL: `${appendSlash(requestConfig.proxyUrl)}https://monorepo-mainnet-prod.minswap.org/graphql`, - withCredentials: false, - }); - } - - liquidityPools(assetA: Token, assetB?: Token): Promise { - // Small optimization for providing both tokens - if (assetA && assetB) { - return this.poolsByPair(assetA, assetB) - .then((pool: LiquidityPool) => [pool]); - } - - const maxPerPage: number = 20; - - const getPaginatedResponse = (page: number): Promise => { - return this.api.post('', { - operationName: 'PoolsByAsset', - query: ` - query PoolsByAsset($asset: InputAsset!, $limit: Int, $offset: Int) { - poolsByAsset( - asset: $asset - limit: $limit - offset: $offset - ) { - assetA { - currencySymbol - tokenName - ...allMetadata - } - assetB { - currencySymbol - tokenName - ...allMetadata - } - reserveA - reserveB - lpAsset { - currencySymbol - tokenName - } - totalLiquidity - } - } - fragment allMetadata on Asset { - metadata { - name - decimals - } - } - `, - variables: { - asset: { - currencySymbol: assetA === 'lovelace' ? '' : assetA.policyId, - tokenName: assetA === 'lovelace' ? '' : assetA.nameHex, - }, - limit: maxPerPage, - offset: page * maxPerPage, - }, - }).then((response: any) => { - response = JSON.parse(this.decryptResponse(response.data.data.encryptedData)); - - const pools = response.poolsByAsset; - - const liquidityPools = pools.map((pool: any) => this.liquidityPoolFromResponse(pool)); - - if (pools.length < maxPerPage) { - return liquidityPools; - } - - return getPaginatedResponse(page + 1).then((nextPagePools: LiquidityPool[]) => { - return liquidityPools.concat(nextPagePools); - }); - }); - }; - - return getPaginatedResponse(0); - } - - private poolsByPair(assetA: Token, assetB: Token): Promise { - return this.api.post('', { - operationName: 'PoolByPair', - query: ` - query PoolByPair($pair: InputPoolByPair!) { - poolByPair(pair: $pair) { - assetA { - currencySymbol - tokenName - isVerified - ...allMetadata - } - assetB { - currencySymbol - tokenName - isVerified - ...allMetadata - } - reserveA - reserveB - lpAsset { - currencySymbol - tokenName - } - totalLiquidity - profitSharing { - feeTo - } - } - } - fragment allMetadata on Asset { - metadata { - name - ticker - url - decimals - description - } - } - `, - variables: { - pair: { - assetA: { - currencySymbol: assetA === 'lovelace' ? '' : assetA.policyId, - tokenName: assetA === 'lovelace' ? '' : assetA.nameHex, - }, - assetB: { - currencySymbol: assetB === 'lovelace' ? '' : assetB.policyId, - tokenName: assetB === 'lovelace' ? '' : assetB.nameHex, - }, - }, - }, - }).then((response: any) => { - response = JSON.parse(this.decryptResponse(response.data.data.encryptedData)); - - return this.liquidityPoolFromResponse(response.poolByPair) - }); - } - - private liquidityPoolFromResponse(poolData: any): LiquidityPool { - const liquidityPool: LiquidityPool = new LiquidityPool( - Minswap.identifier, - poolData.assetA.currencySymbol !== '' - ? new Asset(poolData.assetA.currencySymbol, poolData.assetA.tokenName, poolData.assetA.metadata?.decimals ?? 0) - : 'lovelace', - poolData.assetB.currencySymbol !== '' - ? new Asset(poolData.assetB.currencySymbol, poolData.assetB.tokenName, poolData.assetB.metadata?.decimals ?? 0) - : 'lovelace', - BigInt(poolData.reserveA), - BigInt(poolData.reserveB), - '', // Not provided - this.dex.marketOrderAddress, - this.dex.limitOrderAddress, - ); - - liquidityPool.lpToken = new Asset(poolData.lpAsset.currencySymbol, poolData.lpAsset.tokenName); - liquidityPool.totalLpTokens = BigInt(poolData.totalLiquidity); - liquidityPool.poolFeePercent = 0.3; - liquidityPool.identifier = liquidityPool.lpToken.identifier(); - - return liquidityPool; - } - - private decryptResponse(encryptedResponse: string): any { - return AES.decrypt(encryptedResponse, AES_KEY).toString(Utf8); - } - -} diff --git a/src/dex/api/muesliswap-api.ts b/src/dex/api/muesliswap-api.ts deleted file mode 100644 index 3d1dac2..0000000 --- a/src/dex/api/muesliswap-api.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { BaseApi } from './base-api'; -import { Asset, Token } from '../models/asset'; -import { LiquidityPool } from '../models/liquidity-pool'; -import axios, { AxiosInstance } from 'axios'; -import { MuesliSwap } from '../muesliswap'; -import { RequestConfig } from '@app/types'; -import { appendSlash } from '@app/utils'; - -export class MuesliSwapApi extends BaseApi { - - protected readonly api: AxiosInstance; - protected readonly dex: MuesliSwap; - - constructor(dex: MuesliSwap, requestConfig: RequestConfig) { - super(); - - this.dex = dex; - this.api = axios.create({ - timeout: requestConfig.timeout, - baseURL: `${appendSlash(requestConfig.proxyUrl)}https://api.muesliswap.com/`, - headers: { - 'Content-Type': 'application/json', - } - }); - } - - liquidityPools(assetA: Token, assetB?: Token): Promise { - const providers: string[] = ['muesliswap', 'muesliswap_v2', 'muesliswap_clp']; - const tokenA: string = (assetA === 'lovelace') - ? '.' - : assetA.identifier('.'); - const tokenB: string = (assetB && assetB !== 'lovelace') - ? assetB.identifier('.') - : ''; - - return this.api.get(`/liquidity/pools?providers=${providers.join(',')}&token-a=${tokenA}&token-b=${tokenB}`) - .then((response: any) => { - return response.data.map((pool: any) => { - let liquidityPool: LiquidityPool = new LiquidityPool( - MuesliSwap.identifier, - pool.tokenA.symbol !== 'ADA' - ? new Asset(pool.tokenA.address.policyId, pool.tokenA.address.name, pool.tokenA.decimalPlaces) - : 'lovelace', - pool.tokenB.symbol !== 'ADA' - ? new Asset(pool.tokenB.address.policyId, pool.tokenB.address.name, pool.tokenB.decimalPlaces) - : 'lovelace', - BigInt(pool.tokenA.amount), - BigInt(pool.tokenB.amount), - pool.batcherAddress, - this.dex.orderAddress, - this.dex.orderAddress, - ); - - liquidityPool.identifier = pool.poolId; - liquidityPool.lpToken = new Asset(pool.lpToken.address.policyId, pool.lpToken.address.name); - liquidityPool.poolFeePercent = Number(pool.poolFee); - liquidityPool.totalLpTokens = BigInt(pool.lpToken.amount); - - return liquidityPool; - }); - }); - } - -} diff --git a/src/dex/api/splash-api.ts b/src/dex/api/splash-api.ts deleted file mode 100644 index 7a3d0d2..0000000 --- a/src/dex/api/splash-api.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { BaseApi } from './base-api'; -import { Asset, Token } from '../models/asset'; -import { LiquidityPool } from '../models/liquidity-pool'; -import axios, { AxiosInstance } from 'axios'; -import { RequestConfig } from '@app/types'; -import { appendSlash } from '@app/utils'; -import { Splash } from '@dex/splash'; - -const MAX_INT: bigint = 9_223_372_036_854_775_807n; - -export class SplashApi extends BaseApi { - - protected readonly api: AxiosInstance; - protected readonly dex: Splash; - - constructor(dex: Splash, requestConfig: RequestConfig) { - super(); - - this.dex = dex; - - this.api = axios.create({ - timeout: requestConfig.timeout, - baseURL: `${appendSlash(requestConfig.proxyUrl)}https://api5.splash.trade/platform-api/v1/`, - withCredentials: false, - }); - } - - async liquidityPools(assetA: Token, assetB?: Token): Promise { - const assets: any = (await this.assets()).data['tokens']; - - return this.api.get('/pools/overview?verified=false&duplicated=false').then((response: any) => { - return response.data.map((pool: any) => this.liquidityPoolFromResponse(pool, assets)) as LiquidityPool[]; - }); - } - - private liquidityPoolFromResponse(poolData: any, assets: any): LiquidityPool { - poolData = poolData.pool; - - const tokenA: Token = poolData.x.asset === '.' - ? 'lovelace' - : new Asset(poolData.x.asset.split('.')[0], poolData.x.asset.split('.')[1]); - const tokenB = poolData.y.asset === '.' - ? 'lovelace' - : new Asset(poolData.y.asset.split('.')[0], poolData.y.asset.split('.')[1]); - - if (tokenA !== 'lovelace' && tokenA.identifier('.') in assets) { - tokenA.decimals = assets[tokenA.identifier('.')].decimals; - } - if (tokenB !== 'lovelace' && tokenB.identifier('.') in assets) { - tokenB.decimals = assets[tokenB.identifier('.')].decimals; - } - - const liquidityPool: LiquidityPool = new LiquidityPool( - Splash.identifier, - tokenA, - tokenB, - BigInt(poolData['x']['amount']) - BigInt(poolData['treasuryX']), - BigInt(poolData['y']['amount']) - BigInt(poolData['treasuryY']), - '', - '', - '', - ); - - const [lpTokenPolicyId, lpTokenAssetName] = poolData['lq']['asset'].split('.'); - - liquidityPool.lpToken = new Asset(lpTokenPolicyId, lpTokenAssetName); - liquidityPool.totalLpTokens = MAX_INT - BigInt(poolData['lq']['amount']); - liquidityPool.identifier = poolData['id']; - - return liquidityPool; - } - - private assets(): Promise { - return axios.get('https://spectrum.fi/cardano-token-list-v2.json'); - } - -} diff --git a/src/dex/api/sundaeswap-v1-api.ts b/src/dex/api/sundaeswap-v1-api.ts deleted file mode 100644 index 1e5e9a5..0000000 --- a/src/dex/api/sundaeswap-v1-api.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { BaseApi } from './base-api'; -import { Asset, Token } from '../models/asset'; -import { LiquidityPool } from '../models/liquidity-pool'; -import axios, { AxiosInstance } from 'axios'; -import { SundaeSwapV1 } from '../sundaeswap-v1'; -import { RequestConfig } from '@app/types'; -import { appendSlash } from '@app/utils'; - -export class SundaeSwapV1Api extends BaseApi { - - protected readonly api: AxiosInstance; - protected readonly dex: SundaeSwapV1; - - constructor(dex: SundaeSwapV1, requestConfig: RequestConfig) { - super(); - - this.dex = dex; - this.api = axios.create({ - timeout: requestConfig.timeout, - baseURL: `${appendSlash(requestConfig.proxyUrl)}https://stats.sundaeswap.finance/graphql`, - headers: { - 'Content-Type': 'application/json', - } - }); - } - - liquidityPools(assetA: Token, assetB?: Token): Promise { - const maxPerPage: number = 100; - - const assetAId: string = (assetA === 'lovelace') - ? '' - : assetA.identifier('.'); - let assetBId: string = (assetB && assetB !== 'lovelace') - ? assetB.identifier('.') - : ''; - - const getPaginatedResponse = (page: number): Promise => { - return this.api.post('', { - operationName: 'getPoolsByAssetIds', - query: ` - query getPoolsByAssetIds($assetIds: [String!]!, $pageSize: Int, $page: Int) { - pools(assetIds: $assetIds, pageSize: $pageSize, page: $page) { - ...PoolFragment - } - } - fragment PoolFragment on Pool { - assetA { - ...AssetFragment - } - assetB { - ...AssetFragment - } - assetLP { - ...AssetFragment - } - name - fee - quantityA - quantityB - quantityLP - ident - assetID - } - fragment AssetFragment on Asset { - assetId - decimals - } - `, - variables: { - page: page, - pageSize: maxPerPage, - assetIds: [assetBId !== '' ? assetBId : assetAId], - }, - }).then((response: any) => { - const pools = response.data.data.pools; - const liquidityPools = pools.map((pool: any) => { - let liquidityPool: LiquidityPool = new LiquidityPool( - SundaeSwapV1.identifier, - pool.assetA.assetId - ? Asset.fromIdentifier(pool.assetA.assetId, pool.assetA.decimals) - : 'lovelace', - pool.assetB.assetId - ? Asset.fromIdentifier(pool.assetB.assetId, pool.assetB.decimals) - : 'lovelace', - BigInt(pool.quantityA), - BigInt(pool.quantityB), - this.dex.poolAddress, - this.dex.orderAddress, - this.dex.orderAddress, - ); - - liquidityPool.identifier = pool.ident; - liquidityPool.lpToken = Asset.fromIdentifier(pool.assetLP.assetId); - liquidityPool.poolFeePercent = Number(pool.fee); - liquidityPool.totalLpTokens = BigInt(pool.quantityLP); - - return liquidityPool; - }); - - if (pools.length < maxPerPage) { - return liquidityPools; - } - - return getPaginatedResponse(page + 1).then((nextPagePools: LiquidityPool[]) => { - return liquidityPools.concat(nextPagePools); - }); - }); - }; - - return getPaginatedResponse(0); - } - -} diff --git a/src/dex/api/sundaeswap-v3-api.ts b/src/dex/api/sundaeswap-v3-api.ts deleted file mode 100644 index 4e02073..0000000 --- a/src/dex/api/sundaeswap-v3-api.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { BaseApi } from './base-api'; -import { Asset, Token } from '../models/asset'; -import { LiquidityPool } from '../models/liquidity-pool'; -import axios, { AxiosInstance } from 'axios'; -import { RequestConfig } from '@app/types'; -import { appendSlash } from '@app/utils'; -import { SundaeSwapV3 } from '@dex/sundaeswap-v3'; - -export class SundaeSwapV3Api extends BaseApi { - - protected readonly api: AxiosInstance; - protected readonly dex: SundaeSwapV3; - - constructor(dex: SundaeSwapV3, requestConfig: RequestConfig) { - super(); - - this.dex = dex; - this.api = axios.create({ - timeout: requestConfig.timeout, - baseURL: `${appendSlash(requestConfig.proxyUrl)}https://api.sundae.fi/graphql`, - headers: { - 'Content-Type': 'application/json', - } - }); - } - - async liquidityPools(assetA: Token, assetB?: Token): Promise { - const assetAId: string = (assetA === 'lovelace') - ? 'ada.lovelace' - : assetA.identifier('.'); - const assetBId: string = (assetB && assetB !== 'lovelace') - ? assetB.identifier('.') - : 'ada.lovelace'; - const assets: string[] = [assetAId, assetBId]; - - return await this.api.post('', { - operationName: 'fetchPoolsByPair', - query: `query fetchPoolsByPair($assetA: ID!, $assetB: ID!) {\n pools {\n byPair(assetA: $assetA, assetB: $assetB) {\n ...PoolBrambleFragment\n }\n }\n}\n\nfragment PoolBrambleFragment on Pool {\n id\n assetA {\n ...AssetBrambleFragment\n }\n assetB {\n ...AssetBrambleFragment\n }\n assetLP {\n ...AssetBrambleFragment\n }\n feesFinalized {\n slot\n }\n marketOpen {\n slot\n }\n askFee\n bidFee\n feeManagerId\n current {\n quantityA {\n quantity\n }\n quantityB {\n quantity\n }\n quantityLP {\n quantity\n }\n tvl {\n quantity\n }\n }\n version\n}\n\nfragment AssetBrambleFragment on Asset {\n id\n policyId\n description\n dateListed {\n format\n }\n decimals\n ticker\n name\n logo\n assetName\n metadata {\n ... on OnChainLabel20 {\n __typename\n }\n ... on OnChainLabel721 {\n __typename\n }\n ... on CardanoTokenRegistry {\n __typename\n }\n }\n}`, - variables: { - assetA: assets[0], - assetB: assets[1], - }, - }).then((response: any) => { - const pools = response.data.data.pools.byPair; - - return pools - .filter((pool: any) => pool.version === 'V3') - .map((pool: any) => { - let liquidityPool: LiquidityPool = new LiquidityPool( - SundaeSwapV3.identifier, - pool.assetA.id === 'ada.lovelace' - ? 'lovelace' - : Asset.fromIdentifier(pool.assetA.id, pool.assetA.decimals), - pool.assetB.id === 'ada.lovelace' - ? 'lovelace' - : Asset.fromIdentifier(pool.assetB.id, pool.assetB.decimals), - BigInt(pool.current.quantityA.quantity), - BigInt(pool.current.quantityB.quantity), - this.dex.poolAddress, - '', - '', - ); - - liquidityPool.identifier = pool.id; - liquidityPool.lpToken = Asset.fromIdentifier(pool.assetLP.id); - liquidityPool.poolFeePercent = Number((pool.bidFee[0] / pool.bidFee[1]) * 100); - liquidityPool.totalLpTokens = BigInt(pool.current.quantityLP.quantity); - - return liquidityPool; - }); - }); - - } - -} diff --git a/src/dex/api/vyfinance-api.ts b/src/dex/api/vyfinance-api.ts deleted file mode 100644 index 17c0852..0000000 --- a/src/dex/api/vyfinance-api.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { BaseApi } from './base-api'; -import { Asset, Token } from '../models/asset'; -import { LiquidityPool } from '../models/liquidity-pool'; -import axios, { AxiosInstance } from 'axios'; -import { VyFinance } from '../vyfinance'; -import { RequestConfig } from '@app/types'; -import { appendSlash } from '@app/utils'; - -export class VyfinanceApi extends BaseApi { - - protected readonly api: AxiosInstance; - protected readonly dex: VyFinance; - - constructor(dex: VyFinance, requestConfig: RequestConfig) { - super(); - - this.dex = dex; - this.api = axios.create({ - timeout: requestConfig.timeout, - baseURL: `${appendSlash(requestConfig.proxyUrl)}https://api.vyfi.io`, - headers: { - 'Content-Type': 'application/json', - } - }); - } - - liquidityPools(assetA?: Token, assetB?: Token): Promise { - const assetAId: string = (assetA && assetA !== 'lovelace') - ? assetA.identifier() - : 'lovelace'; - let assetBId: string = (assetB && assetB !== 'lovelace') - ? assetB.identifier() - : 'lovelace'; - - const url: string = assetA && assetB - ? `/lp?networkId=1&v2=true&tokenAUnit=${assetAId}&tokenBUnit=${assetBId}` - : '/lp?networkId=1&v2=true'; - - return this.api.get(url) - .then((poolResponse: any) => { - return poolResponse.data.map((pool: any) => { - const poolDetails: any = JSON.parse(pool.json); - - const tokenA: Token = poolDetails['aAsset']['tokenName'] - ? new Asset(poolDetails['aAsset']['currencySymbol'], Buffer.from(poolDetails['aAsset']['tokenName']).toString('hex')) - : 'lovelace'; - const tokenB: Token = poolDetails['bAsset']['tokenName'] - ? new Asset(poolDetails['bAsset']['currencySymbol'], Buffer.from(poolDetails['bAsset']['tokenName']).toString('hex')) - : 'lovelace'; - - - let liquidityPool: LiquidityPool = new LiquidityPool( - VyFinance.identifier, - tokenA, - tokenB, - BigInt(pool['tokenAQuantity'] ?? 0), - BigInt(pool['tokenBQuantity'] ?? 0), - pool['poolValidatorUtxoAddress'], - pool['orderValidatorUtxoAddress'], - pool['orderValidatorUtxoAddress'], - ); - - const lpTokenDetails: string[] = pool['lpPolicyId-assetId'].split('-'); - liquidityPool.lpToken = new Asset(lpTokenDetails[0], lpTokenDetails[1]); - liquidityPool.poolFeePercent = (poolDetails['feesSettings']['barFee'] + poolDetails['feesSettings']['liqFee']) / 100; - liquidityPool.identifier = liquidityPool.lpToken.identifier(); - liquidityPool.extra.nft = new Asset(poolDetails['mainNFT']['currencySymbol'], poolDetails['mainNFT']['tokenName']); - - return liquidityPool; - }).filter((pool: LiquidityPool | undefined) => pool !== undefined) as LiquidityPool[]; - }).catch((e) => { - console.error(e) - return []; - }); - } - -} diff --git a/src/dex/api/wingriders-api.ts b/src/dex/api/wingriders-api.ts deleted file mode 100644 index 6b45b95..0000000 --- a/src/dex/api/wingriders-api.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { BaseApi } from './base-api'; -import { Asset, Token } from '../models/asset'; -import { LiquidityPool } from '../models/liquidity-pool'; -import axios, { AxiosInstance } from 'axios'; -import { RequestConfig } from '@app/types'; -import { WingRiders } from '@dex/wingriders'; -import { appendSlash } from '@app/utils'; - -export class WingRidersApi extends BaseApi { - - protected readonly api: AxiosInstance; - protected readonly dex: WingRiders; - - constructor(dex: WingRiders, requestConfig: RequestConfig) { - super(); - - this.dex = dex; - this.api = axios.create({ - timeout: requestConfig.timeout, - baseURL: `${appendSlash(requestConfig.proxyUrl)}https://api.mainnet.wingriders.com/graphql`, - headers: { - 'Content-Type': 'application/json', - } - }); - } - - liquidityPools(assetA: Token, assetB?: Token): Promise { - return this.api.post('', { - operationName: 'LiquidityPoolsWithMarketData', - query: ` - query LiquidityPoolsWithMarketData($input: PoolsWithMarketdataInput) { - poolsWithMarketdata(input: $input) { - ...LiquidityPoolFragment - } - } - fragment LiquidityPoolFragment on PoolWithMarketdata { - issuedShareToken { - policyId - assetName - quantity - } - tokenA { - policyId - assetName - quantity - } - tokenB { - policyId - assetName - quantity - } - treasuryA - treasuryB - _utxo { - address - } - } - `, - variables: { - input: { - sort: true - }, - }, - }).then((response: any) => { - return response.data.data.poolsWithMarketdata.map((pool: any) => { - const tokenA: Token = pool.tokenA.policyId !== '' - ? new Asset(pool.tokenA.policyId, pool.tokenA.assetName) - : 'lovelace'; - const tokenB: Token = pool.tokenB.policyId !== '' - ? new Asset(pool.tokenB.policyId, pool.tokenB.assetName) - : 'lovelace'; - - let liquidityPool: LiquidityPool = new LiquidityPool( - WingRiders.identifier, - tokenA, - tokenB, - BigInt(pool.tokenA.quantity) - BigInt(pool.treasuryA), - BigInt(pool.tokenB.quantity) - BigInt(pool.treasuryB), - pool._utxo.address, - this.dex.orderAddress, - this.dex.orderAddress, - ); - - liquidityPool.lpToken = new Asset(pool.issuedShareToken.policyId, pool.issuedShareToken.assetName); - liquidityPool.poolFeePercent = 0.35; - liquidityPool.identifier = liquidityPool.lpToken.identifier(); - liquidityPool.totalLpTokens = BigInt(pool.issuedShareToken.quantity); - - return liquidityPool; - }).filter((pool: LiquidityPool | undefined) => pool !== undefined); - }); - } - -} diff --git a/src/dex/base-dex.ts b/src/dex/base-dex.ts index d990f2c..95b9d67 100644 --- a/src/dex/base-dex.ts +++ b/src/dex/base-dex.ts @@ -1,33 +1,14 @@ -import { LiquidityPool } from './models/liquidity-pool'; -import { BaseDataProvider } from '@providers/data/base-data-provider'; -import { Asset, Token } from './models/asset'; import { AssetBalance, DatumParameters, PayToAddress, SpendUTxO, SwapFee, UTxO } from '@app/types'; import { DatumParameterKey } from '@app/constants'; import { tokensMatch } from '@app/utils'; -import { BaseApi } from '@dex/api/base-api'; -import { BaseWalletProvider } from '@providers/wallet/base-wallet-provider'; +import { Asset, LiquidityPool, Token } from '@indigo-labs/iris-sdk'; +import { Dexter } from '@app/dexter'; export abstract class BaseDex { - /** - * API connection for the DEX. - */ - public abstract readonly api: BaseApi; - - /** - * Fetch addresses mapped to a liquidity pool. - */ - abstract liquidityPoolAddresses(provider?: BaseDataProvider): Promise; - - /** - * Fetch all liquidity pools. - */ - abstract liquidityPools(provider: BaseDataProvider, wallet?: BaseWalletProvider): Promise; - - /** - * Craft liquidity pool state from a valid UTxO. - */ - abstract liquidityPoolFromUtxo(provider: BaseDataProvider, utxo: UTxO, wallet?: BaseWalletProvider): Promise; + constructor( + protected dexter: Dexter, + ) {} /** * Estimated swap in amount given for a swap out token & amount on a liquidity pool. @@ -47,12 +28,12 @@ export abstract class BaseDex { /** * Craft a swap order for this DEX. */ - abstract buildSwapOrder(liquidityPool: LiquidityPool, swapParameters: DatumParameters, spendUtxos?: SpendUTxO[], dataProvider?: BaseDataProvider): Promise; + abstract buildSwapOrder(liquidityPool: LiquidityPool, swapParameters: DatumParameters, spendUtxos?: SpendUTxO[]): Promise; /** * Craft a swap order cancellation for this DEX. */ - abstract buildCancelSwapOrder(txOutputs: UTxO[], returnAddress: string, wallet?: BaseWalletProvider): Promise; + abstract buildCancelSwapOrder(txOutputs: UTxO[], returnAddress: string): Promise; /** * Fees associated with submitting a swap order. diff --git a/src/dex/definitions/minswap/order.ts b/src/dex/definitions/minswap-v1/order.ts similarity index 100% rename from src/dex/definitions/minswap/order.ts rename to src/dex/definitions/minswap-v1/order.ts diff --git a/src/dex/definitions/minswap/pool.ts b/src/dex/definitions/minswap-v1/pool.ts similarity index 100% rename from src/dex/definitions/minswap/pool.ts rename to src/dex/definitions/minswap-v1/pool.ts diff --git a/src/dex/definitions/wingriders/order.ts b/src/dex/definitions/wingriders-v1/order.ts similarity index 100% rename from src/dex/definitions/wingriders/order.ts rename to src/dex/definitions/wingriders-v1/order.ts diff --git a/src/dex/definitions/wingriders/pool.ts b/src/dex/definitions/wingriders-v1/pool.ts similarity index 100% rename from src/dex/definitions/wingriders/pool.ts rename to src/dex/definitions/wingriders-v1/pool.ts diff --git a/src/dex/minswap-v2.ts b/src/dex/minswap-v2.ts index 3415ee9..9a1a8de 100644 --- a/src/dex/minswap-v2.ts +++ b/src/dex/minswap-v2.ts @@ -1,36 +1,25 @@ -import { LiquidityPool } from './models/liquidity-pool'; -import { BaseDataProvider } from '@providers/data/base-data-provider'; -import { Asset, Token } from './models/asset'; import { BaseDex } from './base-dex'; import { - AssetAddress, - AssetBalance, DatumParameters, - DefinitionConstr, - DefinitionField, - PayToAddress, RequestConfig, + PayToAddress, SpendUTxO, SwapFee, UTxO } from '@app/types'; import { DefinitionBuilder } from '@app/definition-builder'; -import { correspondingReserves, lucidUtils } from '@app/utils'; +import { correspondingReserves, lucidUtils, tokensMatch } from '@app/utils'; import { AddressType, DatumParameterKey } from '@app/constants'; import order from '@dex/definitions/minswap-v2/order'; -import { BaseApi } from '@dex/api/base-api'; -import pool from '@dex/definitions/minswap-v2/pool'; import { AddressDetails, Script } from 'lucid-cardano'; +import { LiquidityPool, Token } from '@indigo-labs/iris-sdk'; export class MinswapV2 extends BaseDex { public static readonly identifier: string = 'MinswapV2'; - public readonly api: BaseApi; /** * On-Chain constants. */ - public readonly lpTokenPolicyId: string = 'f5808c2c990d86da54bfc97d89cee6efa20cd8461616359478d96b4c'; - public readonly poolValidityAsset: string = 'f5808c2c990d86da54bfc97d89cee6efa20cd8461616359478d96b4c4d5350'; public readonly orderScriptHash: string = 'c3e28c36c3447315ba5a56f33da6a6ddc1770a876a8d9f0cb3a97c4c'; public readonly cancelDatum: string = 'd87a80'; public readonly orderScript: Script = { @@ -38,110 +27,12 @@ export class MinswapV2 extends BaseDex { script: '590a600100003332323232323232323222222533300832323232533300c3370e900118058008991919299980799b87480000084cc004dd5980a180a980a980a980a980a980a98068030060a99980799b87480080084c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c94ccc080cdc3a4000002264646600200200e44a66604c00229404c8c94ccc094cdc78010028a51133004004001302a002375c60500026eb8c094c07800854ccc080cdc3a40040022646464646600200202844a66605000229404c8c94ccc09ccdd798161812981618129816181698128010028a51133004004001302c002302a0013374a9001198131ba90014bd701bae3026001301e002153330203370e900200089980900419ba548000cc090cdd2a400466048604a603c00497ae04bd70099981019b87375a6044604a66446464a66604866e1d200200114bd6f7b63009bab302930220023022001323300100100322533302700114c103d87a800013232323253330283371e00e004266e9520003302c374c00297ae0133006006003375660520066eb8c09c008c0ac008c0a4004c8cc004004030894ccc09400452f5bded8c0264646464a66604c66e3d22100002100313302a337606ea4008dd3000998030030019bab3027003375c604a0046052004604e0026eb8c094c07800920004a0944c078004c08c004c06c060c8c8c8c8c8c8c94ccc08ccdc3a40000022646464646464646464646464646464646464a6660706076004264646464646464649319299981e99b87480000044c8c94ccc108c1140084c92632375a60840046eb4c10000458c8cdd81822000982218228009bac3043001303b0091533303d3370e90010008a999820181d8048a4c2c2c607601064a66607866e1d2000001132323232323232325333047304a002132498c09401458cdc3a400460886ea8c120004c120008dd6982300098230011822000982200119b8748008c0f8dd51821000981d0060a99981e19b87480080044c8c8c8c8c8c94ccc114c1200084c926302300316375a608c002608c0046088002608800466e1d2002303e3754608400260740182a66607866e1d2004001132323232323232325333047304a002132498c09401458dd6982400098240011bad30460013046002304400130440023370e9001181f1baa3042001303a00c1533303c3370e9003000899191919191919192999823982500109924c604a00a2c66e1d200230443754609000260900046eb4c118004c118008c110004c110008cdc3a4004607c6ea8c108004c0e803054ccc0f0cdc3a40100022646464646464a66608a60900042649319299982199b87480000044c8c8c8c94ccc128c13400852616375a609600260960046eb4c124004c10401854ccc10ccdc3a4004002264646464a666094609a0042930b1bad304b001304b002375a6092002608200c2c608200a2c66e1d200230423754608c002608c0046eb4c110004c110008c108004c0e803054ccc0f0cdc3a401400226464646464646464a66608e60940042649318130038b19b8748008c110dd5182400098240011bad30460013046002375a60880026088004608400260740182a66607866e1d200c001132323232323232325333047304a002132498c09801458cdc3a400460886ea8c120004c120008dd6982300098230011822000982200119b8748008c0f8dd51821000981d0060a99981e19b87480380044c8c8c8c8c8c8c8c8c8c8c8c8c8c94ccc134c14000852616375a609c002609c0046eb4c130004c130008dd6982500098250011bad30480013048002375a608c002608c0046eb4c110004c110008cdc3a4004607c6ea8c108004c0e803054ccc0f0cdc3a4020002264646464646464646464a66609260980042649318140048b19b8748008c118dd5182500098250011bad30480013048002375a608c002608c0046eb4c110004c110008c108004c0e803054ccc0f0cdc3a40240022646464646464a66608a60900042646493181200219198008008031129998238008a4c2646600600660960046464a66608c66e1d2000001132323232533304d3050002132498c0b400c58cdc3a400460946ea8c138004c138008c130004c11000858c110004c12400458dd698230009823001182200098220011bac3042001303a00c1533303c3370e900a0008a99981f981d0060a4c2c2c6074016603a018603001a603001c602c01e602c02064a66606c66e1d200000113232533303b303e002149858dd7181e000981a0090a99981b19b87480080044c8c94ccc0ecc0f800852616375c607800260680242a66606c66e1d200400113232533303b303e002149858dd7181e000981a0090a99981b19b87480180044c8c94ccc0ecc0f800852616375c607800260680242c60680222c607200260720046eb4c0dc004c0dc008c0d4004c0d4008c0cc004c0cc008c0c4004c0c4008c0bc004c0bc008c0b4004c0b4008c0ac004c0ac008c0a4004c08407858c0840748c94ccc08ccdc3a40000022a66604c60420042930b0a99981199b87480080044c8c94ccc0a0c0ac00852616375c605200260420042a66604666e1d2004001132325333028302b002149858dd7181480098108010b1810800919299981119b87480000044c8c8c8c94ccc0a4c0b00084c8c9263253330283370e9000000899192999816981800109924c64a66605666e1d20000011323253330303033002132498c04400458c0c4004c0a400854ccc0accdc3a40040022646464646464a666068606e0042930b1bad30350013035002375a606600260660046eb4c0c4004c0a400858c0a400458c0b8004c09800c54ccc0a0cdc3a40040022a666056604c0062930b0b181300118050018b18150009815001181400098100010b1810000919299981099b87480000044c8c94ccc098c0a400852616375a604e002603e0042a66604266e1d20020011323253330263029002149858dd69813800980f8010b180f800919299981019b87480000044c8c94ccc094c0a000852616375a604c002603c0042a66604066e1d20020011323253330253028002149858dd69813000980f0010b180f000919299980f99b87480000044c8c8c8c94ccc098c0a400852616375c604e002604e0046eb8c094004c07400858c0740048c94ccc078cdc3a400000226464a666046604c0042930b1bae3024001301c0021533301e3370e900100089919299981198130010a4c2c6eb8c090004c07000858c070004dd618100009810000980f8011bab301d001301d001301c00237566034002603400260320026030002602e0046eb0c054004c0340184cc004dd5980a180a980a980a980a980a980a980680300591191980080080191299980a8008a50132323253330153375e00c00229444cc014014008c054008c064008c05c004c03001cc94ccc034cdc3a40000022a666020601600e2930b0a99980699b874800800454ccc040c02c01c526161533300d3370e90020008a99980818058038a4c2c2c601600c2c60200026020004601c002600c00229309b2b118029baa001230033754002ae6955ceaab9e5573eae815d0aba24c126d8799fd87a9f581c1eae96baf29e27682ea3f815aba361a0c6059d45e4bfbe95bbd2f44affff004c0126d8799fd87a9f581cc8b0cc61374d409ff9c8512317003e7196a3e4d48553398c656cc124ffff0001', }; - constructor(requestConfig: RequestConfig = {}) { - super(); - } - - public async liquidityPoolAddresses(provider: BaseDataProvider): Promise { - const validityAsset: Asset = Asset.fromIdentifier(this.poolValidityAsset); - const assetAddresses: AssetAddress[] = await provider.assetAddresses(validityAsset); - - return Promise.resolve([...new Set(assetAddresses.map((assetAddress: AssetAddress) => assetAddress.address))]); - } - - public async liquidityPools(provider: BaseDataProvider): Promise { - const validityAsset: Asset = Asset.fromIdentifier(this.poolValidityAsset); - const poolAddresses: string[] = await this.liquidityPoolAddresses(provider); - - const addressPromises: Promise[] = poolAddresses.map(async (address: string) => { - const utxos: UTxO[] = await provider.utxos(address, validityAsset); - - return await Promise.all( - utxos.map(async (utxo: UTxO) => { - return await this.liquidityPoolFromUtxo(provider, utxo); - }) - ) - .then((liquidityPools: (LiquidityPool | undefined)[]) => { - return liquidityPools.filter((liquidityPool?: LiquidityPool) => { - return liquidityPool !== undefined; - }) as LiquidityPool[] - }); - }); - - return Promise.all(addressPromises) - .then((liquidityPools: (Awaited)[]) => liquidityPools.flat()); - } - - public async liquidityPoolFromUtxo(provider: BaseDataProvider, utxo: UTxO): Promise { - if (! utxo.datumHash) { - return Promise.resolve(undefined); - } - - const relevantAssets: AssetBalance[] = utxo.assetBalances - .filter((assetBalance: AssetBalance) => { - const assetBalanceId: string = assetBalance.asset === 'lovelace' ? 'lovelace' : assetBalance.asset.identifier(); - - return assetBalanceId !== this.poolValidityAsset - && ! assetBalanceId.startsWith(this.lpTokenPolicyId); - }); - - // Irrelevant UTxO - if (relevantAssets.length < 2) { - return Promise.resolve(undefined); - } - - // Could be ADA/X or X/X pool - const assetAIndex: number = relevantAssets.length === 2 ? 0 : 1; - const assetBIndex: number = relevantAssets.length === 2 ? 1 : 2; - - const liquidityPool: LiquidityPool = new LiquidityPool( - MinswapV2.identifier, - relevantAssets[assetAIndex].asset, - relevantAssets[assetBIndex].asset, - relevantAssets[assetAIndex].quantity, - relevantAssets[assetBIndex].quantity, - utxo.address, - '', - '', - ); - - const lpTokenBalance: AssetBalance | undefined = utxo.assetBalances - .find((balance: AssetBalance) => { - return balance.asset !== 'lovelace' - && balance.asset.identifier() !== this.poolValidityAsset - && balance.asset.policyId === this.lpTokenPolicyId; - }); - - if (! lpTokenBalance || ! lpTokenBalance?.asset) return Promise.resolve(undefined); - - liquidityPool.lpToken = lpTokenBalance.asset as Asset; - liquidityPool.identifier = liquidityPool.lpToken.identifier(); - - try { - const builder: DefinitionBuilder = await (new DefinitionBuilder()) - .loadDefinition(pool); - const datum: DefinitionField = await provider.datumValue(utxo.datumHash); - const parameters: DatumParameters = builder.pullParameters(datum as DefinitionConstr); - - // Ignore Zap orders - if (typeof parameters.PoolAssetBPolicyId === 'string' && parameters.PoolAssetBPolicyId === this.lpTokenPolicyId) { - return undefined; - } - - liquidityPool.poolFeePercent = Number(parameters.BaseFee) / 100; - liquidityPool.totalLpTokens = typeof parameters.TotalLpTokens === 'number' - ? BigInt(parameters.TotalLpTokens) - : 0n; - } catch (e) { - return liquidityPool; - } - - return liquidityPool; - } - estimatedGive(liquidityPool: LiquidityPool, swapOutToken: Token, swapOutAmount: bigint): bigint { + if (! liquidityPool.state) return 0n; + const poolFeeMultiplier: bigint = 10000n; - const poolFeeModifier: bigint = poolFeeMultiplier - BigInt(Math.round((liquidityPool.poolFeePercent / 100) * Number(poolFeeMultiplier))); + const poolFeePercent: number = tokensMatch(liquidityPool.tokenA, swapOutToken) ? liquidityPool.state.sellFeePercent : liquidityPool.state.buyFeePercent; + const poolFeeModifier: bigint = poolFeeMultiplier - BigInt(Math.round((poolFeePercent / 100) * Number(poolFeeMultiplier))); const [reserveOut, reserveIn]: bigint[] = correspondingReserves(liquidityPool, swapOutToken); @@ -152,8 +43,11 @@ export class MinswapV2 extends BaseDex { } public estimatedReceive(liquidityPool: LiquidityPool, swapInToken: Token, swapInAmount: bigint): bigint { + if (! liquidityPool.state) return 0n; + const poolFeeMultiplier: bigint = 10000n; - const poolFeeModifier: bigint = poolFeeMultiplier - BigInt(Math.round((liquidityPool.poolFeePercent / 100) * Number(poolFeeMultiplier))); + const poolFeePercent: number = tokensMatch(liquidityPool.tokenA, swapInToken) ? liquidityPool.state.buyFeePercent : liquidityPool.state.sellFeePercent; + const poolFeeModifier: bigint = poolFeeMultiplier - BigInt(Math.round((poolFeePercent / 100) * Number(poolFeeMultiplier))); const [reserveIn, reserveOut]: bigint[] = correspondingReserves(liquidityPool, swapInToken); @@ -164,8 +58,11 @@ export class MinswapV2 extends BaseDex { } public priceImpactPercent(liquidityPool: LiquidityPool, swapInToken: Token, swapInAmount: bigint): number { + if (! liquidityPool.state) return 0; + const poolFeeMultiplier: bigint = 10000n; - const poolFeeModifier: bigint = poolFeeMultiplier - BigInt(Math.round((liquidityPool.poolFeePercent / 100) * Number(poolFeeMultiplier))); + const poolFeePercent: number = tokensMatch(liquidityPool.tokenA, swapInToken) ? liquidityPool.state.buyFeePercent : liquidityPool.state.sellFeePercent; + const poolFeeModifier: bigint = poolFeeMultiplier - BigInt(Math.round((poolFeePercent / 100) * Number(poolFeeMultiplier))); const [reserveIn, reserveOut]: bigint[] = correspondingReserves(liquidityPool, swapInToken); @@ -180,10 +77,12 @@ export class MinswapV2 extends BaseDex { } public async buildSwapOrder(liquidityPool: LiquidityPool, swapParameters: DatumParameters, spendUtxos: SpendUTxO[] = []): Promise { - const batcherFee: SwapFee | undefined = this.swapOrderFees().find((fee: SwapFee) => fee.id === 'batcherFee'); + if (! liquidityPool.lpToken) return Promise.reject('Unknown LP token'); + + const networkFee: SwapFee | undefined = this.swapOrderFees().find((fee: SwapFee) => fee.id === 'networkFee'); const deposit: SwapFee | undefined = this.swapOrderFees().find((fee: SwapFee) => fee.id === 'deposit'); - if (! batcherFee || ! deposit) { + if (! networkFee || ! deposit) { return Promise.reject('Parameters for datum are not set.'); } @@ -195,7 +94,7 @@ export class MinswapV2 extends BaseDex { swapParameters = { ...swapParameters, - [DatumParameterKey.BatcherFee]: batcherFee.value, + [DatumParameterKey.BatcherFee]: 700000n, [DatumParameterKey.LpTokenPolicyId]: liquidityPool.lpToken.policyId, [DatumParameterKey.LpTokenAssetName]: liquidityPool.lpToken.nameHex, [DatumParameterKey.Direction]: swapDirection, @@ -225,7 +124,7 @@ export class MinswapV2 extends BaseDex { assetBalances: [ { asset: 'lovelace', - quantity: batcherFee.value + deposit.value, + quantity: networkFee.value + deposit.value, }, ], datum: datumBuilder.getCbor(), @@ -266,10 +165,10 @@ export class MinswapV2 extends BaseDex { public swapOrderFees(): SwapFee[] { return [ { - id: 'batcherFee', - title: 'Batcher Fee', - description: 'Fee paid for the service of off-chain Laminar batcher to process transactions.', - value: 2_000000n, + id: 'networkFee', + title: 'Network Fee', + description: 'The fee paid to the Cardano network to process a transaction.', + value: 700000n, isReturned: false, }, { diff --git a/src/dex/minswap.ts b/src/dex/minswap.ts index 477f58d..962fb71 100644 --- a/src/dex/minswap.ts +++ b/src/dex/minswap.ts @@ -1,151 +1,39 @@ -import { LiquidityPool } from './models/liquidity-pool'; -import { BaseDataProvider } from '@providers/data/base-data-provider'; -import { Asset, Token } from './models/asset'; import { BaseDex } from './base-dex'; import { - AssetAddress, - AssetBalance, - DatumParameters, DefinitionConstr, DefinitionField, + DatumParameters, PayToAddress, - RequestConfig, SpendUTxO, + SpendUTxO, SwapFee, UTxO } from '@app/types'; import { DefinitionBuilder } from '@app/definition-builder'; -import { correspondingReserves } from '@app/utils'; +import { correspondingReserves, tokensMatch } from '@app/utils'; import { AddressType, DatumParameterKey } from '@app/constants'; -import order from '@dex/definitions/minswap/order'; -import { BaseApi } from '@dex/api/base-api'; -import { MinswapApi } from '@dex/api/minswap-api'; -import pool from '@dex/definitions/minswap/pool'; +import order from '@dex/definitions/minswap-v1/order'; import { Script } from 'lucid-cardano'; +import { LiquidityPool, Token } from '@indigo-labs/iris-sdk'; export class Minswap extends BaseDex { public static readonly identifier: string = 'Minswap'; - public readonly api: BaseApi; /** * On-Chain constants. */ public readonly marketOrderAddress: string = 'addr1wxn9efv2f6w82hagxqtn62ju4m293tqvw0uhmdl64ch8uwc0h43gt'; public readonly limitOrderAddress: string = 'addr1zxn9efv2f6w82hagxqtn62ju4m293tqvw0uhmdl64ch8uw6j2c79gy9l76sdg0xwhd7r0c0kna0tycz4y5s6mlenh8pq6s3z70'; - public readonly lpTokenPolicyId: string = 'e4214b7cce62ac6fbba385d164df48e157eae5863521b4b67ca71d86'; - public readonly poolNftPolicyId: string = '0be55d262b29f564998ff81efe21bdc0022621c12f15af08d0f2ddb1'; - public readonly poolValidityAsset: string = '13aa2accf2e1561723aa26871e071fdf32c867cff7e7d50ad470d62f4d494e53574150'; public readonly cancelDatum: string = 'd87a80'; public readonly orderScript: Script = { type: 'PlutusV1', script: '59014f59014c01000032323232323232322223232325333009300e30070021323233533300b3370e9000180480109118011bae30100031225001232533300d3300e22533301300114a02a66601e66ebcc04800400c5288980118070009bac3010300c300c300c300c300c300c300c007149858dd48008b18060009baa300c300b3754601860166ea80184ccccc0288894ccc04000440084c8c94ccc038cd4ccc038c04cc030008488c008dd718098018912800919b8f0014891ce1317b152faac13426e6a83e06ff88a4d62cce3c1634ab0a5ec133090014a0266008444a00226600a446004602600a601a00626600a008601a006601e0026ea8c03cc038dd5180798071baa300f300b300e3754601e00244a0026eb0c03000c92616300a001375400660106ea8c024c020dd5000aab9d5744ae688c8c0088cc0080080048c0088cc00800800555cf2ba15573e6e1d200201', }; - constructor(requestConfig: RequestConfig = {}) { - super(); - - this.api = new MinswapApi(this, requestConfig); - } - - public async liquidityPoolAddresses(provider: BaseDataProvider): Promise { - const validityAsset: Asset = Asset.fromIdentifier(this.poolValidityAsset); - const assetAddresses: AssetAddress[] = await provider.assetAddresses(validityAsset); - - return Promise.resolve([...new Set(assetAddresses.map((assetAddress: AssetAddress) => assetAddress.address))]); - } - - public async liquidityPools(provider: BaseDataProvider): Promise { - const validityAsset: Asset = Asset.fromIdentifier(this.poolValidityAsset); - const poolAddresses: string[] = await this.liquidityPoolAddresses(provider); - - const addressPromises: Promise[] = poolAddresses.map(async (address: string) => { - const utxos: UTxO[] = await provider.utxos(address, validityAsset); - - return await Promise.all( - utxos.map(async (utxo: UTxO) => { - return await this.liquidityPoolFromUtxo(provider, utxo); - }) - ) - .then((liquidityPools: (LiquidityPool | undefined)[]) => { - return liquidityPools.filter((liquidityPool?: LiquidityPool) => { - return liquidityPool !== undefined; - }) as LiquidityPool[] - }); - }); - - return Promise.all(addressPromises) - .then((liquidityPools: (Awaited)[]) => liquidityPools.flat()); - } - - public async liquidityPoolFromUtxo(provider: BaseDataProvider, utxo: UTxO): Promise { - if (! utxo.datumHash) { - return Promise.resolve(undefined); - } - - const relevantAssets: AssetBalance[] = utxo.assetBalances - .filter((assetBalance: AssetBalance) => { - const assetBalanceId: string = assetBalance.asset === 'lovelace' ? 'lovelace' : assetBalance.asset.identifier(); - - return assetBalanceId !== this.poolValidityAsset - && ! assetBalanceId.startsWith(this.lpTokenPolicyId) - && ! assetBalanceId.startsWith(this.poolNftPolicyId); - }); - - // Irrelevant UTxO - if (relevantAssets.length < 2) { - return Promise.resolve(undefined); - } - - // Could be ADA/X or X/X pool - const assetAIndex: number = relevantAssets.length === 2 ? 0 : 1; - const assetBIndex: number = relevantAssets.length === 2 ? 1 : 2; - - const liquidityPool: LiquidityPool = new LiquidityPool( - Minswap.identifier, - relevantAssets[assetAIndex].asset, - relevantAssets[assetBIndex].asset, - relevantAssets[assetAIndex].quantity, - relevantAssets[assetBIndex].quantity, - utxo.address, - this.marketOrderAddress, - this.limitOrderAddress, - ); - - // Load additional pool information - const poolNft: Asset | undefined = utxo.assetBalances.find((assetBalance: AssetBalance) => { - return assetBalance.asset !== 'lovelace' && assetBalance.asset.policyId === this.poolNftPolicyId; - })?.asset as Asset; - - if (! poolNft) return undefined; - - liquidityPool.lpToken = new Asset(this.lpTokenPolicyId, poolNft.nameHex); - liquidityPool.identifier = liquidityPool.lpToken.identifier(); - liquidityPool.poolFeePercent = 0.3; - - try { - liquidityPool.poolFeePercent = 0.3; - - const builder: DefinitionBuilder = await (new DefinitionBuilder()) - .loadDefinition(pool); - const datum: DefinitionField = await provider.datumValue(utxo.datumHash); - const parameters: DatumParameters = builder.pullParameters(datum as DefinitionConstr); - - // Ignore Zap orders - if (typeof parameters.PoolAssetBPolicyId === 'string' && parameters.PoolAssetBPolicyId === this.lpTokenPolicyId) { - return undefined; - } - - liquidityPool.totalLpTokens = typeof parameters.TotalLpTokens === 'number' - ? BigInt(parameters.TotalLpTokens) - : 0n; - } catch (e) { - return liquidityPool; - } - - return liquidityPool; - } - estimatedGive(liquidityPool: LiquidityPool, swapOutToken: Token, swapOutAmount: bigint): bigint { + if (! liquidityPool.state) return 0n; + const poolFeeMultiplier: bigint = 10000n; - const poolFeeModifier: bigint = poolFeeMultiplier - BigInt(Math.round((liquidityPool.poolFeePercent / 100) * Number(poolFeeMultiplier))); + const poolFeePercent: number = tokensMatch(liquidityPool.tokenA, swapOutToken) ? liquidityPool.state.sellFeePercent : liquidityPool.state.buyFeePercent; + const poolFeeModifier: bigint = poolFeeMultiplier - BigInt(Math.round((poolFeePercent / 100) * Number(poolFeeMultiplier))); const [reserveOut, reserveIn]: bigint[] = correspondingReserves(liquidityPool, swapOutToken); @@ -156,8 +44,11 @@ export class Minswap extends BaseDex { } public estimatedReceive(liquidityPool: LiquidityPool, swapInToken: Token, swapInAmount: bigint): bigint { + if (! liquidityPool.state) return 0n; + const poolFeeMultiplier: bigint = 10000n; - const poolFeeModifier: bigint = poolFeeMultiplier - BigInt(Math.round((liquidityPool.poolFeePercent / 100) * Number(poolFeeMultiplier))); + const poolFeePercent: number = tokensMatch(liquidityPool.tokenA, swapInToken) ? liquidityPool.state.buyFeePercent : liquidityPool.state.sellFeePercent; + const poolFeeModifier: bigint = poolFeeMultiplier - BigInt(Math.round((poolFeePercent / 100) * Number(poolFeeMultiplier))); const [reserveIn, reserveOut]: bigint[] = correspondingReserves(liquidityPool, swapInToken); @@ -168,8 +59,11 @@ export class Minswap extends BaseDex { } public priceImpactPercent(liquidityPool: LiquidityPool, swapInToken: Token, swapInAmount: bigint): number { + if (! liquidityPool.state) return 0; + const poolFeeMultiplier: bigint = 10000n; - const poolFeeModifier: bigint = poolFeeMultiplier - BigInt(Math.round((liquidityPool.poolFeePercent / 100) * Number(poolFeeMultiplier))); + const poolFeePercent: number = tokensMatch(liquidityPool.tokenA, swapInToken) ? liquidityPool.state.buyFeePercent : liquidityPool.state.sellFeePercent; + const poolFeeModifier: bigint = poolFeeMultiplier - BigInt(Math.round((poolFeePercent / 100) * Number(poolFeeMultiplier))); const [reserveIn, reserveOut]: bigint[] = correspondingReserves(liquidityPool, swapInToken); @@ -184,16 +78,16 @@ export class Minswap extends BaseDex { } public async buildSwapOrder(liquidityPool: LiquidityPool, swapParameters: DatumParameters, spendUtxos: SpendUTxO[] = []): Promise { - const batcherFee: SwapFee | undefined = this.swapOrderFees().find((fee: SwapFee) => fee.id === 'batcherFee'); + const networkFee: SwapFee | undefined = this.swapOrderFees().find((fee: SwapFee) => fee.id === 'networkFee'); const deposit: SwapFee | undefined = this.swapOrderFees().find((fee: SwapFee) => fee.id === 'deposit'); - if (! batcherFee || ! deposit) { + if (! networkFee || ! deposit) { return Promise.reject('Parameters for datum are not set.'); } swapParameters = { ...swapParameters, - [DatumParameterKey.BatcherFee]: batcherFee.value, + [DatumParameterKey.BatcherFee]: networkFee.value, [DatumParameterKey.DepositFee]: deposit.value, }; @@ -212,7 +106,7 @@ export class Minswap extends BaseDex { assetBalances: [ { asset: 'lovelace', - quantity: batcherFee.value + deposit.value, + quantity: networkFee.value + deposit.value, }, ], datum: datumBuilder.getCbor(), @@ -251,10 +145,10 @@ export class Minswap extends BaseDex { public swapOrderFees(): SwapFee[] { return [ { - id: 'batcherFee', - title: 'Batcher Fee', - description: 'Fee paid for the service of off-chain Laminar batcher to process transactions.', - value: 2_000000n, + id: 'networkFee', + title: 'Network Fee', + description: 'The fee paid to the Cardano network to process a transaction.', + value: 900000n, isReturned: false, }, { diff --git a/src/dex/models/asset.ts b/src/dex/models/asset.ts deleted file mode 100644 index 614bd53..0000000 --- a/src/dex/models/asset.ts +++ /dev/null @@ -1,33 +0,0 @@ -export class Asset { - - public policyId: string; - public nameHex: string; - public decimals: number; - - constructor(policyId: string, nameHex: string, decimals: number = 0) { - this.policyId = policyId; - this.nameHex = nameHex; - this.decimals = decimals; - } - - static fromIdentifier(id: string, decimals: number = 0): Asset { - id = id.replace('.', ''); - - return new Asset( - id.slice(0, 56), - id.slice(56), - decimals, - ); - } - - identifier(dilimeter: '' | '.' = ''): string { - return this.policyId + dilimeter + this.nameHex; - } - - get assetName(): string { - return Buffer.from(this.nameHex, 'hex').toString(); - } - -} - -export type Token = Asset | 'lovelace'; diff --git a/src/dex/models/liquidity-pool.ts b/src/dex/models/liquidity-pool.ts deleted file mode 100644 index e5039a2..0000000 --- a/src/dex/models/liquidity-pool.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { Asset, Token } from './asset'; - -export class LiquidityPool { - - dex: string; - assetA: Token; - assetB: Token; - reserveA: bigint; - reserveB: bigint; - address: string; - marketOrderAddress: string; - limitOrderAddress: string; - - lpToken: Asset; - poolNft: Asset; - identifier: string = ''; - poolFeePercent: number = 0; - totalLpTokens: bigint = 0n; - extra: any = {}; - - constructor(dex: string, assetA: Token, assetB: Token, reserveA: bigint, reserveB: bigint, address: string, marketOrderAddress: string = '', limitOrderAddress: string = '') { - this.dex = dex; - this.assetA = assetA; - this.assetB = assetB; - this.reserveA = reserveA; - this.reserveB = reserveB; - this.address = address; - this.marketOrderAddress = marketOrderAddress; - this.limitOrderAddress = limitOrderAddress; - } - - get uuid(): string { - return `${this.dex}.${this.pair}.${this.identifier}`; - } - - get pair(): string { - const assetAName: string = this.assetA === 'lovelace' ? 'ADA' : this.assetA.assetName; - const assetBName: string = this.assetB === 'lovelace' ? 'ADA' : this.assetB.assetName; - - return `${assetAName}/${assetBName}`; - } - - get price(): number { - const assetADecimals: number = this.assetA === 'lovelace' ? 6 : this.assetA.decimals; - const assetBDecimals: number = this.assetB === 'lovelace' ? 6 : this.assetB.decimals; - - const adjustedReserveA: number = Number(this.reserveA) / (10**assetADecimals); - const adjustedReserveB: number = Number(this.reserveB) / (10**assetBDecimals); - - return adjustedReserveA / adjustedReserveB; - } - - get totalValueLocked(): number { - const assetADecimals: number = this.assetA === 'lovelace' ? 6 : this.assetA.decimals; - const assetBDecimals: number = this.assetB === 'lovelace' ? 6 : this.assetB.decimals; - - if (this.assetA === 'lovelace') { - return (Number(this.reserveA) / 10**assetADecimals) + ((Number(this.reserveB) / 10**assetBDecimals) * this.price); - } - - return ((Number(this.reserveA) / 10**assetADecimals) * this.price) * ((Number(this.reserveB) / 10**assetBDecimals) * (1 / this.price)); - } - -} diff --git a/src/dex/muesliswap.ts b/src/dex/muesliswap.ts index e2f88b9..ae74492 100644 --- a/src/dex/muesliswap.ts +++ b/src/dex/muesliswap.ts @@ -1,159 +1,50 @@ import { BaseDex } from './base-dex'; import { - AssetAddress, - AssetBalance, DatumParameters, - DefinitionConstr, - DefinitionField, PayToAddress, - RequestConfig, SpendUTxO, + SpendUTxO, SwapFee, UTxO } from '@app/types'; -import { Asset, Token } from './models/asset'; -import { LiquidityPool } from './models/liquidity-pool'; -import { BaseDataProvider } from '@providers/data/base-data-provider'; import { DefinitionBuilder } from '@app/definition-builder'; import { correspondingReserves, tokensMatch } from '@app/utils'; import { AddressType, DatumParameterKey } from '@app/constants'; -import pool from '@dex/definitions/muesliswap/pool'; import order from '@dex/definitions/muesliswap/order'; -import { BaseApi } from '@dex/api/base-api'; -import { MuesliSwapApi } from '@dex/api/muesliswap-api'; import { Script } from 'lucid-cardano'; +import { LiquidityPool, Token } from '@indigo-labs/iris-sdk'; export class MuesliSwap extends BaseDex { public static readonly identifier: string = 'MuesliSwap'; - public readonly api: BaseApi; /** * On-Chain constants. */ public readonly orderAddress: string = 'addr1zyq0kyrml023kwjk8zr86d5gaxrt5w8lxnah8r6m6s4jp4g3r6dxnzml343sx8jweqn4vn3fz2kj8kgu9czghx0jrsyqqktyhv'; - public readonly lpTokenPolicyId: string = 'af3d70acf4bd5b3abb319a7d75c89fb3e56eafcdd46b2e9b57a2557f'; - public readonly poolNftPolicyIdV1: string = '909133088303c49f3a30f1cc8ed553a73857a29779f6c6561cd8093f'; - public readonly poolNftPolicyIdV2: string = '7a8041a0693e6605d010d5185b034d55c79eaf7ef878aae3bdcdbf67'; - public readonly factoryToken: string = 'de9b756719341e79785aa13c164e7fe68c189ed04d61c9876b2fe53f4d7565736c69537761705f414d4d'; public readonly cancelDatum: string = 'd87980'; public readonly orderScript: Script = { type: 'PlutusV2', script: '59152a010000323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323223232323232322232323232323232323232533355333573460d000226464646424446600200a0086eb4d5d09aba2003355333573460d060da0022660a06eb4d5d098360009bad357426ae88c1b000458c1b88894ccd5cd18358008b0a999ab9a337100029000099801983500118350008991982a19b8400300133708004002660ce0040026ea8d5d080098350010a999ab9a306700113212223002004375a6ae84c1a800854ccd5cd18330008220b099180e1a9a805030911111111111299a999aa983583601892999ab9a3371e01c002260c80020c400840d20c2a020426038660946010002660946603a666aa60b40c06a0340c26a0340c4666aa60b40c044a66a6a0044444a66a6605060a4030008260ba0060b642660c200200420020ba60546a0140c2660366660486a01e0c26a01e0c460460246660486a01e0c26a01e0c466604c6a0120886a01e0c26a01e0c4660946008a0226020a00a4426464646464646046660a2601e00e660a2603e032660a2602ea018660a26016a030660a26a01044666ae68cdc499b8200248008cdc1240000020be0cc660a26a0104426ae68cdc419b8200248008cdc1011000998289982899814982980c98298029982899827981d00c981d0029982899827981700c98170029982899827980e00c980e0029982899827980e80c980e802a99a980f80c88020a99a80202e031998289a9980f1a804111919191982d99b8400300133708004002660dc00400266e0808c008cdc099b8202200133704004044660ac60540329001112999ab9a3370e00a0042660760440020bc66048660446a00c0d26660560040026a6a6603c010660ac66605a6a0200960040029001111982c19b84002001330583370a0040020020d0660446a0200966660566a02c0d06a02c0d26a6603c660ac6054032900100438435014068350130663027002301b00135001063533553353500b22350022222222222223333500d206620662066233355306f070035235001225335330470020041306a00306800d2135001223500122223501222350022222222222223335530700762235002222253353303e01800413307a006005100507300a16162215335001133052300a00235002204a2216306a00137540144666aa60b80ba604a04c400266aa60b00ba46a00244446a0084466a0044a666ae68cdc78048008a999a80282d102d90a99a9981a0009a80803390a99a9999999aba40012325333573460e060ea0022646666aae7c00481848cccd55cf9aba2002253353039357420064260c82460020040c240c40d60d460e80020bc6ea8008817881788178817819c84cc140d4004800522010f4d7565736c69537761705f76322e320005c05b061206230273500705e13306822533500105922132533553353035303735003062215335007213304a00200105615335006205605c15335333049034350030613500922200113305e30073500306200110011001300400130313500505c30513500304025333535001203f16216215335330290013500505c21533533333335748002464a666ae68c194c1a80044c8cccd55cf800902b11999aab9f35744004464a66a6666666ae900048c94ccd5cd183598380008991999aab9f001205c23233335573e00240bc4646666aae7c00481808c8cccd55cf80090311191999aab9f001206423233335573e00240cc4646666aae7c00481a08c8cccd55cf800903511999aab9f35744004464a66aa66aa66aa66aa66aa66aa66aa66a6666666ae900048c94ccd5cd183f9842008008991999aab9f001207023233335573e00240e446666aae7cd5d10011299a98241aba1005213253353333333574800246464a666ae68c224040044cccd55cf984680801103c91999aab9f35744611c02006464a66a6666666ae900048c8c94ccd5cd18480080089999aab9f309301002207f23233335573e0024102024646666aae7c004820c048cccd55cf9aba200225335305a3574261320201042a66a60b66ae84018854cd4c170d5d0802909844009998410080180100084280842008418090420084680846009aba200208a0135744612802006110022a666ae68c23c040044cccd55cf984980801103f91999aab9f357446128020064a66a60aa6ae84c2540401084c20804c208040041fc82000422404220041f4c24c04004dd5001103e103e103e103e0428090983e983e80083d1aba1308f01004207a083010820115333573461140200226666aae7cc234040088c1e81e481e4208041dcc23404004dd5001103b103b103b103b03f90983b9983780180083a1aba1004072207307c07b357440040f26106020020da6ea800881b481b481b481b41d884c1b8c1bc0041ac854cd4c110d5d0808909837980100083603590a99a98221aba100f21306f300200106c06b21533530443574201a4260de60040020d80d642a66a60886ae8402c84c1bcc0080041b01ac854cd4c10cd5d080490983798010008360359099299a9999999aba4001232325333573461060200226666aae7cc218040088c1cc1e481c81ec54ccd5cd18410080089999aab9f30860100223073072207207b070308601001375400440de40de40de40de0f04260e060060020da6ae8401c1ac854cd4c10cd5d080290983798010008360359aba1011206b074073357440040e26ae880081bcd5d10010369aba200206b357440040d26ae8800819cd5d1001032983780082c9baa002205920592059205906221305a305c0010573574200640ae0c00be60d20020a66ea8008814c814c814c814c17084d4004800458588c8d4d4d401016c888818888d40048c894ccd54ccd4018854ccd4010854ccd402084c0140c44c0100c054ccd401484c0140c44c0100c011810c54ccd401c84c0100c04c00c0bc54ccd401084c0100c04c00c0bc11454ccd400c810811010454ccd400c854ccd401c84c0100c04c00c0bc54ccd401084c0100c04c00c0bc11410854ccd401884c00c0bc4c0080b854ccd400c84c00c0bc4c0080b811054cd400415016c16c15094ccd4008854ccd4018854ccd401084ccc0d00c400800458585810854ccd4014854ccd400c84ccc0cc0c0008004585858104100c100ccc198888c94ccd5cd19b87003371a002200426600866e0000d20023370066e080092080043371c002006a66a660d244a66a0020a64426a00444a666ae68cdc78012451c5817c34e5702473304f3cf676299176d3824e55b8c0bfa94830429fd001305900113006003353533533069221225333573466e2000520001615335002162215333573460d20062004266a600c0c400266e0400d200205c30323500605d00405e204321533500116221350022253350031002221616480012000350012233335001262626232533530303032001213212333001003002005350022043163330672225335002162213500222533533035002005100113300700300530303500405b0015333573460ba60c400226464642466002006004606c6ae84d5d11831801a999ab9a305e3063001132323232323232323232323232323232323232323232321233333333333300101801601401201000e00c009007005003002304e357426ae88008ccc121d710009aba10013574400466608c09040026ae84004d5d100119822bae357420026ae8800d4ccd5cd1836983900089919191909198008020012999ab9a307030750011330583304175a6ae84c1d0004c158d5d09aba230740011637546ae84d5d11839801a999ab9a306e30730011323212330010030023055357426ae88c1cc008cc0fdd69aba130720011637546ae84c1c400458dd51aba10013574400466607e0a6eb4d5d08009aba20023303e040357420026ae88008ccc0edd701d1aba100135744004666072eb80e0d5d08009aba200233038035357420026ae88008cc0d80c8d5d08009aba23063002330340303574260c40022c6ea8d5d098308008b1baa00133041300700430080043304030240033018003305d22533500104e2213303e33303d03c303f3040002500530040011303a303b001355333573460aa60b40022646090a666ae68c158c16c0044c8c8c8c8c8c8cccccccc134c10cd5d098300039bae3574200c6eb8d5d08029bae357420086eb8d5d08019bad3574200460846ae84004dd69aba1357440026ae88004d5d10009aba2001357440026ae88004d5d1182d0008b1baa3574260b20022c40026ea80048d40041408d4004814488d400888d400c88c8c8c8cc104cdc200100099b84003001330540010023370400a00666e0800c0048d4004888880c9200233035001043223355304204723500122330390023355304504a235001223303c0023335001370090003802337000029000000998028010009299a8008890008b11199aa9822022980680711a80091199aa9823824180800891a80091199a80091980ea400000203846603a0029000000998018010009119aa981f82211a800911981b001199a800919aa982182411a800911981d001181900080091199804018801000919aa982182411a800911981d0011806000800999801816001000911199aa981f02202119aa981f82211a800911981b0011817000999aa981f022111a80111299a999aa98238241981b91199805025801000980402511a8009119805001002803080189982300200182080099aa981f82211a800911981b0011982a11299a800898050019109a80111299a9980600100408911198010050020980300180200111980091299a80101f880081b909111800802111a801111a801911919a802919a80212999ab9a3371e004002006078407a466a008407a4a666ae68cdc780100080181e0a99a80190a99a8011099a801119a801119a801119a8011198190010009020119a801102011981900100091102011119a80210201112999ab9a3370e00c0062a666ae68cdc380280109980f00200082082081d0a99a800901d02011a800911110149111981e998170019981e9981700100081e01e1981511299a801108018800818911198251119a800a4000446a00444a666ae68cdc78010040998281119a800a4000446a00444a666ae68cdc78010068800898030018008980300180191a8009111111100311981411199a80181e0010009a80081d891980081101a91a80091111111111100511999999aba40012323253335734608200226666aae7cc11000880c08cccd55cf9aba2304500325335300835742608c008426066605e00206040620740722a666ae68c1000044cccd55cf9822001101811999aab9f35744608a0064a66a60106ae84c11801084c0ccc0cc0040c080c40e80e40b8c110004dd5001101690169016901681b11999999aba4001202c202c202c2302d375a004405806a46666666ae9000480ac80ac80ac80ac8c0b0dd700101a111a8009111111111111982691299a80081b9109a801112999ab9a3371e0040282607a0022600c006004930919999999800801912999ab9a3370e0040020302a666ae68cdc480100080a80b1109ab9a337100040024426ae68cdc480100091199ab9a3371200400205206000444a666ae68cdc480100088008801112999ab9a337120040022004200244666ae68cdc40010008138171109ab9a3370e00400246a0024444444400e44a666ae68cdc79a8010179a800817889ab9a3370e6a0040606a00206004646a0024466a004404a04a46a00244444444444401846a0024444008446464a666ae68c0d400403854ccd5cd181a0008980998021aba13037002153335734606600201e2c606e0026ea80048c94ccd5cd1818181a80089919091980080180118021aba135744606a00460126ae84c0d000458dd50009192999ab9a302f3034001132323232323232321233330010090070030023302375c6ae84d5d10022999ab9a3037001132122230020043574260720042a666ae68c0d80044c84888c004010dd71aba13039002153335734606a0020262c60720026ea8d5d08009aba200233300675c00a6ae84004d5d1181a001180b1aba1303300116375400266002eb9d69111981a111999aab9f0012027232330293301a30073037001300630360013004357440066ae840080a4dd58009119819111999aab9f001202523302630053574200460066ae8800809cdd6000919192999ab9a302f00113212222300400530043574260600042a666ae68c0b80044c848888c008014c054d5d098180010a999ab9a302d00113212222300100530053574260600042a666ae68c0b00044c848888c00c014dd71aba13030002163030001375400246464a666ae68cdc3a401800222444401c2a666ae68cdc3a4014002220522a666ae68cdc3a40100022646424444444660020120106eb4d5d09aba23030003375c6ae84c0bc00854ccd5cd18170008991909111111198010048041bae357426ae88c0c000cdd71aba1302f002153335734605a00226464244444446600c0120106eb8d5d09aba23030003301435742605e0042a666ae68c0b00044c848888888c01c020c050d5d098178010a999ab9a302b001132122222223005008301435742605e0042c605e0026ea80048c94ccd5cd181498170008991909198008018011bad357426ae88c0b8008c00cd5d098168008b1baa001232533357346050605a00226eb8d5d098160008b1baa0011122200111001222002110012220032122230030042213573466e3c0080048894cd4cc00c00800403c058894cd400840040348d400488cd40088004988d4004888888880208c94ccd5cd180e8008088a999ab9a301c00100a1630203754002464a666ae68c06cc0800044cc00cc018d5d0980f800998040021aba135744603e0022c6ea80048848cc00400c0088c8c94ccd5cd180d8008991998029bad35742603e0066eb4d5d08009bad357426ae88004d5d1180f0010a999ab9a301a0011300a300535742603c0042c603c0026ea8004888488ccc00401401000c8c8c94ccd5cd180c800898021bae3574260380042a666ae68c0600044c020dd71aba1301c00216301c001375400242446002006446464a666ae68c05c0044c01cc010d5d0980d8010a999ab9a301800100516301b0013754002200220184244600400644444444246666666600201201000e00c00a008006004424600200460264422444a66a00220044426600a004666aa600e01a00a0080026024442244a66a00200a44266012600800466aa600c016008002200220084424466002008006601c4422444a66a00226a006010442666a00a0126008004666aa600e01000a0080022400244004440026014444a666ae68c01c00440084cc00c004cdc30010009111111100291111110021b8148000dc3a40006e1d2002370e90021b874801955cf2ab9d23230010012233003300200200101', }; - constructor(requestConfig: RequestConfig = {}) { - super(); - - this.api = new MuesliSwapApi(this, requestConfig); - } - - public async liquidityPoolAddresses(provider: BaseDataProvider): Promise { - const validityAsset: Asset = Asset.fromIdentifier(this.factoryToken); - const assetAddresses: AssetAddress[] = await provider.assetAddresses(validityAsset); - - return Promise.resolve([...new Set(assetAddresses.map((assetAddress: AssetAddress) => assetAddress.address))]); - } - - async liquidityPools(provider: BaseDataProvider): Promise { - const validityAsset: Asset = Asset.fromIdentifier(this.factoryToken); - const poolAddresses: string[] = await this.liquidityPoolAddresses(provider); - - const addressPromises: Promise[] = poolAddresses.map(async (address: string) => { - const utxos: UTxO[] = await provider.utxos(address, validityAsset); - - return await Promise.all( - utxos.map(async (utxo: UTxO): Promise => { - return await this.liquidityPoolFromUtxo(provider, utxo); - }) - ) - .then((liquidityPools: (LiquidityPool | undefined)[]) => { - return liquidityPools.filter((liquidityPool?: LiquidityPool): boolean => { - return liquidityPool !== undefined; - }) as LiquidityPool[] - }); - }); - - return Promise.all(addressPromises) - .then((liquidityPools: (Awaited)[]) => liquidityPools.flat()); - } - - public async liquidityPoolFromUtxo(provider: BaseDataProvider, utxo: UTxO): Promise { - if (! utxo.datumHash) { - return Promise.resolve(undefined); - } - - const relevantAssets: AssetBalance[] = utxo.assetBalances.filter((assetBalance: AssetBalance) => { - const assetBalanceId: string = assetBalance.asset === 'lovelace' ? 'lovelace' : assetBalance.asset.identifier(); - - return ! assetBalanceId.startsWith(this.factoryToken.slice(0, 56)) - && ! [this.poolNftPolicyIdV1, this.poolNftPolicyIdV2].includes(assetBalanceId); - }); - - // Irrelevant UTxO - if (relevantAssets.length < 2) { - return Promise.resolve(undefined); - } - - try { - const builder: DefinitionBuilder = await (new DefinitionBuilder()) - .loadDefinition(pool); - const datum: DefinitionField = await provider.datumValue(utxo.datumHash); - const parameters: DatumParameters = builder.pullParameters(datum as DefinitionConstr); - - const tokenA: Token = parameters.PoolAssetAPolicyId - ? new Asset(parameters.PoolAssetAPolicyId as string, parameters.PoolAssetAAssetName as string) - : 'lovelace'; - const tokenB: Token = parameters.PoolAssetBPolicyId - ? new Asset(parameters.PoolAssetBPolicyId as string, parameters.PoolAssetBAssetName as string) - : 'lovelace'; - - const liquidityPool: LiquidityPool = new LiquidityPool( - MuesliSwap.identifier, - tokenA, - tokenB, - relevantAssets.find((balance: AssetBalance) => tokensMatch(tokenA, balance.asset))?.quantity ?? 0n, - relevantAssets.find((balance: AssetBalance) => tokensMatch(tokenB, balance.asset))?.quantity ?? 0n, - utxo.address, - this.orderAddress, - this.orderAddress, - ); - - // Load additional pool information - const lpToken: Asset = utxo.assetBalances.find((assetBalance: AssetBalance) => { - return assetBalance.asset !== 'lovelace' && [this.poolNftPolicyIdV1, this.poolNftPolicyIdV2].includes(assetBalance.asset.policyId); - })?.asset as Asset; - - if (lpToken) { - lpToken.policyId = this.lpTokenPolicyId; - liquidityPool.lpToken = lpToken; - liquidityPool.identifier = lpToken.identifier(); - } - - liquidityPool.totalLpTokens = typeof parameters.TotalLpTokens === 'number' - ? BigInt(parameters.TotalLpTokens) - : 0n; - liquidityPool.poolFeePercent = typeof parameters.LpFee === 'number' - ? parameters.LpFee / 100 - : 0; - - return Promise.resolve(liquidityPool); - } catch (e) { - return Promise.resolve(undefined); - } - } - estimatedGive(liquidityPool: LiquidityPool, swapOutToken: Token, swapOutAmount: bigint): bigint { + if (! liquidityPool.state) return 0n; + const [reserveOut, reserveIn]: bigint[] = correspondingReserves(liquidityPool, swapOutToken); const receive: number = (Number(reserveIn) * Number(reserveOut)) / (Number(reserveOut) - Number(swapOutAmount)) - Number(reserveIn); + const poolFeePercent: number = tokensMatch(liquidityPool.tokenA, swapOutToken) ? liquidityPool.state.sellFeePercent : liquidityPool.state.buyFeePercent; - return BigInt(Math.floor(Number(receive) * (1 + liquidityPool.poolFeePercent / 100))); + return BigInt(Math.floor(Number(receive) * (1 + poolFeePercent / 100))); } estimatedReceive(liquidityPool: LiquidityPool, swapInToken: Token, swapInAmount: bigint): bigint { + if (! liquidityPool.state) return 0n; + const [reserveIn, reserveOut]: bigint[] = correspondingReserves(liquidityPool, swapInToken); - const swapFee: bigint = ((swapInAmount * BigInt(Math.floor(liquidityPool.poolFeePercent * 100))) + BigInt(10000) - 1n) / 10000n; + const poolFeePercent: number = tokensMatch(liquidityPool.tokenA, swapInToken) ? liquidityPool.state.buyFeePercent : liquidityPool.state.sellFeePercent; + const swapFee: bigint = ((swapInAmount * BigInt(Math.floor(poolFeePercent * 100))) + BigInt(10000) - 1n) / 10000n; const adjustedSwapInAmount: bigint = swapInAmount - swapFee; const estimatedReceive: number = Number(reserveOut) - (Number(reserveIn) * Number(reserveOut)) / (Number(reserveIn) + Number(adjustedSwapInAmount)); diff --git a/src/dex/splash.ts b/src/dex/splash.ts index b54a665..5e2de27 100644 --- a/src/dex/splash.ts +++ b/src/dex/splash.ts @@ -1,36 +1,27 @@ -import { LiquidityPool } from './models/liquidity-pool'; -import { BaseDataProvider } from '@providers/data/base-data-provider'; -import { Asset, Token } from './models/asset'; import { BaseDex } from './base-dex'; import { - AssetBalance, DatumParameters, - DefinitionConstr, - DefinitionField, PayToAddress, - RequestConfig, SpendUTxO, + SpendUTxO, SwapFee, UTxO } from '@app/types'; import { DefinitionBuilder } from '@app/definition-builder'; import { AddressType, DatumParameterKey } from '@app/constants'; -import { BaseApi } from '@dex/api/base-api'; -import pool from '@dex/definitions/splash/pool'; import order from '@dex/definitions/splash/order'; import { bytesToHex, correspondingReserves, hexToBytes, lucidUtils, tokensMatch } from '@app/utils'; import { AddressDetails, Script } from 'lucid-cardano'; import { Uint64BE } from 'int64-buffer'; import blake2b from 'blake2b'; -import { SplashApi } from '@dex/api/splash-api'; +import { BaseDataProvider } from '@providers/data/base-data-provider'; +import { Asset, LiquidityPool, Token } from '@indigo-labs/iris-sdk'; -const MAX_INT: bigint = 9_223_372_036_854_775_807n; const EXECUTOR_FEE: bigint = 1100000n; const WORST_ORDER_STEP_COST: bigint = 900000n; export class Splash extends BaseDex { public static readonly identifier: string = 'Splash'; - readonly api: BaseApi; /** * On-Chain constants. @@ -43,114 +34,6 @@ export class Splash extends BaseDex { script: '59042d01000033232323232323222323232232253330093232533300b0041323300100137566022602460246024602460246024601c6ea8008894ccc040004528099299980719baf00d300f301300214a226600600600260260022646464a66601c6014601e6ea80044c94ccc03cc030c040dd5000899191929998090038a99980900108008a5014a066ebcc020c04cdd5001180b180b980b980b980b980b980b980b980b980b98099baa00f3375e600860246ea8c010c048dd5180a98091baa00230043012375400260286eb0c050c054c054c044dd50028b1991191980080080191299980a8008a60103d87a80001323253330143375e6016602c6ea80080144cdd2a40006603000497ae0133004004001301900230170013758600a60206ea8010c04cc040dd50008b180098079baa0052301230130013322323300100100322533301200114a0264a66602066e3cdd7180a8010020a5113300300300130150013758602060226022602260226022602260226022601a6ea8004dd71808180898089808980898089808980898089808980898069baa0093001300c37540044601e00229309b2b19299980598050008a999804180218048008a51153330083005300900114a02c2c6ea8004c8c94ccc01cc010c020dd50028991919191919191919191919191919191919191919191919299981118128010991919191924c646600200200c44a6660500022930991980180198160011bae302a0015333022301f30233754010264646464a666052605800426464931929998141812800899192999816981800109924c64a666056605000226464a66606060660042649318140008b181880098169baa0021533302b3027001132323232323253330343037002149858dd6981a800981a8011bad30330013033002375a6062002605a6ea800858c0acdd50008b181700098151baa0031533302830240011533302b302a37540062930b0b18141baa002302100316302a001302a0023028001302437540102ca666042603c60446ea802c4c8c8c8c94ccc0a0c0ac00852616375a605200260520046eb4c09c004c08cdd50058b180d006180c8098b1bac30230013023002375c60420026042004603e002603e0046eb4c074004c074008c06c004c06c008c064004c064008dd6980b800980b8011bad30150013015002375a60260026026004602200260220046eb8c03c004c03c008dd7180680098049baa0051625333007300430083754002264646464a66601c60220042930b1bae300f001300f002375c601a00260126ea8004588c94ccc01cc0100044c8c94ccc030c03c00852616375c601a00260126ea800854ccc01cc00c0044c8c94ccc030c03c00852616375c601a00260126ea800858c01cdd50009b8748008dc3a4000ae6955ceaab9e5573eae815d0aba24c0126d8799fd87a9f581c96f5c1bee23481335ff4aece32fe1dfa1aa40a944a66d2d6edc9a9a5ffff0001', }; - constructor(requestConfig: RequestConfig = {}) { - super(); - - this.api = new SplashApi(this, requestConfig); - } - - public async liquidityPoolAddresses(provider: BaseDataProvider): Promise { - return Promise.resolve([ - 'addr1x94ec3t25egvhqy2n265xfhq882jxhkknurfe9ny4rl9k6dj764lvrxdayh2ux30fl0ktuh27csgmpevdu89jlxppvrst84slu', - 'addr1x8nz307k3sr60gu0e47cmajssy4fmld7u493a4xztjrll0aj764lvrxdayh2ux30fl0ktuh27csgmpevdu89jlxppvrswgxsta', - 'addr1x8xw6pmmy8jcnpss6sg7za9c5lk2v9nflq684vzxyn70unaj764lvrxdayh2ux30fl0ktuh27csgmpevdu89jlxppvrs4tm5z7', - 'addr1x8cq97k066w4rd37wprvd4qrfxctzlyd6a67us2uv6hnen9j764lvrxdayh2ux30fl0ktuh27csgmpevdu89jlxppvrsgzvahe', - 'addr1xxcdveqw6g88w6cvwkf705xw30gflshu79ljc3ysrmmluadj764lvrxdayh2ux30fl0ktuh27csgmpevdu89jlxppvrscak26z', - 'addr1x8mql508pa9emlqfeh0g6lmlzfmauf55eq49zmta8ny7q04j764lvrxdayh2ux30fl0ktuh27csgmpevdu89jlxppvrs08z9dt', - 'addr1xxw7upjedpkr4wq839wf983jsnq3yg40l4cskzd7dy8eyndj764lvrxdayh2ux30fl0ktuh27csgmpevdu89jlxppvrsgddq74', - 'addr1x8zjsd5fagcwpysv2zklwu69kkqfcpwfvtxpz8s0r5kmakaj764lvrxdayh2ux30fl0ktuh27csgmpevdu89jlxppvrszgx7ef', - 'addr1x92m92cttwgpllls5y4c889splwgujjyy0eccl424nlezm9j764lvrxdayh2ux30fl0ktuh27csgmpevdu89jlxppvrswdesh2', - 'addr1xxg94wrfjcdsjncmsxtj0r87zk69e0jfl28n934sznu95tdj764lvrxdayh2ux30fl0ktuh27csgmpevdu89jlxppvrs2993lw', - 'addr1x9wnm7vle7al9q4aw63aw63wxz7aytnpc4h3gcjy0yufxwaj764lvrxdayh2ux30fl0ktuh27csgmpevdu89jlxppvrs84l0h4', - ]); - } - - async liquidityPools(provider: BaseDataProvider): Promise { - const poolAddresses: string[] = await this.liquidityPoolAddresses(provider); - - const addressPromises: Promise[] = poolAddresses.map(async (address: string) => { - const utxos: UTxO[] = await provider.utxos(address); - - return await Promise.all( - utxos.map(async (utxo: UTxO) => { - return await this.liquidityPoolFromUtxo(provider, utxo); - }) - ).then((liquidityPools: (LiquidityPool | undefined)[]) => { - return liquidityPools.filter((liquidityPool?: LiquidityPool) => { - return liquidityPool !== undefined; - }) as LiquidityPool[]; - }); - - }); - - return Promise.all(addressPromises).then((liquidityPools: Awaited[]) => liquidityPools.flat()); - } - - public async liquidityPoolFromUtxo(provider: BaseDataProvider, utxo: UTxO): Promise { - if (!utxo.datumHash) { - return Promise.resolve(undefined); - } - - const relevantAssets = utxo.assetBalances.filter((assetBalance: AssetBalance) => { - const assetName = assetBalance.asset === 'lovelace' ? 'lovelace' : assetBalance.asset.assetName; - return !assetName?.toLowerCase()?.endsWith('_nft') - && !assetName?.toLowerCase()?.endsWith('_lq'); - }); - - // Irrelevant UTxO - if (![2, 3].includes(relevantAssets.length)) { - return Promise.resolve(undefined); - } - - const assetAIndex: number = relevantAssets.length === 2 ? 0 : 1; - const assetBIndex: number = relevantAssets.length === 2 ? 1 : 2; - - try { - const builder: DefinitionBuilder = await new DefinitionBuilder().loadDefinition(pool); - const datum: DefinitionField = await provider.datumValue(utxo.datumHash); - const parameters: DatumParameters = builder.pullParameters(datum as DefinitionConstr); - - const liquidityPool: LiquidityPool = new LiquidityPool( - Splash.identifier, - parameters.PoolAssetAPolicyId === '' - ? 'lovelace' - : new Asset(parameters.PoolAssetAPolicyId as string, parameters.PoolAssetAAssetName as string), - new Asset(parameters.PoolAssetBPolicyId as string, parameters.PoolAssetBAssetName as string), - relevantAssets[assetAIndex].quantity - BigInt(parameters.PoolAssetATreasury as number), - relevantAssets[assetBIndex].quantity - BigInt(parameters.PoolAssetBTreasury as number), - utxo.address, - '', - '', - ); - - const [lpTokenPolicyId, lpTokenAssetName] = typeof parameters.LpTokenPolicyId === 'string' && typeof parameters.LpTokenAssetName === 'string' - ? [parameters.LpTokenPolicyId, parameters.LpTokenAssetName] - : [null, null]; - const lpTokenBalance: AssetBalance | undefined = utxo.assetBalances.find((assetBalance: AssetBalance) => { - return assetBalance.asset !== 'lovelace' - && assetBalance.asset.policyId === lpTokenPolicyId - && assetBalance.asset.nameHex === lpTokenAssetName; - }); - const nftToken: Asset | undefined = utxo.assetBalances.find((assetBalance) => { - return (assetBalance.asset as Asset).assetName?.toLowerCase()?.endsWith('_nft'); - })?.asset as Asset | undefined; - - if (! lpTokenBalance || ! nftToken) { - return Promise.resolve(undefined); - } - - liquidityPool.poolNft = nftToken; - liquidityPool.lpToken = lpTokenBalance.asset as Asset; - liquidityPool.totalLpTokens = MAX_INT - lpTokenBalance.quantity; - liquidityPool.identifier = liquidityPool.lpToken.identifier(); - liquidityPool.poolFeePercent = typeof parameters.LpFee === 'number' ? (1000 - parameters.LpFee) / 10 : 0.3; - } catch (e) { - return undefined; - } - - return undefined; - } - estimatedGive(liquidityPool: LiquidityPool, swapOutToken: Token, swapOutAmount: bigint): bigint { const [reserveOut, reserveIn]: bigint[] = correspondingReserves(liquidityPool, swapOutToken); @@ -164,14 +47,16 @@ export class Splash extends BaseDex { } priceImpactPercent(liquidityPool: LiquidityPool, swapInToken: Token, swapInAmount: bigint): number { - const reserveIn: bigint = tokensMatch(swapInToken, liquidityPool.assetA) - ? liquidityPool.reserveA - : liquidityPool.reserveB; + if (! liquidityPool.state) return 0; + + const reserveIn: bigint = tokensMatch(swapInToken, liquidityPool.tokenA) + ? liquidityPool.state.reserveA + : liquidityPool.state.reserveB; return (1 - (Number(reserveIn) / Number(reserveIn + swapInAmount))) * 100; } - public async buildSwapOrder(liquidityPool: LiquidityPool, swapParameters: DatumParameters, spendUtxos: SpendUTxO[] = [], dataProvider?: BaseDataProvider): Promise { + public async buildSwapOrder(liquidityPool: LiquidityPool, swapParameters: DatumParameters, spendUtxos: SpendUTxO[] = []): Promise { const batcherFee: SwapFee | undefined = this.swapOrderFees().find((fee: SwapFee) => fee.id === 'batcherFee'); const deposit: SwapFee | undefined = this.swapOrderFees().find((fee: SwapFee) => fee.id === 'deposit'); const minReceive = swapParameters.MinReceive as bigint; @@ -179,11 +64,11 @@ export class Splash extends BaseDex { if (! batcherFee || ! deposit || ! minReceive) { return Promise.reject('Parameters for datum are not set.'); } - if (! dataProvider) { + if (! this.dexter.dataProvider) { return Promise.reject('Data provider is required.'); } - const walletUtxos: UTxO[] = await dataProvider.utxos( + const walletUtxos: UTxO[] = await this.dexter.dataProvider.utxos( swapParameters[DatumParameterKey.Address] as string, swapParameters[DatumParameterKey.SwapInTokenPolicyId] !== '' ? new Asset(swapParameters.SwapInTokenPolicyId as string, swapParameters.SwapInTokenAssetName as string) @@ -205,7 +90,7 @@ export class Splash extends BaseDex { const outDecimals: number = swapOutToken === 'lovelace' ? 6 - : (tokensMatch(swapOutToken, liquidityPool.assetA)) ? (liquidityPool.assetA as Asset).decimals : (liquidityPool.assetB as Asset).decimals; + : (tokensMatch(swapOutToken, liquidityPool.tokenA)) ? (liquidityPool.tokenA as Asset).decimals ?? 0 : (liquidityPool.tokenB as Asset).decimals ?? 0; const [numerator, denominator] = decimalToFractionalImproved(Number(minReceive) / 10**outDecimals); swapParameters = { diff --git a/src/dex/sundaeswap-v3.ts b/src/dex/sundaeswap-v3.ts index ea0416b..0423382 100644 --- a/src/dex/sundaeswap-v3.ts +++ b/src/dex/sundaeswap-v3.ts @@ -1,28 +1,19 @@ -import { LiquidityPool } from './models/liquidity-pool'; -import { BaseDataProvider } from '@providers/data/base-data-provider'; -import { Asset, Token } from './models/asset'; import { BaseDex } from './base-dex'; -import { AssetBalance, DatumParameters, DefinitionConstr, DefinitionField, PayToAddress, RequestConfig, SpendUTxO, SwapFee, UTxO } from '@app/types'; +import { DatumParameters, PayToAddress, SpendUTxO, SwapFee, UTxO } from '@app/types'; import { DefinitionBuilder } from '@app/definition-builder'; import { correspondingReserves, lucidUtils, tokensMatch } from '@app/utils'; import { AddressType, DatumParameterKey } from '@app/constants'; -import pool from '@dex/definitions/sundaeswap-v3/pool'; import order from '@dex/definitions/sundaeswap-v3/order'; -import { BaseApi } from '@dex/api/base-api'; import { AddressDetails, Script } from 'lucid-cardano'; -import { SundaeSwapV3Api } from '@dex/api/sundaeswap-v3-api'; -import { BaseWalletProvider } from '@providers/wallet/base-wallet-provider'; +import { LiquidityPool, Token } from '@indigo-labs/iris-sdk'; export class SundaeSwapV3 extends BaseDex { public static readonly identifier: string = 'SundaeSwapV3'; - public readonly api: BaseApi; /** * On-Chain constants. */ - public readonly poolAddress: string = 'addr1x8srqftqemf0mjlukfszd97ljuxdp44r372txfcr75wrz26rnxqnmtv3hdu2t6chcfhl2zzjh36a87nmd6dwsu3jenqsslnz7e'; - public readonly lpTokenPolicyId: string = 'e0302560ced2fdcbfcb2602697df970cd0d6a38f94b32703f51c312b'; public readonly cancelDatum: string = 'd87a80'; public readonly orderScriptHash: string = 'fa6a58bbe2d0ff05534431c8e2f0ef2cbdc1602a8456e4b13c8f3077'; public readonly orderScript: Script = { @@ -32,114 +23,32 @@ export class SundaeSwapV3 extends BaseDex { private readonly protocolFeeDefault: bigint = 1_280000n; - constructor(requestConfig: RequestConfig = {}) { - super(); - - this.api = new SundaeSwapV3Api(this, requestConfig); - } - - public async liquidityPoolAddresses(): Promise { - return Promise.resolve([this.poolAddress]); - } - - async liquidityPools(provider: BaseDataProvider, wallet?: BaseWalletProvider): Promise { - const utxos: UTxO[] = await provider.utxos(this.poolAddress); - - return await Promise.all( - utxos.map(async (utxo: UTxO) => { - return await this.liquidityPoolFromUtxo(provider, utxo, wallet); - }) - ).then((liquidityPools: (LiquidityPool | undefined)[]) => { - return liquidityPools.filter((liquidityPool?: LiquidityPool) => { - return liquidityPool !== undefined; - }) as LiquidityPool[]; - }); - } - - public async liquidityPoolFromUtxo(provider: BaseDataProvider, utxo: UTxO, wallet?: BaseWalletProvider): Promise { - if (! utxo.datumHash) { - return Promise.resolve(undefined); - } - - const relevantAssets: AssetBalance[] = utxo.assetBalances.filter((assetBalance: AssetBalance) => { - const assetBalanceId: string = assetBalance.asset === 'lovelace' ? 'lovelace' : assetBalance.asset.identifier(); - - return !assetBalanceId.startsWith(this.lpTokenPolicyId); - }); - - // Irrelevant UTxO - if (![2, 3].includes(relevantAssets.length)) { - return Promise.resolve(undefined); - } - - // Could be ADA/X or X/X pool - const assetAIndex: number = relevantAssets.length === 2 ? 0 : 1; - const assetBIndex: number = relevantAssets.length === 2 ? 1 : 2; - - try { - const builder: DefinitionBuilder = await new DefinitionBuilder().loadDefinition(pool); - const datum: DefinitionField = await provider.datumValue(utxo.datumHash); - const parameters: DatumParameters = builder.pullParameters(datum as DefinitionConstr); - - const reservesA: bigint = relevantAssets[assetAIndex].asset === 'lovelace' - ? relevantAssets[assetAIndex].quantity - BigInt((parameters.ProtocolFee ?? 0) as number) - : relevantAssets[assetAIndex].quantity; - const reservesB: bigint = relevantAssets[assetBIndex].asset === 'lovelace' - ? relevantAssets[assetBIndex].quantity - BigInt((parameters.ProtocolFee ?? 0) as number) - : relevantAssets[assetBIndex].quantity; - - const liquidityPool: LiquidityPool = new LiquidityPool( - SundaeSwapV3.identifier, - relevantAssets[assetAIndex].asset, - relevantAssets[assetBIndex].asset, - reservesA, - reservesB, - utxo.address, - '', - '' - ); - - const lpToken: Asset = utxo.assetBalances.find((assetBalance) => { - return assetBalance.asset !== 'lovelace' && assetBalance.asset.policyId === this.lpTokenPolicyId; - })?.asset as Asset; - - if (lpToken) { - lpToken.nameHex = '0014df1' + lpToken.nameHex.substr(7); - liquidityPool.lpToken = lpToken; - liquidityPool.identifier = lpToken.identifier(); - } - - liquidityPool.lpToken = lpToken; - liquidityPool.identifier = typeof parameters.PoolIdentifier === 'string' ? parameters.PoolIdentifier : ''; - liquidityPool.poolFeePercent = typeof parameters.OpeningFee === 'number' ? (parameters.OpeningFee / 10_000) * 100 : 0; - liquidityPool.totalLpTokens = typeof parameters.TotalLpTokens === 'number' ? BigInt(parameters.TotalLpTokens) : 0n; - liquidityPool.extra.protocolFee = typeof parameters.ProtocolFee === 'number' ? parameters.ProtocolFee : this.protocolFeeDefault; - - return liquidityPool; - } catch (e) { - return undefined; - } - } - estimatedGive(liquidityPool: LiquidityPool, swapOutToken: Token, swapOutAmount: bigint): bigint { + if (! liquidityPool.state) return 0n; + const [reserveOut, reserveIn]: bigint[] = correspondingReserves(liquidityPool, swapOutToken); + const poolFeePercent: number = tokensMatch(liquidityPool.tokenA, swapOutToken) ? liquidityPool.state.sellFeePercent : liquidityPool.state.buyFeePercent; const receive: bigint = (reserveIn * reserveOut) / (reserveOut - swapOutAmount) - reserveIn; - const swapFee: bigint = (receive * BigInt(Math.floor(liquidityPool.poolFeePercent * 100)) + BigInt(10000) - 1n) / 10000n; + const swapFee: bigint = (receive * BigInt(Math.floor(poolFeePercent * 100)) + BigInt(10000) - 1n) / 10000n; return receive + swapFee; } estimatedReceive(liquidityPool: LiquidityPool, swapInToken: Token, swapInAmount: bigint): bigint { - const [reserveIn, reserveOut]: bigint[] = correspondingReserves(liquidityPool, swapInToken); + if (! liquidityPool.state) return 0n; - const swapFee: bigint = (swapInAmount * BigInt(Math.floor(liquidityPool.poolFeePercent * 100)) + BigInt(10000) - 1n) / 10000n; + const [reserveIn, reserveOut]: bigint[] = correspondingReserves(liquidityPool, swapInToken); + const poolFeePercent: number = tokensMatch(liquidityPool.tokenA, swapInToken) ? liquidityPool.state.buyFeePercent : liquidityPool.state.sellFeePercent; + const swapFee: bigint = (swapInAmount * BigInt(Math.floor(poolFeePercent * 100)) + BigInt(10000) - 1n) / 10000n; return reserveOut - (reserveIn * reserveOut) / (reserveIn + swapInAmount - swapFee); } priceImpactPercent(liquidityPool: LiquidityPool, swapInToken: Token, swapInAmount: bigint): number { - const reserveIn: bigint = tokensMatch(swapInToken, liquidityPool.assetA) ? liquidityPool.reserveA : liquidityPool.reserveB; + if (! liquidityPool.state) return 0; + + const reserveIn: bigint = tokensMatch(swapInToken, liquidityPool.tokenA) ? liquidityPool.state.reserveA : liquidityPool.state.reserveB; return (1 - Number(reserveIn) / Number(reserveIn + swapInAmount)) * 100; } diff --git a/src/dex/sundaeswap-v1.ts b/src/dex/sundaeswap.ts similarity index 67% rename from src/dex/sundaeswap-v1.ts rename to src/dex/sundaeswap.ts index 381d648..fdfe05d 100644 --- a/src/dex/sundaeswap-v1.ts +++ b/src/dex/sundaeswap.ts @@ -1,154 +1,60 @@ -import { LiquidityPool } from './models/liquidity-pool'; -import { BaseDataProvider } from '@providers/data/base-data-provider'; -import { Asset, Token } from './models/asset'; import { BaseDex } from './base-dex'; import { - AssetBalance, DatumParameters, - DefinitionConstr, - DefinitionField, PayToAddress, - RequestConfig, SpendUTxO, + SpendUTxO, SwapFee, UTxO } from '@app/types'; import { DefinitionBuilder } from '@app/definition-builder'; import { correspondingReserves, tokensMatch } from '@app/utils'; import { AddressType, DatumParameterKey } from '@app/constants'; -import pool from '@dex/definitions/sundaeswap-v1/pool'; import order from '@dex/definitions/sundaeswap-v1/order'; -import { BaseApi } from '@dex/api/base-api'; -import { SundaeSwapV1Api } from '@dex/api/sundaeswap-v1-api'; import { Script } from 'lucid-cardano'; +import { LiquidityPool, Token } from '@indigo-labs/iris-sdk'; -export class SundaeSwapV1 extends BaseDex { +export class SundaeSwap extends BaseDex { - public static readonly identifier: string = 'SundaeSwapV1'; - public readonly api: BaseApi; + public static readonly identifier: string = 'SundaeSwap'; /** * On-Chain constants. */ public readonly orderAddress: string = 'addr1wxaptpmxcxawvr3pzlhgnpmzz3ql43n2tc8mn3av5kx0yzs09tqh8'; - public readonly poolAddress: string = 'addr1w9qzpelu9hn45pefc0xr4ac4kdxeswq7pndul2vuj59u8tqaxdznu'; - public readonly lpTokenPolicyId: string = '0029cb7c88c7567b63d1a512c0ed626aa169688ec980730c0473b913'; public readonly cancelDatum: string = 'd87a80'; public readonly orderScript: Script = { type: 'PlutusV1', script: '59084601000033233322232332232333222323332223322323332223233223233223332223333222233322233223322332233223332223322332233322232323232322222325335300b001103c13503d35303b3357389201035054350003c498ccc888c8c8c94cd4c05c0144d4c0680188888cd4c04c480048d4c0ed40188888888888cd4c078480048ccd5cd19b8f375c0020180440420066a6040006446a6048004446a605000444666aa60302400244a66a6a07c0044266a08c0020042002a0886466a002a088a08a2446600466a609000846a0820024a0806600400e00226a606ca002444444444466a6032240024646464666ae68cdc399991119191800802990009aa82c1119a9a826000a4000446a6aa08a00444a66a6050666ae68cdc78010048150148980380089803001990009aa82b9119a9a825800a4000446a6aa08800444a66a604e666ae68cdc7801003814814080089803001999aa81e3ae335503c75ceb4d4c084cccd5cd19b8735573aa006900011998119aba1500335742a00466a080eb8d5d09aba2500223505135304f33573892010350543100050499262220020183371491010270200035302801422220044800808007c4d5d1280089aab9e500113754002012264a66a6a070601a6aae78dd50008a81a910a99a9a81d0008a81b910a99a9a81e0008a81c910a99a9a81f0008a81d910a99a9a8200008a81e910a99a9a8210008a81f910a99a9a8220008a820910a99a9a8230008a821910a99a9a8240008a822910a99a9a8250008a823910a99a9a82600089999999999825981000a18100090080071810006181000500418100031810002001110a8259a980a1999ab9a3370e6aae754009200023301635742a0046ae84d5d1280111a8211a982019ab9c490103505431000414992622002135573ca00226ea8004cd40148c8c8c8c8cccd5cd19b8735573aa00890001199980d9bae35742a0086464646666ae68cdc39aab9d5002480008cc88cc08c008004c8c8c8cccd5cd19b8735573aa004900011991198148010009919191999ab9a3370e6aae754009200023302d304735742a00466a07a4646464646666ae68cdc3a800a4004466606a6eb4d5d0a8021bad35742a0066eb4d5d09aba2500323333573466e1d4009200023037304e357426aae7940188d4154d4c14ccd5ce2490350543100054499264984d55cea80189aba25001135573ca00226ea8004d5d09aba2500223504e35304c335738921035054310004d49926135573ca00226ea8004d5d0a80119a81cbae357426ae8940088d4128d4c120cd5ce249035054310004949926135573ca00226ea8004d5d0a80119a81abae357426ae8940088d4118d4c110cd5ce249035054310004549926135573ca00226ea8004d5d0a8019bad35742a00464646464646666ae68cdc3a800a40084605c646464646666ae68cdc3a800a40044606c6464646666ae68cdc39aab9d5002480008cc88cd40f8008004dd69aba15002375a6ae84d5d1280111a8289a982799ab9c491035054310005049926135573ca00226ea8004d5d09aab9e500423333573466e1d40092000233036304b35742a0086eb4d5d09aba2500423504e35304c335738921035054310004d499264984d55cea80109aab9e5001137540026ae84d55cf280291999ab9a3370ea0049001118169bad357426aae7940188cccd5cd19b875003480008ccc0bcc11cd5d0a8031bad35742a00a66a072eb4d5d09aba2500523504a353048335738920103505431000494992649926135573aa00626ae8940044d55cf280089baa001357426ae8940088d4108d4c100cd5ce249035054310004149926135744a00226ae8940044d55cf280089baa0010033350052323333573466e1d40052002201623333573466e1d40092000201623504035303e335738921035054310003f499264984d55ce9baa001002335005200100112001230023758002640026aa072446666aae7c004940c08cd40bcd5d080118019aba2002498c8004d540e088448894cd4d40bc0044008884cc014008ccd54c01c48004014010004c8004d540dc884894cd4d40b400440188854cd4c01cc01000840244cd4c01848004010004488008488004800488848ccc00401000c00880048848cc00400c00880044880084880048004888848cccc00401401000c00880048848cc00400c00880048848cc00400c00880048848cc00400c00880048488c00800c888488ccc00401401000c800484888c00c0108884888ccc00801801401084888c00401080048488c00800c88488cc00401000c800448848cc00400c008480044488c88c008dd5800990009aa80d11191999aab9f0022501223350113355008300635573aa004600a6aae794008c010d5d100180c09aba10011122123300100300211200112232323333573466e1d400520002350083005357426aae79400c8cccd5cd19b87500248008940208d405cd4c054cd5ce24810350543100016499264984d55cea80089baa00112122300200311220011200113500d35300b3357389211f556e6578706563746564205478496e666f20636f6e737472756374696f6e2e0000c498888888888848cccccccccc00402c02802402001c01801401000c00880044488008488488cc00401000c480048c8c8cccd5cd19b875001480088c018dd71aba135573ca00646666ae68cdc3a80124000460106eb8d5d09aab9e500423500c35300a3357389201035054310000b499264984d55cea80089baa001212230020032122300100320012323333573466e1d40052002200823333573466e1d40092000200a2350073530053357389210350543100006499264984d55ce9baa0011200120011261220021220012001112323001001223300330020020014891c0029cb7c88c7567b63d1a512c0ed626aa169688ec980730c0473b9130001', }; - constructor(requestConfig: RequestConfig = {}) { - super(); - - this.api = new SundaeSwapV1Api(this, requestConfig); - } - - public async liquidityPoolAddresses(provider: BaseDataProvider): Promise { - return Promise.resolve([this.poolAddress]); - } - - async liquidityPools(provider: BaseDataProvider): Promise { - const utxos: UTxO[] = await provider.utxos(this.poolAddress); - - return await Promise.all( - utxos.map(async (utxo: UTxO) => { - return await this.liquidityPoolFromUtxo(provider, utxo); - }) - ) - .then((liquidityPools: (LiquidityPool | undefined)[]) => { - return liquidityPools.filter((liquidityPool?: LiquidityPool) => { - return liquidityPool !== undefined; - }) as LiquidityPool[]; - }); - } - - public async liquidityPoolFromUtxo(provider: BaseDataProvider, utxo: UTxO): Promise { - if (! utxo.datumHash) { - return Promise.resolve(undefined); - } - - const relevantAssets: AssetBalance[] = utxo.assetBalances.filter((assetBalance: AssetBalance) => { - const assetBalanceId: string = assetBalance.asset === 'lovelace' ? 'lovelace' : assetBalance.asset.identifier(); - - return ! assetBalanceId.startsWith(this.lpTokenPolicyId); - }); - - // Irrelevant UTxO - if (! [2, 3].includes(relevantAssets.length)) { - return Promise.resolve(undefined); - } - - // Could be ADA/X or X/X pool - const assetAIndex: number = relevantAssets.length === 2 ? 0 : 1; - const assetBIndex: number = relevantAssets.length === 2 ? 1 : 2; - - const liquidityPool: LiquidityPool = new LiquidityPool( - SundaeSwapV1.identifier, - relevantAssets[assetAIndex].asset, - relevantAssets[assetBIndex].asset, - relevantAssets[assetAIndex].quantity, - relevantAssets[assetBIndex].quantity, - utxo.address, - this.orderAddress, - this.orderAddress, - ); - - // Load additional pool information - const lpToken: Asset = utxo.assetBalances.find((assetBalance) => { - return assetBalance.asset !== 'lovelace' && assetBalance.asset.policyId === this.lpTokenPolicyId; - })?.asset as Asset; - - if (lpToken) { - lpToken.nameHex = '6c' + lpToken.nameHex; - liquidityPool.lpToken = lpToken; - liquidityPool.identifier = lpToken.identifier(); - } - - try { - const builder: DefinitionBuilder = await (new DefinitionBuilder()) - .loadDefinition(pool); - const datum: DefinitionField = await provider.datumValue(utxo.datumHash); - const parameters: DatumParameters = builder.pullParameters(datum as DefinitionConstr); - - liquidityPool.lpToken = lpToken; - liquidityPool.identifier = typeof parameters.PoolIdentifier === 'string' - ? parameters.PoolIdentifier - : ''; - liquidityPool.poolFeePercent = typeof parameters.LpFeeNumerator === 'number' && typeof parameters.LpFeeDenominator === 'number' - ? (parameters.LpFeeNumerator / parameters.LpFeeDenominator) * 100 - : 0; - liquidityPool.totalLpTokens = typeof parameters.TotalLpTokens === 'number' - ? BigInt(parameters.TotalLpTokens) - : 0n; - } catch (e) { - return liquidityPool; - } - - return liquidityPool; - } - estimatedGive(liquidityPool: LiquidityPool, swapOutToken: Token, swapOutAmount: bigint): bigint { + if (! liquidityPool.state) return 0n; + const [reserveOut, reserveIn]: bigint[] = correspondingReserves(liquidityPool, swapOutToken); + const poolFeePercent: number = tokensMatch(liquidityPool.tokenA, swapOutToken) ? liquidityPool.state.sellFeePercent : liquidityPool.state.buyFeePercent; const receive: bigint = (reserveIn * reserveOut) / (reserveOut - swapOutAmount) - reserveIn; - const swapFee: bigint = ((receive * BigInt(Math.floor(liquidityPool.poolFeePercent * 100))) + BigInt(10000) - 1n) / 10000n; + const swapFee: bigint = ((receive * BigInt(Math.floor(poolFeePercent * 100))) + BigInt(10000) - 1n) / 10000n; return receive + swapFee; } estimatedReceive(liquidityPool: LiquidityPool, swapInToken: Token, swapInAmount: bigint): bigint { - const [reserveIn, reserveOut]: bigint[] = correspondingReserves(liquidityPool, swapInToken); + if (! liquidityPool.state) return 0n; - const swapFee: bigint = ((swapInAmount * BigInt(Math.floor(liquidityPool.poolFeePercent * 100))) + BigInt(10000) - 1n) / 10000n; + const [reserveIn, reserveOut]: bigint[] = correspondingReserves(liquidityPool, swapInToken); + const poolFeePercent: number = tokensMatch(liquidityPool.tokenA, swapInToken) ? liquidityPool.state.buyFeePercent : liquidityPool.state.sellFeePercent; + const swapFee: bigint = ((swapInAmount * BigInt(Math.floor(poolFeePercent * 100))) + BigInt(10000) - 1n) / 10000n; return reserveOut - (reserveIn * reserveOut) / (reserveIn + swapInAmount - swapFee); } priceImpactPercent(liquidityPool: LiquidityPool, swapInToken: Token, swapInAmount: bigint): number { - const reserveIn: bigint = tokensMatch(swapInToken, liquidityPool.assetA) - ? liquidityPool.reserveA - : liquidityPool.reserveB; + if (! liquidityPool.state) return 0; + + const reserveIn: bigint = tokensMatch(swapInToken, liquidityPool.tokenA) + ? liquidityPool.state.reserveA + : liquidityPool.state.reserveB; return (1 - (Number(reserveIn) / Number(reserveIn + swapInAmount))) * 100; } diff --git a/src/dex/vyfinance.ts b/src/dex/vyfinance.ts index ded5ce3..6d753bf 100644 --- a/src/dex/vyfinance.ts +++ b/src/dex/vyfinance.ts @@ -1,15 +1,11 @@ -import { LiquidityPool } from './models/liquidity-pool'; -import { BaseDataProvider } from '@providers/data/base-data-provider'; -import { Asset, Token } from './models/asset'; import { BaseDex } from './base-dex'; -import { DatumParameters, PayToAddress, RequestConfig, SpendUTxO, SwapFee, UTxO } from '@app/types'; +import { DatumParameters, PayToAddress, SpendUTxO, SwapFee, UTxO } from '@app/types'; import { DefinitionBuilder } from '@app/definition-builder'; -import { correspondingReserves } from '@app/utils'; +import { correspondingReserves, tokensMatch } from '@app/utils'; import { AddressType, DatumParameterKey } from '@app/constants'; import order from '@dex/definitions/vyfinance/order'; -import { BaseApi } from '@dex/api/base-api'; -import { VyfinanceApi } from '@dex/api/vyfinance-api'; -import { Data, Script } from 'lucid-cardano'; +import { Script } from 'lucid-cardano'; +import { LiquidityPool, Token } from '@indigo-labs/iris-sdk'; /** * VyFinance constants. @@ -20,7 +16,6 @@ const SWAP_ACTION_EXPECT_ADA: number = 4; export class VyFinance extends BaseDex { public static readonly identifier: string = 'VyFinance'; - public readonly api: BaseApi; /** * On-Chain constants. @@ -31,27 +26,12 @@ export class VyFinance extends BaseDex { script: '590a8c010000332323232322232322322323253353330093333573466e1cd55cea803a40004646424660020060046464646666ae68cdc3a800a40184642444444460020106eb4d5d09aab9e500323333573466e1d4009200a232122222223002008375a6ae84d55cf280211999ab9a3370ea00690041190911111118018041bad357426aae7940148cccd5cd19b875004480188c848888888c010020dd69aba135573ca00c46666ae68cdc3a802a400842444444400a46666ae68cdc3a8032400446424444444600c0106464646666ae68cdc39aab9d5002480008cc8848cc00400c008dd69aba15002375a6ae84d5d1280111931a99ab9c01d01c01b01a135573ca00226ea8004d5d09aab9e500823333573466e1d401d2000232122222223007008375a6ae84d55cf280491931a99ab9c01a019018017016015014013012011135573aa00226ea8004d5d09aba25008375c6ae85401c8c98d4cd5ce0078070068061999ab9a3370ea0089001109100111999ab9a3370ea00a9000109100091931a99ab9c01000f00e00d00c3333573466e1cd55cea8012400046644246600200600464646464646464646464646666ae68cdc39aab9d500a480008cccccccccc888888888848cccccccccc00402c02802402001c01801401000c008d5d0a80519a80b90009aba1500935742a0106ae85401cd5d0a8031aba1500535742a00866a02eeb8d5d0a8019aba15002357426ae8940088c98d4cd5ce00d80d00c80c09aba25001135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aab9e5001137540026ae854008c8c8c8cccd5cd19b875001480188c848888c010014c8c8c8c8c8c8cccd5cd19b8750014803084888888800c8cccd5cd19b875002480288488888880108cccd5cd19b875003480208cc8848888888cc004024020dd71aba15005375a6ae84d5d1280291999ab9a3370ea00890031199109111111198010048041bae35742a00e6eb8d5d09aba2500723333573466e1d40152004233221222222233006009008301b35742a0126eb8d5d09aba2500923333573466e1d40192002232122222223007008301c357426aae79402c8cccd5cd19b875007480008c848888888c014020c074d5d09aab9e500c23263533573804003e03c03a03803603403203002e26aae7540104d55cf280189aab9e5002135573ca00226ea8004d5d09aab9e500323333573466e1d400920042321222230020053011357426aae7940108cccd5cd19b875003480088c848888c004014c8c8c8cccd5cd19b8735573aa004900011991091980080180119191999ab9a3370e6aae75400520002375c6ae84d55cf280111931a99ab9c01c01b01a019137540026ae854008dd69aba135744a004464c6a66ae7006406005c0584d55cf280089baa001357426aae7940148cccd5cd19b875004480008c848888c00c014dd71aba135573ca00c464c6a66ae7005805405004c0480440404d55cea80089baa001357426ae8940088c98d4cd5ce007807006806080689931a99ab9c4901035054350000d00c135573ca00226ea80044d55ce9baa001135573ca00226ea800448c88c008dd60009900099180080091191999aab9f0022122002233221223300100400330053574200660046ae8800c01cc0080088c8c8c8c8cccd5cd19b875001480088ccc888488ccc00401401000cdd69aba15004375a6ae85400cdd69aba135744a00646666ae68cdc3a8012400046424460040066464646666ae68cdc3a800a400446424460020066eb8d5d09aab9e500323333573466e1d400920002321223002003375c6ae84d55cf280211931a99ab9c00f00e00d00c00b135573aa00226ea8004d5d09aab9e500623263533573801401201000e00c26aae75400c4d5d1280089aab9e5001137540029309000a481035054310033232323322323232323232323232332223222253350021350012232350032222222222533533355301512001321233001225335002210031001002501e25335333573466e3c0300040540504d40800045407c00c84054404cd4c8c8d4cc8848cc00400c008ccdc624000030004a66a666ae68cdc7a800a4410000b00a150151350165001223355011002001133371802e02e0026a00a4400444004260086a6464646464a66a6666666ae900148cccd5cd19b8735573aa00a900011999aab9f500525019233335573ea00a4a03446666aae7d40149406c8cccd55cf9aba2500625335323232323333333574800846666ae68cdc39aab9d5004480008cccd55cfa8021281191999aab9f500425024233335573e6ae89401494cd4c088d5d0a80390a99a99a811119191919191999999aba400623333573466e1d40092002233335573ea00c4a05e46666aae7d4018940c08cccd55cfa8031281891999aab9f35744a00e4a66a605a6ae854028854cd4c0b8d5d0a80510a99a98179aba1500a21350361223330010050040031503415033150322503203303203103023333573466e1d400d2000233335573ea00e4a06046666aae7cd5d128041299a98171aba150092135033122300200315031250310320312502f02c02b2502d2502d2502d2502d02e135573aa00826ae8940044d5d1280089aab9e5001137540026ae85401c84d40a048cc00400c0085409854094940940980940909408807c940849408494084940840884d5d1280089aab9e5001137540026ae854024854cd4ccd54054070cd54054070060d5d0a80490a99a99a80d00e9aba150092135020123330010040030021501e1501d1501c2501c01d01c01b01a250180152501725017250172501701821001135626135744a00226ae8940044d55cf280089baa00135001223500222222222225335009132635335738921035054380001f01b22100222200232001355011225335001100422135002225335333573466e3c00801c02402040244c01800c488008488004c8004d5403488448894cd40044d400c88004884ccd401488008c010008ccd54c01c480040140100044488c88ccccccd5d2000aa8029299a98019bab002213500f0011500d55005550055500500e3200135500e223233335573e00446a01e2440044a66a600c6aae754008854cd4c018d55cf280190a99a98031aba200521350123212233001003004335500b003002150101500f1500e00f135742002224a0102244246600200600446666666ae900049401c9401c9401c8d4020dd6801128038040911919191999999aba400423333573466e1d40092000233335573ea0084a01846666aae7cd5d128029299a98049aba15006213500f3500f0011500d2500d00e00d23333573466e1d400d2002233335573ea00a46a01ca01a4a01a01c4a0180120104a0144a0144a0144a01401626aae7540084d55cf280089baa00123232323333333574800846666ae68cdc3a8012400446666aae7d4010940288cccd55cf9aba2500525335300a35742a00c426a01a24460020062a0164a01601801646666ae68cdc3a801a400046666aae7d40149402c8cccd55cf9aba2500625335300b35742a00e426a01c24460040062a0184a01801a0184a01400e00c4a0104a0104a0104a01001226aae7540084d55cf280089baa0014988ccccccd5d20009280192801928019280191a8021bae002004121223002003112200112001480e0448c8c00400488cc00cc00800800522011c', }; - constructor(requestConfig: RequestConfig = {}) { - super(); - - this.api = new VyfinanceApi(this, requestConfig); - } - - public async liquidityPoolAddresses(provider: BaseDataProvider): Promise { - return Promise.reject('Not implemented as VyFinance pools are not easily identifiable on-chain.'); - } - - public async liquidityPools(provider: BaseDataProvider): Promise { - return Promise.reject('Not implemented as VyFinance pools are not easily identifiable on-chain.'); - } - - public liquidityPoolFromUtxo(provider: BaseDataProvider, utxo: UTxO): Promise { - return Promise.reject('Not implemented until pools are identifiable on-chain'); - } - estimatedGive(liquidityPool: LiquidityPool, swapOutToken: Token, swapOutAmount: bigint): bigint { + if (! liquidityPool.state) return 0n; + const poolFeeMultiplier: bigint = 1000n; - const poolFeeModifier: bigint = poolFeeMultiplier - BigInt(Math.round((liquidityPool.poolFeePercent / 100) * Number(poolFeeMultiplier))); + const poolFeePercent: number = tokensMatch(liquidityPool.tokenA, swapOutToken) ? liquidityPool.state.sellFeePercent : liquidityPool.state.buyFeePercent; + const poolFeeModifier: bigint = poolFeeMultiplier - BigInt(Math.round((poolFeePercent / 100) * Number(poolFeeMultiplier))); const [reserveOut, reserveIn]: bigint[] = correspondingReserves(liquidityPool, swapOutToken); @@ -62,8 +42,11 @@ export class VyFinance extends BaseDex { } public estimatedReceive(liquidityPool: LiquidityPool, swapInToken: Token, swapInAmount: bigint): bigint { + if (! liquidityPool.state) return 0n; + const poolFeeMultiplier: bigint = 1000n; - const poolFeeModifier: bigint = poolFeeMultiplier - BigInt(Math.round((liquidityPool.poolFeePercent / 100) * Number(poolFeeMultiplier))); + const poolFeePercent: number = tokensMatch(liquidityPool.tokenA, swapInToken) ? liquidityPool.state.buyFeePercent : liquidityPool.state.sellFeePercent; + const poolFeeModifier: bigint = poolFeeMultiplier - BigInt(Math.round((poolFeePercent / 100) * Number(poolFeeMultiplier))); const [reserveIn, reserveOut]: bigint[] = correspondingReserves(liquidityPool, swapInToken); @@ -74,10 +57,13 @@ export class VyFinance extends BaseDex { } public priceImpactPercent(liquidityPool: LiquidityPool, swapInToken: Token, swapInAmount: bigint): number { + if (! liquidityPool.state) return 0; + const [reserveIn, reserveOut]: number[] = correspondingReserves(liquidityPool, swapInToken).map((x: bigint) => Number(x)); const estimatedReceive: number = Number(this.estimatedReceive(liquidityPool, swapInToken, swapInAmount)); - const swapFee: number = Number(swapInAmount) * liquidityPool.poolFeePercent / 100; + const poolFeePercent: number = tokensMatch(liquidityPool.tokenA, swapInToken) ? liquidityPool.state.buyFeePercent : liquidityPool.state.sellFeePercent; + const swapFee: number = Number(swapInAmount) * poolFeePercent / 100; return (1 - estimatedReceive / ((Number(swapInAmount) - swapFee) * (reserveOut / reserveIn))) * 100; } @@ -104,7 +90,7 @@ export class VyFinance extends BaseDex { this.buildSwapOrderPayment( swapParameters, { - address: liquidityPool.marketOrderAddress, + address: liquidityPool.orderAddress, addressType: AddressType.Contract, assetBalances: [ { @@ -129,15 +115,18 @@ export class VyFinance extends BaseDex { return Promise.reject('Unable to find relevant UTxO for cancelling the swap order.'); } - const pool: LiquidityPool | undefined = (await this.api.liquidityPools()) - .find((pool: LiquidityPool) => [pool.marketOrderAddress, pool.limitOrderAddress].includes(relevantUtxo.address)); + // const nft = this.dexter.dataProvider?.utxos() - if (! pool) { - return Promise.reject('Unable to find relevant liquidity pool for cancelling the swap order.'); - } + // todo + // const pool: LiquidityPool | undefined = (await this.api.liquidityPools()) + // .find((pool: LiquidityPool) => [pool.marketOrderAddress, pool.limitOrderAddress].includes(relevantUtxo.address)); + // + // if (! pool) { + // return Promise.reject('Unable to find relevant liquidity pool for cancelling the swap order.'); + // } const script: Script = this.orderScript; - script.script += `${pool.extra.nft.policyId}0001`; + // script.script += `${pool.extra.nft.policyId}0001`; return [ { diff --git a/src/dex/wingriders-v2.ts b/src/dex/wingriders-v2.ts index 9c3bd72..2cee65b 100644 --- a/src/dex/wingriders-v2.ts +++ b/src/dex/wingriders-v2.ts @@ -1,164 +1,38 @@ import { BaseDex } from './base-dex'; import { - AssetAddress, - AssetBalance, DatumParameters, - DefinitionConstr, - DefinitionField, PayToAddress, - RequestConfig, SpendUTxO, + SpendUTxO, SwapFee, UTxO } from '@app/types'; -import { Asset, Token } from './models/asset'; -import { LiquidityPool } from './models/liquidity-pool'; -import { BaseDataProvider } from '@providers/data/base-data-provider'; import { correspondingReserves, tokensMatch } from '@app/utils'; import { AddressType, DatumParameterKey } from '@app/constants'; import { DefinitionBuilder } from '@app/definition-builder'; import order from '@dex/definitions/wingriders-v2/order'; -import { BaseApi } from '@dex/api/base-api'; -import pool from "@dex/definitions/wingriders-v2/pool"; import { Script } from 'lucid-cardano'; - -/** - * WingRiders constants. - */ -const MIN_POOL_ADA: bigint = 3_000_000n; -const MAX_INT: bigint = 9_223_372_036_854_775_807n; +import { LiquidityPool, Token } from '@indigo-labs/iris-sdk'; export class WingRidersV2 extends BaseDex { public static readonly identifier: string = 'WingRidersV2'; - public readonly api: BaseApi; /** * On-Chain constants. */ public readonly orderAddress: string = 'addr1w8qnfkpe5e99m7umz4vxnmelxs5qw5dxytmfjk964rla98q605wte'; - public readonly poolValidityAsset: string = '6fdc63a1d71dc2c65502b79baae7fb543185702b12c3c5fb639ed7374c'; public readonly cancelDatum: string = 'd87a80'; public readonly orderScript: Script = { type: 'PlutusV2', script: '59019e010000323232323232323232222325333008001149858c8c8c94ccc028cdc3a40040042664601444a666aae7c0045280a99980699baf301000100314a226004601c00264646464a66601c66e1d20000021301100116301100230110013754601c601a002601a6010601800c646eb0c038c8c034c034c034c034c034c034c028004c034004c034c0300104ccc888cdc79919191bae301300132323253330123370e90000010b0800980a801180a8009baa3012301100132301230110013011300f301000133300c222533301033712900500109980199b8100248028c044c044c044c044c04400454ccc040cdc3801240002602600226644a66602466e20009200016133301122253330153370e00490000980c00089980199b8100248008c058004008004cdc0801240046022002004646eb0c044c040004c040c03c00400cdd70039bad300d001004300d002300d00137540046ea52211caf97793b8702f381976cec83e303e9ce17781458c73c4bb16fe02b83002300430040012323002233002002001230022330020020015734ae888c00cdd5000aba15573caae741', }; - private _assetAddresses: AssetAddress[] = []; - - constructor(requestConfig: RequestConfig = {}) { - super(); - } - - public async liquidityPoolAddresses(provider: BaseDataProvider): Promise { - const validityAsset: Asset = Asset.fromIdentifier(this.poolValidityAsset); - const assetAddresses: AssetAddress[] = this._assetAddresses.length > 0 - ? this._assetAddresses - : await provider.assetAddresses(validityAsset); - - return Promise.resolve([...new Set(assetAddresses.map((assetAddress: AssetAddress) => assetAddress.address))]); - } - - async liquidityPools(provider: BaseDataProvider): Promise { - const validityAsset: Asset = Asset.fromIdentifier(this.poolValidityAsset); - const poolAddresses: string[] = await this.liquidityPoolAddresses(provider); - - const addressPromises: Promise[] = poolAddresses.map(async (address: string) => { - const utxos: UTxO[] = await provider.utxos(address, validityAsset); - - return await Promise.all( - utxos.map(async (utxo: UTxO) => { - return await this.liquidityPoolFromUtxo(provider, utxo); - }) - ) - .then((liquidityPools: (LiquidityPool | undefined)[]) => { - return liquidityPools.filter((liquidityPool?: LiquidityPool) => { - return liquidityPool !== undefined; - }) as LiquidityPool[] - }); - }); - - return Promise.all(addressPromises) - .then((liquidityPools: (Awaited)[]) => liquidityPools.flat()); - } - - public async liquidityPoolFromUtxo(provider: BaseDataProvider, utxo: UTxO): Promise { - if (! utxo.datumHash) { - return Promise.resolve(undefined); - } - - const validityAsset: Asset = Asset.fromIdentifier(this.poolValidityAsset); - - const relevantAssets: AssetBalance[] = utxo.assetBalances.filter((assetBalance: AssetBalance) => { - const assetBalanceId: string = assetBalance.asset === 'lovelace' ? 'lovelace' : assetBalance.asset.identifier(); - - return ! assetBalanceId.startsWith(validityAsset.policyId); - }); - - // Irrelevant UTxO - if (relevantAssets.length < 2) { - return Promise.resolve(undefined); - } - - // Could be ADA/X or X/X pool - const assetAIndex: number = relevantAssets.length === 2 ? 0 : 1; - const assetBIndex: number = relevantAssets.length === 2 ? 1 : 2; - - const assetAQuantity: bigint = relevantAssets[assetAIndex].quantity; - const assetBQuantity: bigint = relevantAssets[assetBIndex].quantity; - const liquidityPool: LiquidityPool = new LiquidityPool( - WingRidersV2.identifier, - relevantAssets[assetAIndex].asset, - relevantAssets[assetBIndex].asset, - relevantAssets[assetAIndex].asset === 'lovelace' - ? (assetAQuantity - MIN_POOL_ADA < 1_000_000n) - ? assetAQuantity - MIN_POOL_ADA - : assetAQuantity - : assetAQuantity, - relevantAssets[assetBIndex].asset === 'lovelace' - ? (assetBQuantity - MIN_POOL_ADA < 1_000_000n) - ? assetBQuantity - MIN_POOL_ADA - : assetBQuantity - : assetBQuantity, - utxo.address, - this.orderAddress, - this.orderAddress, - ); - - const lpTokenBalance: AssetBalance | undefined = utxo.assetBalances.find((assetBalance) => { - return assetBalance.asset !== 'lovelace' - && assetBalance.asset.policyId === validityAsset.policyId - && assetBalance.asset.nameHex !== validityAsset.nameHex; - }); - - if (lpTokenBalance) { - liquidityPool.lpToken = lpTokenBalance.asset as Asset; - liquidityPool.identifier = liquidityPool.lpToken.identifier(); - liquidityPool.totalLpTokens = MAX_INT - lpTokenBalance.quantity; - } - liquidityPool.poolFeePercent = 0.35; - - try { - const builder: DefinitionBuilder = await (new DefinitionBuilder()) - .loadDefinition(pool); - const datum: DefinitionField = await provider.datumValue(utxo.datumHash); - const parameters: DatumParameters = builder.pullParameters(datum as DefinitionConstr); - - liquidityPool.reserveA = typeof parameters.PoolAssetATreasury === 'number' - ? (liquidityPool.reserveA - BigInt(parameters.PoolAssetATreasury)) - : liquidityPool.reserveA; - liquidityPool.reserveB = typeof parameters.PoolAssetBTreasury === 'number' - ? (liquidityPool.reserveB - BigInt(parameters.PoolAssetBTreasury)) - : liquidityPool.reserveB; - } catch (e) { - return liquidityPool; - } - - return liquidityPool; - } - estimatedGive(liquidityPool: LiquidityPool, swapOutToken: Token, swapOutAmount: bigint): bigint { + if (! liquidityPool.state) return 0n; + const poolFeeMultiplier: bigint = 10000n; - const poolFeeModifier: bigint = poolFeeMultiplier - BigInt(Math.round((liquidityPool.poolFeePercent / 100) * Number(poolFeeMultiplier))); + const poolFeePercent: number = tokensMatch(liquidityPool.tokenA, swapOutToken) ? liquidityPool.state.sellFeePercent : liquidityPool.state.buyFeePercent; + const poolFeeModifier: bigint = poolFeeMultiplier - BigInt(Math.round((poolFeePercent / 100) * Number(poolFeeMultiplier))); const [reserveOut, reserveIn]: bigint[] = correspondingReserves(liquidityPool, swapOutToken); @@ -169,8 +43,11 @@ export class WingRidersV2 extends BaseDex { } estimatedReceive(liquidityPool: LiquidityPool, swapInToken: Token, swapInAmount: bigint): bigint { + if (! liquidityPool.state) return 0n; + const poolFeeMultiplier: bigint = 10000n; - const poolFeeModifier: bigint = poolFeeMultiplier - BigInt(Math.round((liquidityPool.poolFeePercent / 100) * Number(poolFeeMultiplier))); + const poolFeePercent: number = tokensMatch(liquidityPool.tokenA, swapInToken) ? liquidityPool.state.buyFeePercent : liquidityPool.state.sellFeePercent; + const poolFeeModifier: bigint = poolFeeMultiplier - BigInt(Math.round((poolFeePercent / 100) * Number(poolFeeMultiplier))); const [reserveIn, reserveOut]: bigint[] = correspondingReserves(liquidityPool, swapInToken); @@ -181,14 +58,14 @@ export class WingRidersV2 extends BaseDex { } priceImpactPercent(liquidityPool: LiquidityPool, swapInToken: Token, swapInAmount: bigint): number { - const swapOutTokenDecimals: number = tokensMatch(liquidityPool.assetA, swapInToken) - ? (liquidityPool.assetB === 'lovelace' ? 6 : liquidityPool.assetB.decimals) - : (liquidityPool.assetA === 'lovelace' ? 6 : liquidityPool.assetA.decimals) + const swapOutTokenDecimals: number = tokensMatch(liquidityPool.tokenA, swapInToken) + ? (liquidityPool.tokenB.decimals ?? 0) + : (liquidityPool.tokenA === 'lovelace' ? 6 : liquidityPool.tokenA.decimals ?? 0) const estimatedReceive: bigint = this.estimatedReceive(liquidityPool, swapInToken, swapInAmount); - const swapPrice: number = (Number(swapInAmount) / 10**(swapInToken === 'lovelace' ? 6 : swapInToken.decimals)) + const swapPrice: number = (Number(swapInAmount) / 10**(swapInToken === 'lovelace' ? 6 : swapInToken.decimals ?? 0)) / (Number(estimatedReceive) / 10**swapOutTokenDecimals); - const poolPrice: number = tokensMatch(liquidityPool.assetA, swapInToken) + const poolPrice: number = tokensMatch(liquidityPool.tokenA, swapInToken) ? liquidityPool.price : (1 / liquidityPool.price); diff --git a/src/dex/wingriders.ts b/src/dex/wingriders.ts index a7c6665..4b196b1 100644 --- a/src/dex/wingriders.ts +++ b/src/dex/wingriders.ts @@ -1,167 +1,42 @@ import { BaseDex } from './base-dex'; import { - AssetAddress, - AssetBalance, DatumParameters, - DefinitionConstr, - DefinitionField, PayToAddress, - RequestConfig, SpendUTxO, + SpendUTxO, SwapFee, UTxO } from '@app/types'; -import { Asset, Token } from './models/asset'; -import { LiquidityPool } from './models/liquidity-pool'; -import { BaseDataProvider } from '@providers/data/base-data-provider'; import { correspondingReserves, tokensMatch } from '@app/utils'; import { AddressType, DatumParameterKey } from '@app/constants'; import { DefinitionBuilder } from '@app/definition-builder'; -import order from '@dex/definitions/wingriders/order'; -import { BaseApi } from '@dex/api/base-api'; -import { WingRidersApi } from '@dex/api/wingriders-api'; -import pool from "@dex/definitions/wingriders/pool"; +import order from '@dex/definitions/wingriders-v1/order'; import { Script } from 'lucid-cardano'; +import { LiquidityPool, Token } from '@indigo-labs/iris-sdk'; /** * WingRiders constants. */ -const MIN_POOL_ADA: bigint = 3_000_000n; -const MAX_INT: bigint = 9_223_372_036_854_775_807n; export class WingRiders extends BaseDex { public static readonly identifier: string = 'WingRiders'; - public readonly api: BaseApi; /** * On-Chain constants. */ public readonly orderAddress: string = 'addr1wxr2a8htmzuhj39y2gq7ftkpxv98y2g67tg8zezthgq4jkg0a4ul4'; - public readonly poolValidityAsset: string = '026a18d04a0c642759bb3d83b12e3344894e5c1c7b2aeb1a2113a5704c'; public readonly cancelDatum: string = 'd87a80'; public readonly orderScript: Script = { type: 'PlutusV1', script: '590370010000332332233322232323332223332223233223232323232332233222232322323225335301533225335301a00221333573466e3c02cdd7299a9a8101980924004a66a6a040660249000299a9a8101980924000a66a6a04066024900019a980b8900098099bac5335350203301248000d4d54054c0440088800858884008004588854cd4d4088004588854cd4d409000440088858588854cd4d4088004588854cd4d4090004588854cd4d409800440188858588854cd4d4088004588854cd4d409000440108858588854cd4d4088004400888580680644cc88d4c03400888d4c0440088888cc05cdd70019918139bac0015335350273301948000d4d54070c06001c88008588854cd4d40a4004588854cd4d40ac004588854cd4d40b4004588854cd4d40bc004588854cd4d40c4004588854cd4d40cc004588854cd4d40d400458884008cccd5cd19b8735573aa010900011980699191919191999ab9a3370e6aae75401120002333301535742a0086ae85400cd5d0a8011aba135744a004464c6a605266ae700900a80680644d5d1280089aba25001135573ca00226ea8004d5d0a8041aba135744a010464c6a604666ae7007809005004c004cccd5cd19b8750024800880688cccd5cd19b875003480008c8c074004dd69aba135573ca00a464c6a604466ae7007408c04c0480440044084584d55cea80089baa001135573ca00226ea80048848cc00400c0088004888848cccc00401401000c0088004c8004d540548894cd4d404c00440308854cd4c034ccd5cd19b8f00400200f00e100f13300500400125335350103300248000004588854cd4d4048004588854cd4d40500044cd54028010008885888c8d4d54018cd5401cd55cea80098021aab9e5001225335300b333573466e1c0140080340304004584dd5000990009aa809111999aab9f0012501223350113574200460066ae8800800d26112212330010030021120013200135500e2212253353500d0021622153353007333573466e1c00d2000009008100213353006120010013370200690010910010910009000909118010018910009000a490350543100320013550062233335573e0024a00c466a00a6eb8d5d080118019aba2002007112200212212233001004003120011200120011123230010012233003300200200148811ce6c90a5923713af5786963dee0fdffd830ca7e0c86a041d9e5833e910001', }; - private _assetAddresses: AssetAddress[] = []; - - constructor(requestConfig: RequestConfig = {}) { - super(); - - this.api = new WingRidersApi(this, requestConfig); - } - - public async liquidityPoolAddresses(provider: BaseDataProvider): Promise { - const validityAsset: Asset = Asset.fromIdentifier(this.poolValidityAsset); - const assetAddresses: AssetAddress[] = this._assetAddresses.length > 0 - ? this._assetAddresses - : await provider.assetAddresses(validityAsset); - - return Promise.resolve([...new Set(assetAddresses.map((assetAddress: AssetAddress) => assetAddress.address))]); - } - - async liquidityPools(provider: BaseDataProvider): Promise { - const validityAsset: Asset = Asset.fromIdentifier(this.poolValidityAsset); - const poolAddresses: string[] = await this.liquidityPoolAddresses(provider); - - const addressPromises: Promise[] = poolAddresses.map(async (address: string) => { - const utxos: UTxO[] = await provider.utxos(address, validityAsset); - - return await Promise.all( - utxos.map(async (utxo: UTxO) => { - return await this.liquidityPoolFromUtxo(provider, utxo); - }) - ) - .then((liquidityPools: (LiquidityPool | undefined)[]) => { - return liquidityPools.filter((liquidityPool?: LiquidityPool) => { - return liquidityPool !== undefined; - }) as LiquidityPool[] - }); - }); - - return Promise.all(addressPromises) - .then((liquidityPools: (Awaited)[]) => liquidityPools.flat()); - } - - public async liquidityPoolFromUtxo(provider: BaseDataProvider, utxo: UTxO): Promise { - if (! utxo.datumHash) { - return Promise.resolve(undefined); - } - - const validityAsset: Asset = Asset.fromIdentifier(this.poolValidityAsset); - - const relevantAssets: AssetBalance[] = utxo.assetBalances.filter((assetBalance: AssetBalance) => { - const assetBalanceId: string = assetBalance.asset === 'lovelace' ? 'lovelace' : assetBalance.asset.identifier(); - - return ! assetBalanceId.startsWith(validityAsset.policyId); - }); - - // Irrelevant UTxO - if (relevantAssets.length < 2) { - return Promise.resolve(undefined); - } - - // Could be ADA/X or X/X pool - const assetAIndex: number = relevantAssets.length === 2 ? 0 : 1; - const assetBIndex: number = relevantAssets.length === 2 ? 1 : 2; - - const assetAQuantity: bigint = relevantAssets[assetAIndex].quantity; - const assetBQuantity: bigint = relevantAssets[assetBIndex].quantity; - const liquidityPool: LiquidityPool = new LiquidityPool( - WingRiders.identifier, - relevantAssets[assetAIndex].asset, - relevantAssets[assetBIndex].asset, - relevantAssets[assetAIndex].asset === 'lovelace' - ? (assetAQuantity - MIN_POOL_ADA < 1_000_000n) - ? assetAQuantity - MIN_POOL_ADA - : assetAQuantity - : assetAQuantity, - relevantAssets[assetBIndex].asset === 'lovelace' - ? (assetBQuantity - MIN_POOL_ADA < 1_000_000n) - ? assetBQuantity - MIN_POOL_ADA - : assetBQuantity - : assetBQuantity, - utxo.address, - this.orderAddress, - this.orderAddress, - ); - - const lpTokenBalance: AssetBalance | undefined = utxo.assetBalances.find((assetBalance) => { - return assetBalance.asset !== 'lovelace' - && assetBalance.asset.policyId === validityAsset.policyId - && assetBalance.asset.nameHex !== validityAsset.nameHex; - }); - - if (lpTokenBalance) { - liquidityPool.lpToken = lpTokenBalance.asset as Asset; - liquidityPool.identifier = liquidityPool.lpToken.identifier(); - liquidityPool.totalLpTokens = MAX_INT - lpTokenBalance.quantity; - } - liquidityPool.poolFeePercent = 0.35; - - try { - const builder: DefinitionBuilder = await (new DefinitionBuilder()) - .loadDefinition(pool); - const datum: DefinitionField = await provider.datumValue(utxo.datumHash); - const parameters: DatumParameters = builder.pullParameters(datum as DefinitionConstr); - - liquidityPool.reserveA = typeof parameters.PoolAssetATreasury === 'number' - ? (liquidityPool.reserveA - BigInt(parameters.PoolAssetATreasury)) - : liquidityPool.reserveA; - liquidityPool.reserveB = typeof parameters.PoolAssetBTreasury === 'number' - ? (liquidityPool.reserveB - BigInt(parameters.PoolAssetBTreasury)) - : liquidityPool.reserveB; - } catch (e) { - return liquidityPool; - } - - return liquidityPool; - } - estimatedGive(liquidityPool: LiquidityPool, swapOutToken: Token, swapOutAmount: bigint): bigint { + if (! liquidityPool.state) return 0n; + const poolFeeMultiplier: bigint = 10000n; - const poolFeeModifier: bigint = poolFeeMultiplier - BigInt(Math.round((liquidityPool.poolFeePercent / 100) * Number(poolFeeMultiplier))); + const poolFeePercent: number = tokensMatch(liquidityPool.tokenA, swapOutToken) ? liquidityPool.state.sellFeePercent : liquidityPool.state.buyFeePercent; + const poolFeeModifier: bigint = poolFeeMultiplier - BigInt(Math.round((poolFeePercent / 100) * Number(poolFeeMultiplier))); const [reserveOut, reserveIn]: bigint[] = correspondingReserves(liquidityPool, swapOutToken); @@ -172,8 +47,11 @@ export class WingRiders extends BaseDex { } estimatedReceive(liquidityPool: LiquidityPool, swapInToken: Token, swapInAmount: bigint): bigint { + if (! liquidityPool.state) return 0n; + const poolFeeMultiplier: bigint = 10000n; - const poolFeeModifier: bigint = poolFeeMultiplier - BigInt(Math.round((liquidityPool.poolFeePercent / 100) * Number(poolFeeMultiplier))); + const poolFeePercent: number = tokensMatch(liquidityPool.tokenA, swapInToken) ? liquidityPool.state.buyFeePercent : liquidityPool.state.sellFeePercent; + const poolFeeModifier: bigint = poolFeeMultiplier - BigInt(Math.round((poolFeePercent / 100) * Number(poolFeeMultiplier))); const [reserveIn, reserveOut]: bigint[] = correspondingReserves(liquidityPool, swapInToken); @@ -184,14 +62,16 @@ export class WingRiders extends BaseDex { } priceImpactPercent(liquidityPool: LiquidityPool, swapInToken: Token, swapInAmount: bigint): number { - const swapOutTokenDecimals: number = tokensMatch(liquidityPool.assetA, swapInToken) - ? (liquidityPool.assetB === 'lovelace' ? 6 : liquidityPool.assetB.decimals) - : (liquidityPool.assetA === 'lovelace' ? 6 : liquidityPool.assetA.decimals) + if (! liquidityPool.state) return 0; + + const swapOutTokenDecimals: number = tokensMatch(liquidityPool.tokenA, swapInToken) + ? (liquidityPool.tokenB.decimals ?? 0) + : (liquidityPool.tokenA === 'lovelace' ? 6 : liquidityPool.tokenA.decimals ?? 0) const estimatedReceive: bigint = this.estimatedReceive(liquidityPool, swapInToken, swapInAmount); - const swapPrice: number = (Number(swapInAmount) / 10**(swapInToken === 'lovelace' ? 6 : swapInToken.decimals)) + const swapPrice: number = (Number(swapInAmount) / 10**(swapInToken === 'lovelace' ? 6 : swapInToken.decimals ?? 0)) / (Number(estimatedReceive) / 10**swapOutTokenDecimals); - const poolPrice: number = tokensMatch(liquidityPool.assetA, swapInToken) + const poolPrice: number = tokensMatch(liquidityPool.tokenA, swapInToken) ? liquidityPool.price : (1 / liquidityPool.price); diff --git a/src/dexter.ts b/src/dexter.ts index b1bcd42..7713f23 100644 --- a/src/dexter.ts +++ b/src/dexter.ts @@ -1,17 +1,12 @@ -import { BaseDataProvider } from '@providers/data/base-data-provider'; import { AvailableDexs, DexterConfig, RequestConfig } from '@app/types'; import { Minswap } from '@dex/minswap'; -import { SundaeSwapV1 } from '@dex/sundaeswap-v1'; +import { SundaeSwap } from '@dex/sundaeswap'; import { MuesliSwap } from '@dex/muesliswap'; import { WingRiders } from '@dex/wingriders'; import { SwapRequest } from '@requests/swap-request'; import { BaseWalletProvider } from '@providers/wallet/base-wallet-provider'; import { BaseDex } from '@dex/base-dex'; -import { VyFinance } from '@dex/vyfinance'; -import { BaseMetadataProvider } from '@providers/asset-metadata/base-metadata-provider'; -import { TokenRegistryProvider } from '@providers/asset-metadata/token-registry-provider'; import { CancelSwapRequest } from '@requests/cancel-swap-request'; -import { FetchRequest } from '@requests/fetch-request'; import axios from 'axios'; import axiosRetry from 'axios-retry'; import { SplitSwapRequest } from '@requests/split-swap-request'; @@ -20,16 +15,14 @@ import { SundaeSwapV3 } from '@dex/sundaeswap-v3'; import { MinswapV2 } from '@dex/minswap-v2'; import { WingRidersV2 } from '@dex/wingriders-v2'; import { Splash } from '@dex/splash'; +import { BaseDataProvider } from '@providers/data/base-data-provider'; export class Dexter { public config: DexterConfig; public requestConfig: RequestConfig; - - public dataProvider?: BaseDataProvider; public walletProvider?: BaseWalletProvider; - public metadataProvider: BaseMetadataProvider; - + public dataProvider?: BaseDataProvider; public availableDexs: AvailableDexs; constructor(config: DexterConfig = {}, requestConfig: RequestConfig = {}) { @@ -57,17 +50,15 @@ export class Dexter { axiosRetry(axios, { retries: this.requestConfig.retries }); axios.defaults.timeout = this.requestConfig.timeout; - this.metadataProvider = new TokenRegistryProvider(this.requestConfig); this.availableDexs = { - [Minswap.identifier]: new Minswap(this.requestConfig), - [SundaeSwapV1.identifier]: new SundaeSwapV1(this.requestConfig), - [SundaeSwapV3.identifier]: new SundaeSwapV3(this.requestConfig), - [MinswapV2.identifier]: new MinswapV2(this.requestConfig), - [MuesliSwap.identifier]: new MuesliSwap(this.requestConfig), - [WingRiders.identifier]: new WingRiders(this.requestConfig), - [WingRidersV2.identifier]: new WingRidersV2(this.requestConfig), - [VyFinance.identifier]: new VyFinance(this.requestConfig), - [Splash.identifier]: new Splash(this.requestConfig), + [Minswap.identifier]: new Minswap(this), + [SundaeSwap.identifier]: new SundaeSwap(this), + [SundaeSwapV3.identifier]: new SundaeSwapV3(this), + [MinswapV2.identifier]: new MinswapV2(this), + [MuesliSwap.identifier]: new MuesliSwap(this), + [WingRiders.identifier]: new WingRiders(this), + [WingRidersV2.identifier]: new WingRidersV2(this), + [Splash.identifier]: new Splash(this), }; } @@ -96,22 +87,6 @@ export class Dexter { return this; } - /** - * Switch to a new asset metadata provider. - */ - public withMetadataProvider(metadataProvider: BaseMetadataProvider): Dexter { - this.metadataProvider = metadataProvider; - - return this; - } - - /** - * New request for data fetching. - */ - public newFetchRequest(): FetchRequest { - return new FetchRequest(this); - } - /** * New request for a swap order. */ diff --git a/src/index.ts b/src/index.ts index f75b32c..2c6ecb9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,22 +10,13 @@ export * from './definition-builder'; /** * Provider exports. */ -export * from './providers/data/base-data-provider'; -export * from './providers/data/blockfrost-provider'; -export * from './providers/data/kupo-provider'; -export * from './providers/data/mock-data-provider'; - export * from './providers/wallet/base-wallet-provider'; export * from './providers/wallet/mock-wallet-provider'; export * from './providers/wallet/lucid-provider'; -export * from './providers/asset-metadata/base-metadata-provider'; -export * from './providers/asset-metadata/token-registry-provider'; - /** * Request exports. */ -export * from './requests/fetch-request'; export * from './requests/swap-request'; export * from './requests/split-swap-request'; export * from './requests/cancel-swap-request'; @@ -34,17 +25,14 @@ export * from './requests/split-cancel-swap-request'; /** * DEX exports. */ -export * from './dex/models/asset'; -export * from './dex/models/liquidity-pool'; export * from './dex/models/dex-transaction'; export * from './dex/base-dex'; export * from './dex/minswap'; export * from './dex/minswap-v2'; -export * from './dex/sundaeswap-v1'; +export * from '@dex/sundaeswap'; export * from './dex/sundaeswap-v3'; export * from './dex/muesliswap'; export * from './dex/wingriders'; export * from './dex/wingriders-v2'; -export * from './dex/vyfinance'; export * from './dex/splash'; diff --git a/src/providers/asset-metadata/base-metadata-provider.ts b/src/providers/asset-metadata/base-metadata-provider.ts deleted file mode 100644 index 1c46c77..0000000 --- a/src/providers/asset-metadata/base-metadata-provider.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { AssetMetadata } from '@app/types'; -import { Asset } from '@dex/models/asset'; - -export abstract class BaseMetadataProvider { - - /** - * Fetch Asset metadata. - */ - abstract fetch(assets: Asset[]): Promise; - -} \ No newline at end of file diff --git a/src/providers/asset-metadata/token-registry-provider.ts b/src/providers/asset-metadata/token-registry-provider.ts deleted file mode 100644 index f9720ca..0000000 --- a/src/providers/asset-metadata/token-registry-provider.ts +++ /dev/null @@ -1,44 +0,0 @@ -import axios, { AxiosInstance } from 'axios'; -import { AssetMetadata, RequestConfig } from '@app/types'; -import { Asset } from '@dex/models/asset'; -import { BaseMetadataProvider } from './base-metadata-provider'; -import { appendSlash } from '@app/utils'; - -export class TokenRegistryProvider extends BaseMetadataProvider { - - private _api: AxiosInstance; - private _requestConfig: RequestConfig; - - /** - * https://input-output-hk.github.io/offchain-metadata-tools/api/latest/ - */ - constructor(requestConfig: RequestConfig = {}) { - super(); - - this._requestConfig = requestConfig; - - this._api = axios.create({ - timeout: requestConfig.timeout ?? 5000, - baseURL: `${appendSlash(requestConfig.proxyUrl)}https://tokens.cardano.org/`, - headers: { - 'Content-Type': 'application/json', - }, - }); - } - - /** - * https://input-output-hk.github.io/offchain-metadata-tools/api/latest/#tag/query/paths/~1metadata~1query/post - */ - fetch(assets: Asset[]): Promise { - return this._api.post('/metadata/query', { - subjects: assets.map((asset: Asset) => asset.identifier()), - }).then((response) => response.data.subjects.map((entry: any) => { - return { - policyId: entry.subject.slice(0, 56), - nameHex: entry.subject.slice(56), - decimals: entry.decimals ? Number(entry.decimals.value) : 0, - } as AssetMetadata; - })); - } - -} diff --git a/src/providers/data/base-data-provider.ts b/src/providers/data/base-data-provider.ts index ded4055..5f791d5 100644 --- a/src/providers/data/base-data-provider.ts +++ b/src/providers/data/base-data-provider.ts @@ -1,5 +1,5 @@ import { AssetAddress, DefinitionField, Transaction, UTxO } from '@app/types'; -import { Asset } from '@dex/models/asset'; +import { Asset } from '@indigo-labs/iris-sdk'; export abstract class BaseDataProvider { diff --git a/src/providers/data/blockfrost-provider.ts b/src/providers/data/blockfrost-provider.ts index 924d084..74258e7 100644 --- a/src/providers/data/blockfrost-provider.ts +++ b/src/providers/data/blockfrost-provider.ts @@ -9,9 +9,9 @@ import { Transaction, UTxO } from '@app/types'; -import { Asset } from '@dex/models/asset'; import Bottleneck from 'bottleneck'; import { appendSlash } from '@app/utils'; +import { Asset } from '@indigo-labs/iris-sdk'; const API_BURST_SIZE: number = 500; const API_COOLDOWN_SIZE: number = 10; diff --git a/src/providers/data/kupo-provider.ts b/src/providers/data/kupo-provider.ts index 693a153..71dffd9 100644 --- a/src/providers/data/kupo-provider.ts +++ b/src/providers/data/kupo-provider.ts @@ -1,5 +1,4 @@ import { BaseDataProvider } from './base-data-provider'; -import { Asset } from '@dex/models/asset'; import { AssetAddress, AssetBalance, @@ -15,6 +14,7 @@ import { import axios, { AxiosInstance } from 'axios'; import { Data } from 'lucid-cardano'; import { appendSlash } from '@app/utils'; +import { Asset } from '@indigo-labs/iris-sdk'; export class KupoProvider extends BaseDataProvider { diff --git a/src/providers/data/mock-data-provider.ts b/src/providers/data/mock-data-provider.ts index 222caf9..59d955b 100644 --- a/src/providers/data/mock-data-provider.ts +++ b/src/providers/data/mock-data-provider.ts @@ -1,6 +1,6 @@ import { BaseDataProvider } from './base-data-provider'; import { AssetAddress, DefinitionField, Transaction, UTxO } from '@app/types'; -import { Asset } from '@dex/models/asset'; +import { Asset } from '@indigo-labs/iris-sdk'; export class MockDataProvider extends BaseDataProvider { diff --git a/src/requests/fetch-request.ts b/src/requests/fetch-request.ts deleted file mode 100644 index 8f470b0..0000000 --- a/src/requests/fetch-request.ts +++ /dev/null @@ -1,302 +0,0 @@ -import { BaseDex } from '@dex/base-dex'; -import { Asset, Token } from '@dex/models/asset'; -import { LiquidityPool } from '@dex/models/liquidity-pool'; -import { Dexter } from '@app/dexter'; -import { AssetMetadata, AvailableDexs, Transaction, UTxO } from '@app/types'; -import { BaseDataProvider } from '@providers/data/base-data-provider'; -import { tokensMatch } from "@app/utils"; - -export class FetchRequest { - - private _dexter: Dexter; - private _onDexs: AvailableDexs; - private _dexDataProviders: Map; - private _filteredTokens: Token[] = []; - private _filteredPairs: Array = []; - - constructor(dexter: Dexter) { - this._dexter = dexter; - this._onDexs = dexter.availableDexs; - - this._dexDataProviders = new Map(); - if (dexter.dataProvider) { - Object.keys(dexter.availableDexs).forEach((dexName: string) => { - this._dexDataProviders.set(dexName, dexter.dataProvider as BaseDataProvider); - }); - } - } - - /** - * Set the DEX(s) Dexter will fetch data on. - */ - public onDexs(dexs: string | string[]): FetchRequest { - this._onDexs = {}; - - (Array.isArray(dexs) ? dexs : [dexs]).forEach((dexName: string) => { - if (! Object.keys(this._dexter.availableDexs).includes(dexName)) { - throw new Error(`DEX ${dexName} is not available.`); - } - - this._onDexs[dexName] = this._dexter.availableDexs[dexName]; - }); - - return this; - } - - /** - * Fetch data on all available DEXs. - */ - public onAllDexs(): FetchRequest { - this._onDexs = this._dexter.availableDexs; - - return this; - } - - /** - * Force a data provider for a DEX. - */ - public setDataProviderForDex(dexName: string, provider: BaseDataProvider | undefined): FetchRequest { - // Force API usage - if (! provider) { - this._dexDataProviders.delete(dexName); - return this; - } - - this._dexDataProviders.set(dexName, provider); - - return this; - } - - /** - * Only fetch pools containing these tokens. - */ - public forTokens(tokens: Token[]): FetchRequest { - this._filteredTokens = tokens; - - return this; - } - - /** - * Only fetch pools containing these token pairs. - */ - public forTokenPairs(tokenPairs: Array): FetchRequest { - tokenPairs.forEach((pair: Token[]) => { - if (pair.length !== 2) { - throw new Error('Token pair must contain two tokens.'); - } - - if (tokensMatch(pair[0], pair[1])) { - throw new Error('Provided pair contains the same tokens. Ensure each pair has differing tokens.'); - } - }); - - this._filteredPairs = tokenPairs; - - return this; - } - - /** - * Fetch latest state for a liquidity pool. - */ - public getLiquidityPoolState(liquidityPool: LiquidityPool): Promise { - if (! liquidityPool) { - return Promise.reject('Invalid liquidity pool provided.'); - } - - const dexInstance: BaseDex | undefined = this._dexter.dexByName(liquidityPool.dex); - - if (! dexInstance) { - return Promise.reject('Unable to determine DEX from the provided liquidity pool.'); - } - - let liquidityPoolPromises: Promise; - const dexDataProvider: BaseDataProvider | undefined = this._dexDataProviders.get(liquidityPool.dex); - - if (dexDataProvider) { - if (! liquidityPool.address) { - return Promise.reject('Liquidity pool must have a set address.'); - } - - const filterableAsset: Asset = liquidityPool.assetA === 'lovelace' - ? liquidityPool.assetB as Asset - : liquidityPool.assetA as Asset; - - liquidityPoolPromises = dexDataProvider.utxos(liquidityPool.address, filterableAsset) - .then(async (utxos: UTxO[]) => { - return await Promise.all( - utxos.map(async (utxo: UTxO) => { - return await dexInstance.liquidityPoolFromUtxo(dexDataProvider, utxo); - }) - ).then((liquidityPools: (LiquidityPool | undefined)[]) => { - return liquidityPools.filter((liquidityPool?: LiquidityPool) => { - return liquidityPool !== undefined; - }) as LiquidityPool[]; - }) - }); - } else { - liquidityPoolPromises = dexInstance.api.liquidityPools(liquidityPool.assetA, liquidityPool.assetB); - } - - return liquidityPoolPromises - .then(async (liquidityPools: LiquidityPool[]) => { - const possiblePools: LiquidityPool[] = liquidityPools.filter((pool?: LiquidityPool) => { - return pool !== undefined && pool.uuid === liquidityPool.uuid; - }) as LiquidityPool[]; - - if (possiblePools.length > 1) { - return Promise.reject('Encountered more than 1 possible pool state.'); - } - - if (this._dexter.config.shouldFetchMetadata) { - await this.fetchAssetMetadata(possiblePools); - } - - return possiblePools[0]; - }); - } - - /** - * Fetch all liquidity pools matching token filters. - */ - public getLiquidityPools(): Promise { - const liquidityPoolPromises: Promise[] = - Object.entries(this._onDexs).map(([dexName, dexInstance]) => { - const dexDataProvider: BaseDataProvider | undefined = this._dexDataProviders.get(dexName); - - if (! dexDataProvider) { - return this.fetchPoolsFromApi(dexInstance); - } - - return dexInstance.liquidityPools(dexDataProvider) - .catch(() => { - // Attempt fallback to API - return this._dexter.config.shouldFallbackToApi - ? this.fetchPoolsFromApi(dexInstance) - : []; - }); - }); - - return Promise.all( - liquidityPoolPromises, - ).then(async (mappedLiquidityPools: Awaited[]) => { - const liquidityPools: LiquidityPool[] = mappedLiquidityPools - .flat() - .filter((pool: LiquidityPool) => this.poolMatchesFilter(pool)); - - if (this._dexter.config.shouldFetchMetadata) { - await this.fetchAssetMetadata(liquidityPools); - } - - return liquidityPools; - }); - } - - /** - * Fetch historic states for a liquidity pool. - */ - public async getLiquidityPoolHistory(liquidityPool: LiquidityPool): Promise { - if (! this._dexter.dataProvider) { - return []; // todo - } - - const transactions: Transaction[] = await this._dexter.dataProvider.assetTransactions(liquidityPool.lpToken); - - const liquidityPoolPromises: Promise[] = transactions.map(async (transaction: Transaction) => { - const utxos: UTxO[] = await (this._dexter.dataProvider as BaseDataProvider) - .transactionUtxos(transaction.hash); - - const relevantUtxo: UTxO | undefined = utxos.find((utxo: UTxO) => { - return utxo.address === liquidityPool.address; - }); - - if (! relevantUtxo) { - return undefined; - } - - return await this._dexter.availableDexs[liquidityPool.dex].liquidityPoolFromUtxo( - this._dexter.dataProvider as BaseDataProvider, - relevantUtxo, - ) as LiquidityPool | undefined; - }); - - return await Promise.all(liquidityPoolPromises) - .then((liquidityPools: (LiquidityPool | undefined)[]) => { - return liquidityPools.filter((pool?: LiquidityPool) => pool !== undefined) as LiquidityPool[]; - }); - } - - /** - * Fetch asset metadata for the assets in the provided liquidity pools. - */ - private async fetchAssetMetadata(liquidityPools: LiquidityPool[]) { - const assets: Asset[] = liquidityPools.reduce((results: Asset[], liquidityPool: LiquidityPool) => { - if (liquidityPool.assetA !== 'lovelace' && ! results.some((asset: Asset) => asset.identifier() === (liquidityPool.assetA as Asset).identifier())) { - results.push(liquidityPool.assetA); - } - if (liquidityPool.assetB !== 'lovelace' && ! results.some((asset: Asset) => asset.identifier() === (liquidityPool.assetB as Asset).identifier())) { - results.push(liquidityPool.assetB); - } - - return results; - }, [] as Asset[]); - - await this._dexter.metadataProvider.fetch(assets) - .then((response: AssetMetadata[]) => { - liquidityPools.forEach((liquidityPool: LiquidityPool) => { - [liquidityPool.assetA, liquidityPool.assetB].forEach((asset: Token) => { - if (! (asset instanceof Asset)) { - return; - } - - const responseAsset: AssetMetadata | undefined = response.find((metadata: AssetMetadata) => { - return (metadata.policyId === asset.policyId) && (metadata.nameHex === asset.nameHex); - }); - - asset.decimals = responseAsset ? responseAsset.decimals : 0; - }); - }); - }); - } - - /** - * Check if a pools assets match the supplied token filters. - */ - private poolMatchesFilter(liquidityPool: LiquidityPool): boolean { - if (! this._filteredTokens.length && ! this._filteredPairs.length) { - return true; - } - - const inFilteredTokens: boolean = this._filteredTokens.some((filterToken: Token) => { - return tokensMatch(filterToken, liquidityPool.assetA) || tokensMatch(filterToken, liquidityPool.assetB); - }); - const inFilteredPairs: boolean = this._filteredPairs.some((filterPair: Token[]) => { - return (tokensMatch(filterPair[0], liquidityPool.assetA) && tokensMatch(filterPair[1], liquidityPool.assetB)) - || (tokensMatch(filterPair[0], liquidityPool.assetB) && tokensMatch(filterPair[1], liquidityPool.assetA)); - }); - - return inFilteredTokens || inFilteredPairs; - } - - /** - * Fetch liquidity pools from DEX APIs using the provided token filters. - */ - private fetchPoolsFromApi(dex: BaseDex): Promise { - const filterTokenPromises: Promise[] = this._filteredTokens.map((token: Token) => { - return dex.api.liquidityPools(token) - .catch(() => []); - }); - const filterPairPromises: Promise[] = this._filteredPairs.map((pair: Token[]) => { - return dex.api.liquidityPools(pair[0], pair[1]) - .catch(() => []); - }); - - return Promise.all( - filterTokenPromises.concat(filterPairPromises).flat(), - ).then((allLiquidityPools: Awaited[]) => { - return allLiquidityPools - .flat() - .filter((pool?: LiquidityPool) => pool !== undefined) as LiquidityPool[]; - }); - } - -} diff --git a/src/requests/split-swap-request.ts b/src/requests/split-swap-request.ts index bbd6fde..d50e75f 100644 --- a/src/requests/split-swap-request.ts +++ b/src/requests/split-swap-request.ts @@ -1,10 +1,9 @@ -import { LiquidityPool } from '@dex/models/liquidity-pool'; -import { Token } from '@dex/models/asset'; import { Dexter } from '@app/dexter'; import { PayToAddress, SwapFee, SwapInAmountMapping, SwapOutAmountMapping, UTxO } from '@app/types'; import { MetadataKey, TransactionStatus } from '@app/constants'; import { DexTransaction } from '@dex/models/dex-transaction'; import { SwapRequest } from '@requests/swap-request'; +import { LiquidityPool, Token } from '@indigo-labs/iris-sdk'; export class SplitSwapRequest { @@ -193,8 +192,8 @@ export class SplitSwapRequest { private sendSplitSwapOrder(splitSwapTransaction: DexTransaction, payToAddresses: PayToAddress[]) { splitSwapTransaction.status = TransactionStatus.Building; - const swapInTokenName: string = this._swapInToken === 'lovelace' ? 'ADA' : this._swapInToken.assetName; - const swapOutTokenName: string = this._swapOutToken === 'lovelace' ? 'ADA' : this._swapOutToken.assetName; + const swapInTokenName: string = this._swapInToken === 'lovelace' ? 'ADA' : this._swapInToken.readableTicker; + const swapOutTokenName: string = this._swapOutToken === 'lovelace' ? 'ADA' : this._swapOutToken.readableTicker; splitSwapTransaction.attachMetadata(MetadataKey.Message, { msg: [ this._metadata !== '' ? this._metadata : `[${this._dexter.config.metadataMsgBranding}] Split ${swapInTokenName} -> ${swapOutTokenName} Swap` diff --git a/src/requests/swap-request.ts b/src/requests/swap-request.ts index 0e38905..dfaff54 100644 --- a/src/requests/swap-request.ts +++ b/src/requests/swap-request.ts @@ -1,10 +1,9 @@ -import { LiquidityPool } from '@dex/models/liquidity-pool'; -import { Token } from '@dex/models/asset'; import { Dexter } from '@app/dexter'; import { tokensMatch } from '@app/utils'; import { DatumParameters, PayToAddress, SpendUTxO, SwapFee, UTxO } from '@app/types'; import { DatumParameterKey, MetadataKey, TransactionStatus } from '@app/constants'; import { DexTransaction } from '@dex/models/dex-transaction'; +import { LiquidityPool, Token } from '@indigo-labs/iris-sdk'; export class SwapRequest { @@ -71,10 +70,10 @@ export class SwapRequest { throw new Error('Liquidity pool must be set before providing an input token.'); } - if (tokensMatch(swapInToken, this._liquidityPool.assetA)) { - this._swapOutToken = this._liquidityPool.assetB; - } else if (tokensMatch(swapInToken, this._liquidityPool.assetB)) { - this._swapOutToken = this._liquidityPool.assetA; + if (tokensMatch(swapInToken, this._liquidityPool.tokenA)) { + this._swapOutToken = this._liquidityPool.tokenB; + } else if (tokensMatch(swapInToken, this._liquidityPool.tokenB)) { + this._swapOutToken = this._liquidityPool.tokenA; } else { throw new Error("Input token doesn't exist in the set liquidity pool."); } @@ -89,10 +88,10 @@ export class SwapRequest { throw new Error('Liquidity pool must be set before providing an input token.'); } - if (tokensMatch(swapOutToken, this._liquidityPool.assetA)) { - this._swapInToken = this._liquidityPool.assetB; - } else if (tokensMatch(swapOutToken, this._liquidityPool.assetB)) { - this._swapInToken = this._liquidityPool.assetA; + if (tokensMatch(swapOutToken, this._liquidityPool.tokenA)) { + this._swapInToken = this._liquidityPool.tokenB; + } else if (tokensMatch(swapOutToken, this._liquidityPool.tokenB)) { + this._swapInToken = this._liquidityPool.tokenA; } else { throw new Error("Output token doesn't exist in the set liquidity pool."); } @@ -248,7 +247,6 @@ export class SwapRequest { utxo, } }) as SpendUTxO[], - this._dexter.dataProvider ); } @@ -277,8 +275,8 @@ export class SwapRequest { private sendSwapOrder(swapTransaction: DexTransaction, payToAddresses: PayToAddress[]) { swapTransaction.status = TransactionStatus.Building; - const swapInTokenName: string = this._swapInToken === 'lovelace' ? 'ADA' : this._swapInToken.assetName; - const swapOutTokenName: string = this._swapOutToken === 'lovelace' ? 'ADA' : this._swapOutToken.assetName; + const swapInTokenName: string = this._swapInToken === 'lovelace' ? 'ADA' : this._swapInToken.readableTicker; + const swapOutTokenName: string = this._swapOutToken === 'lovelace' ? 'ADA' : this._swapOutToken.readableTicker; swapTransaction.attachMetadata(MetadataKey.Message, { msg: [ this._metadata !== '' ? this._metadata : `[${this._dexter.config.metadataMsgBranding}] ${this._liquidityPool.dex} ${swapInTokenName} -> ${swapOutTokenName} Swap` diff --git a/src/types.ts b/src/types.ts index 2c3f67a..824baa5 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,8 +1,7 @@ import { AddressType, DatumParameterKey, TransactionStatus } from './constants'; -import { Token } from '@dex/models/asset'; import { BaseDex } from '@dex/base-dex'; -import { LiquidityPool } from '@dex/models/liquidity-pool'; import { Script } from 'lucid-cardano'; +import { LiquidityPool, Token } from '@indigo-labs/iris-sdk'; export interface DexterConfig { shouldFetchMetadata?: boolean; diff --git a/src/utils.ts b/src/utils.ts index a80b97f..864cf89 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,8 +1,7 @@ -import { Token } from '@dex/models/asset'; -import { LiquidityPool } from '@dex/models/liquidity-pool'; import { C, Datum, fromHex, Lucid, toHex, Utils } from 'lucid-cardano'; import { DatumJson } from '@app/types'; import { encoder } from 'js-encoding-utils'; +import { LiquidityPool, Token } from '@indigo-labs/iris-sdk'; export const lucidUtils: Utils = new Utils(new Lucid()); @@ -14,9 +13,11 @@ export function tokensMatch(tokenA: Token, tokenB: Token): boolean { } export function correspondingReserves(liquidityPool: LiquidityPool, token: Token): bigint[] { - return tokensMatch(token, liquidityPool.assetA) - ? [liquidityPool.reserveA, liquidityPool.reserveB] - : [liquidityPool.reserveB, liquidityPool.reserveA] + if (! liquidityPool.state) return [0n, 0n]; + + return tokensMatch(token, liquidityPool.tokenA) + ? [liquidityPool.state.reserveA, liquidityPool.state.reserveB] + : [liquidityPool.state.reserveB, liquidityPool.state.reserveA] } export function appendSlash(value?: string) { diff --git a/tests/dex-transaction.test.ts b/tests/dex-transaction.test.ts deleted file mode 100644 index 76f7ef8..0000000 --- a/tests/dex-transaction.test.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { DexTransaction, MockWalletProvider, TransactionStatus } from '../src'; - -describe('DexTransaction', () => { - - const transaction: DexTransaction = new DexTransaction(new MockWalletProvider()); - - it('Fails to submit when un-signed', () => { - expect(() => { transaction.submit(); }).toThrowError(); - }); - - it('Can sign', () => { - return transaction.sign() - .then(() => { - expect(transaction.isSigned).toBe(true); - }); - }); - - it('Can submit', () => { - return transaction.submit() - .then(() => { - expect(transaction.hash).toBe('hashtest'); - }); - }); - - it('Can expose building status', () => { - const testTransaction: DexTransaction = new DexTransaction(new MockWalletProvider()); - let receivedStatus: boolean = false; - - testTransaction.onBuilding(() => receivedStatus = true); - - testTransaction.status = TransactionStatus.Building; - - expect(receivedStatus).toBe(true); - }); - - it('Can expose signing status', () => { - const testTransaction: DexTransaction = new DexTransaction(new MockWalletProvider()); - let receivedStatus: boolean = false; - - testTransaction.onSigning(() => receivedStatus = true); - - testTransaction.status = TransactionStatus.Signing; - - expect(receivedStatus).toBe(true); - }); - - it('Can expose submitting status', () => { - const testTransaction: DexTransaction = new DexTransaction(new MockWalletProvider()); - let receivedStatus: boolean = false; - - testTransaction.onSubmitting(() => receivedStatus = true); - - testTransaction.status = TransactionStatus.Submitting; - - expect(receivedStatus).toBe(true); - }); - - it('Can expose submitted status', () => { - const testTransaction: DexTransaction = new DexTransaction(new MockWalletProvider()); - let receivedStatus: boolean = false; - - testTransaction.onSubmitted(() => receivedStatus = true); - - testTransaction.status = TransactionStatus.Submitted; - - expect(receivedStatus).toBe(true); - }); - - it('Can expose error status', () => { - const testTransaction: DexTransaction = new DexTransaction(new MockWalletProvider()); - let receivedStatus: boolean = false; - - testTransaction.onError(() => receivedStatus = true); - - testTransaction.status = TransactionStatus.Errored; - - expect(receivedStatus).toBe(true); - }); - -}); diff --git a/tests/minswap.test.ts b/tests/minswap.test.ts deleted file mode 100644 index c9fda36..0000000 --- a/tests/minswap.test.ts +++ /dev/null @@ -1,147 +0,0 @@ -import { - Asset, - Dexter, - LiquidityPool, - Minswap, - MockDataProvider, - SwapRequest, - MockWalletProvider, - DatumParameters, - DatumParameterKey, - PayToAddress, - AddressType, - UTxO -} from '../src'; - -describe('Minswap', () => { - let minswap: Minswap; - const returnAddress = 'mockBlockchainAddress123'; - - beforeEach(() => { - minswap = new Minswap(); - }); - const walletProvider: MockWalletProvider = new MockWalletProvider(); - walletProvider.loadWalletFromSeedPhrase(['']); - const dexter: Dexter = (new Dexter()) - .withDataProvider(new MockDataProvider()) - .withWalletProvider(walletProvider); - const asset: Asset = new Asset('f66d78b4a3cb3d37afa0ec36461e51ecbde00f26c8f0a68f94b69880', '69555344', 6); - - - describe('Set Swap In', () => { - - const liquidityPool: LiquidityPool = new LiquidityPool( - Minswap.identifier, - 'lovelace', - asset, - 30817255371488n, - 349805856622734n, - 'addr1', - ); - liquidityPool.poolFeePercent = 0.3; - - const swapRequest: SwapRequest = dexter.newSwapRequest() - .forLiquidityPool(liquidityPool) - .withSwapInToken('lovelace') - .withSwapInAmount(10_000_000_000000n) - .withSlippagePercent(0.5); - - it('Can calculate swap parameters', () => { - expect(+swapRequest.getPriceImpactPercent().toFixed(2)).toEqual(24.37); - expect(swapRequest.getEstimatedReceive()).toEqual(85_506_228_814959n); - expect(swapRequest.getMinimumReceive()).toEqual(85_080_824_691501n); - }); - - it('Can build swap order', () => { - const minswap: Minswap = new Minswap(); - const defaultSwapParameters: DatumParameters = { - [DatumParameterKey.SenderPubKeyHash]: walletProvider.publicKeyHash(), - [DatumParameterKey.SenderStakingKeyHash]: walletProvider.stakingKeyHash(), - [DatumParameterKey.ReceiverPubKeyHash]: walletProvider.publicKeyHash(), - [DatumParameterKey.ReceiverStakingKeyHash]: walletProvider.stakingKeyHash(), - [DatumParameterKey.SwapInAmount]: swapRequest.swapInAmount, - [DatumParameterKey.MinReceive]: swapRequest.getMinimumReceive(), - [DatumParameterKey.SwapInTokenPolicyId]: '', - [DatumParameterKey.SwapInTokenAssetName]: '', - [DatumParameterKey.SwapOutTokenPolicyId]: asset.policyId, - [DatumParameterKey.SwapOutTokenAssetName]: asset.nameHex, - }; - - return minswap.buildSwapOrder(liquidityPool, defaultSwapParameters) - .then((payments: PayToAddress[]) => { - expect(() => { minswap.buildSwapOrder(liquidityPool, defaultSwapParameters); }).not.toThrowError(); - expect(payments[0].addressType).toBe(AddressType.Contract); - expect(payments[0].assetBalances[0].quantity).toEqual(10000004000000n); - expect(payments[0].datum).toBe('d8799fd8799fd8799f42ed56ffd8799fd8799fd8799f42ed56ffffffffd8799fd8799f42ed56ffd8799fd8799fd8799f42bac6ffffffffd87a80d8799fd8799f581cf66d78b4a3cb3d37afa0ec36461e51ecbde00f26c8f0a68f94b698804469555344ff1b00004d616c553b2dff1a001e84801a001e8480ff'); - }); - }); - - }); - - describe('Set Swap Out', () => { - const liquidityPool: LiquidityPool = new LiquidityPool( - Minswap.identifier, - 'lovelace', - asset, - 5126788000507n, - 1405674367646n, - 'addr1', - ); - liquidityPool.poolFeePercent = 0.3; - - const swapRequest: SwapRequest = dexter.newSwapRequest() - .forLiquidityPool(liquidityPool) - .withSwapInToken('lovelace') - .withSwapOutAmount(100_000000n) - .withSlippagePercent(0.5); - - it('Can calculate swap parameters', () => { - expect(swapRequest.swapInAmount).toEqual(365844367n); - }); - - }); - - describe('Minswap Cancel Order', () => { - - it('should successfully cancel an order', async () => { - let marketOrderAddress = minswap.marketOrderAddress; - const txOutputs: UTxO[] = [ - { - txHash: 'mockTxHash123', - address: marketOrderAddress, - datumHash: 'mockDatumHash123', - outputIndex: 0, - assetBalances: [{ asset: 'lovelace', quantity: 1000000000000n }] - } - ]; - - const result = await minswap.buildCancelSwapOrder(txOutputs, returnAddress); - - expect(result).toBeDefined(); - expect(result[0].address).toBe(returnAddress); - }); - - it('should fail to cancel an order with invalid UTxO', async () => { - const invalidTxOutputs: UTxO[] = [ - { - txHash: 'invalidTxHash', - address: 'invalidAddress', - datumHash: 'invalidDatumHash', - outputIndex: 0, - assetBalances: [{ asset: 'lovelace', quantity: 1000n }] - } - ]; - - - try { - await minswap.buildCancelSwapOrder(invalidTxOutputs, returnAddress); - fail('Expected buildCancelSwapOrder to throw an error'); - } catch (error: unknown) { - if (error instanceof Error) { - expect(error.message).toContain('Unable to find relevant UTxO for cancelling the swap order.'); - } - } - }); - }); - -}); diff --git a/tests/muesliswap.test.ts b/tests/muesliswap.test.ts deleted file mode 100644 index 29707a2..0000000 --- a/tests/muesliswap.test.ts +++ /dev/null @@ -1,147 +0,0 @@ -import { - Asset, - Dexter, - LiquidityPool, - MuesliSwap, - MockDataProvider, - SwapRequest, - MockWalletProvider, - DatumParameters, - DatumParameterKey, - PayToAddress, - AddressType, - UTxO -} from '../src'; - -describe('MuesliSwap', () => { - - const walletProvider: MockWalletProvider = new MockWalletProvider(); - walletProvider.loadWalletFromSeedPhrase(['']); - const dexter: Dexter = (new Dexter()) - .withDataProvider(new MockDataProvider()) - .withWalletProvider(walletProvider); - const asset: Asset = new Asset('f66d78b4a3cb3d37afa0ec36461e51ecbde00f26c8f0a68f94b69880', '69555344', 6); - - describe('Set Swap In', () => { - - const liquidityPool: LiquidityPool = new LiquidityPool( - MuesliSwap.identifier, - 'lovelace', - asset, - 1386837721743n, - 485925n, - 'addr1', - ); - liquidityPool.poolFeePercent = 0.3; - - const swapRequest: SwapRequest = dexter.newSwapRequest() - .forLiquidityPool(liquidityPool) - .withSwapInToken('lovelace') - .withSwapInAmount(100_000_000000n) - .withSlippagePercent(3.0); - - it('Can calculate swap parameters', () => { - expect(+swapRequest.getPriceImpactPercent().toFixed(2)).toEqual(7.51); - expect(swapRequest.getEstimatedReceive()).toEqual(32590n); - expect(swapRequest.getMinimumReceive()).toEqual(31640n); - }); - - it('Can build swap order', () => { - const muesliswap: MuesliSwap = new MuesliSwap(); - const defaultSwapParameters: DatumParameters = { - [DatumParameterKey.SenderPubKeyHash]: walletProvider.publicKeyHash(), - [DatumParameterKey.SenderStakingKeyHash]: walletProvider.stakingKeyHash(), - [DatumParameterKey.ReceiverPubKeyHash]: walletProvider.publicKeyHash(), - [DatumParameterKey.ReceiverStakingKeyHash]: walletProvider.stakingKeyHash(), - [DatumParameterKey.SwapInAmount]: swapRequest.swapInAmount, - [DatumParameterKey.MinReceive]: swapRequest.getMinimumReceive(), - [DatumParameterKey.SwapInTokenPolicyId]: '', - [DatumParameterKey.SwapInTokenAssetName]: '', - [DatumParameterKey.SwapOutTokenPolicyId]: asset.policyId, - [DatumParameterKey.SwapOutTokenAssetName]: asset.nameHex, - }; - - return muesliswap.buildSwapOrder(liquidityPool, defaultSwapParameters) - .then((payments: PayToAddress[]) => { - expect(() => { muesliswap.buildSwapOrder(liquidityPool, defaultSwapParameters); }).not.toThrowError(); - expect(payments[0].addressType).toBe(AddressType.Contract); - expect(payments[0].assetBalances[0].quantity).toEqual(100002650000n); - expect(payments[0].datum).toBe('d8799fd8799fd8799fd8799f42ed56ffd8799fd8799fd8799f42bac6ffffffff581cf66d78b4a3cb3d37afa0ec36461e51ecbde00f26c8f0a68f94b6988044695553444040197b98d87a801a00286f90ffff'); - }); - }); - - }); - - describe('Set Swap Out', () => { - const liquidityPool: LiquidityPool = new LiquidityPool( - MuesliSwap.identifier, - 'lovelace', - asset, - 67011967873n, - 5026969972n, - 'addr1', - ); - liquidityPool.poolFeePercent = 0.3; - - const swapRequest: SwapRequest = dexter.newSwapRequest() - .forLiquidityPool(liquidityPool) - .withSwapInToken('lovelace') - .withSwapOutAmount(10_000000n) - .withSlippagePercent(0.5); - - it('Can calculate swap parameters', () => { - expect(swapRequest.swapInAmount).toEqual(133971309n); - }); - - }); - - describe('Muesliswap Cancel Order', () => { - let muesliswap: MuesliSwap; - const returnAddress = 'mockBlockchainAddress123'; - - beforeEach(() => { - muesliswap = new MuesliSwap(); - }); - - it('should successfully cancel an order', async () => { - let orderAddress = muesliswap.orderAddress; - const txOutputs: UTxO[] = [ - { - txHash: 'mockTxHash123', - address: orderAddress, - datumHash: 'mockDatumHash123', - outputIndex: 0, - assetBalances: [{ asset: 'lovelace', quantity: 10000n }] - } - ]; - - const result = await muesliswap.buildCancelSwapOrder(txOutputs, returnAddress); - - expect(result).toBeDefined(); - expect(result[0].address).toBe(returnAddress); - }); - - it('should fail to cancel an order with invalid UTxO', async () => { - const invalidTxOutputs: UTxO[] = [ - { - txHash: 'invalidTxHash', - address: 'invalidAddress', - datumHash: 'invalidDatumHash', - outputIndex: 0, - assetBalances: [{ asset: 'lovelace', quantity: 10000n }] - } - ]; - - try { - await muesliswap.buildCancelSwapOrder(invalidTxOutputs, returnAddress); - fail('Expected buildCancelSwapOrder to throw an error'); - } catch (error: unknown) { - if (error instanceof Error) { - expect(error.message).toContain('Unable to find relevant UTxO for cancelling the swap order.'); - } - } - }); - - }); - -}); diff --git a/tests/split-swap-request.test.ts b/tests/split-swap-request.test.ts deleted file mode 100644 index 26241be..0000000 --- a/tests/split-swap-request.test.ts +++ /dev/null @@ -1,127 +0,0 @@ -import { - Asset, - Dexter, - LiquidityPool, - MockDataProvider, - MockWalletProvider, - WingRiders, - Minswap -} from '../src'; -import { SplitSwapRequest } from '../src/requests/split-swap-request'; - -describe('SplitSwapRequest', () => { - - const walletProvider: MockWalletProvider = new MockWalletProvider(); - walletProvider.loadWalletFromSeedPhrase(['']); - const dexter: Dexter = (new Dexter()) - .withDataProvider(new MockDataProvider()) - .withWalletProvider(walletProvider); - const asset: Asset = new Asset('f66d78b4a3cb3d37afa0ec36461e51ecbde00f26c8f0a68f94b69880', '69555344', 6); - - const minswapPool: LiquidityPool = new LiquidityPool( - Minswap.identifier, - 'lovelace', - asset, - 30817255371488n, - 349805856622734n, - 'addr1', - ); - minswapPool.poolFeePercent = 0.3 - - const wingridersPool: LiquidityPool = new LiquidityPool( - WingRiders.identifier, - 'lovelace', - asset, - 923224398616n, - 7942169n, - 'addr1', - ); - wingridersPool.poolFeePercent = 0.35; - - describe('Parameter setting', () => { - - const swapRequest: SplitSwapRequest = dexter.newSplitSwapRequest(); - - it('Can set swap in token', () => { - swapRequest.withSwapInToken('lovelace') - - expect(swapRequest.swapInToken).toBe('lovelace'); - }); - - it('Can set swap out token', () => { - swapRequest.withSwapOutToken('lovelace') - - expect(swapRequest.swapOutToken).toBe('lovelace'); - }); - - it('Can set swap in mappings', () => { - swapRequest.withSwapInAmountMappings([ - { - swapInAmount: 2_000000n, - liquidityPool: minswapPool, - } - ]) - - expect(swapRequest.swapRequests[0].liquidityPool.uuid).toBe(minswapPool.uuid); - expect(swapRequest.swapRequests[0].swapInAmount).toBe(2_000000n); - }); - - it('Can set swap out mappings', () => { - swapRequest.withSwapOutAmountMappings([ - { - swapOutAmount: 2_000000n, - liquidityPool: minswapPool, - } - ]) - - expect(swapRequest.swapRequests[0].liquidityPool.uuid).toBe(minswapPool.uuid); - }); - - }) - - describe('Alter Order', () => { - - it('Can flip all swap in tokens', () => { - const swapRequest: SplitSwapRequest = dexter.newSplitSwapRequest(); - - swapRequest - .withSwapInToken(asset) - .withSwapInAmountMappings([ - { - swapInAmount: 2_000000n, - liquidityPool: minswapPool, - }, - { - swapInAmount: 2_000000n, - liquidityPool: wingridersPool, - } - ]) - .flip(); - - expect(swapRequest.swapRequests[0].swapInToken).toBe('lovelace'); - expect(swapRequest.swapRequests[1].swapInToken).toBe('lovelace'); - }); - - it('Can calculate avg. price impact percent', () => { - const swapRequest: SplitSwapRequest = dexter.newSplitSwapRequest(); - - swapRequest - .withSwapInToken('lovelace') - .withSlippagePercent(0.5) - .withSwapInAmountMappings([ - { - swapInAmount: 10_000_000_000000n, - liquidityPool: minswapPool, - }, - { - swapInAmount: 10_000_000000n, - liquidityPool: wingridersPool, - } - ]); - - expect(+swapRequest.getAvgPriceImpactPercent().toFixed(2)).toEqual(12.90); - }); - - }); - -}); diff --git a/tests/sundaeswap-v1.test.ts b/tests/sundaeswap-v1.test.ts deleted file mode 100644 index 8791557..0000000 --- a/tests/sundaeswap-v1.test.ts +++ /dev/null @@ -1,150 +0,0 @@ -import { - Asset, - Dexter, - LiquidityPool, - SundaeSwapV1, - MockDataProvider, - SwapRequest, - MockWalletProvider, - DatumParameters, - DatumParameterKey, - PayToAddress, - AddressType, - UTxO, -} from '../src'; - -describe('SundaeSwapV1', () => { - - const walletProvider: MockWalletProvider = new MockWalletProvider(); - walletProvider.loadWalletFromSeedPhrase(['']); - const dexter: Dexter = (new Dexter()) - .withDataProvider(new MockDataProvider()) - .withWalletProvider(walletProvider); - const asset: Asset = new Asset('f66d78b4a3cb3d37afa0ec36461e51ecbde00f26c8f0a68f94b69880', '69555344', 6); - - describe('Set Swap In', () => { - - const liquidityPool: LiquidityPool = new LiquidityPool( - SundaeSwapV1.identifier, - 'lovelace', - asset, - 3699642000000n, - 78391015000000n, - 'addr1', - ); - liquidityPool.poolFeePercent = 0.3; - - - const swapRequest: SwapRequest = dexter.newSwapRequest() - .forLiquidityPool(liquidityPool) - .withSwapInToken('lovelace') - .withSwapInAmount(10_000_000000n) - .withSlippagePercent(1.0); - - it('Can calculate swap parameters', () => { - expect(+swapRequest.getPriceImpactPercent().toFixed(2)).toEqual(0.27); - expect(swapRequest.getEstimatedReceive()).toEqual(210_684_680649n); - expect(swapRequest.getMinimumReceive()).toEqual(208_598_693711n); - }); - - it('Can build swap order', () => { - const sundaeswap: SundaeSwapV1 = new SundaeSwapV1(); - const defaultSwapParameters: DatumParameters = { - [DatumParameterKey.PoolIdentifier]: '1234', - [DatumParameterKey.SenderPubKeyHash]: walletProvider.publicKeyHash(), - [DatumParameterKey.SenderStakingKeyHash]: walletProvider.stakingKeyHash(), - [DatumParameterKey.ReceiverPubKeyHash]: walletProvider.publicKeyHash(), - [DatumParameterKey.ReceiverStakingKeyHash]: walletProvider.stakingKeyHash(), - [DatumParameterKey.SwapInAmount]: swapRequest.swapInAmount, - [DatumParameterKey.MinReceive]: swapRequest.getMinimumReceive(), - [DatumParameterKey.SwapInTokenPolicyId]: '', - [DatumParameterKey.SwapInTokenAssetName]: '', - [DatumParameterKey.SwapOutTokenPolicyId]: asset.policyId, - [DatumParameterKey.SwapOutTokenAssetName]: asset.nameHex, - }; - - return sundaeswap.buildSwapOrder(liquidityPool, defaultSwapParameters) - .then((payments: PayToAddress[]) => { - expect(() => { sundaeswap.buildSwapOrder(liquidityPool, defaultSwapParameters); }).not.toThrowError(); - expect(payments[0].addressType).toBe(AddressType.Contract); - expect(payments[0].assetBalances[0].quantity).toEqual(10004500000n); - expect(payments[0].datum).toBe('d8799f421234d8799fd8799fd8799fd8799f42ed56ffd8799fd8799fd8799f42bac6ffffffffd87a80ffd87a80ff1a002625a0d8799fd879801b00000002540be400d8799f1b000000309173774fffffff'); - }); - }); - - }); - - describe('Set Swap Out', () => { - - const liquidityPool: LiquidityPool = new LiquidityPool( - SundaeSwapV1.identifier, - 'lovelace', - asset, - 1032791394311n, - 74925313821n, - 'addr1', - ); - liquidityPool.poolFeePercent = 0.3; - - const swapRequest: SwapRequest = dexter.newSwapRequest() - .forLiquidityPool(liquidityPool) - .withSwapInToken('lovelace') - .withSwapOutAmount(100_000000n) - .withSlippagePercent(0.5); - - it('Can calculate swap parameters', () => { - expect(swapRequest.swapInAmount).toEqual(1384410858n); - }); - - }); - - describe('SundaeSwap Cancel Order', () => { - let sundaeswap: SundaeSwapV1; - const returnAddress = 'addr1'; - - beforeEach(() => { - sundaeswap = new SundaeSwapV1(); - }); - - it('should successfully cancel an order', async () => { - let marketOrderAddress = sundaeswap.orderAddress; - const txOutputs: UTxO[] = [ - { - txHash: 'mockTxHash123', - address: marketOrderAddress, - datumHash: 'mockDatumHash123', - outputIndex: 0, - assetBalances: [{ asset: 'lovelace', quantity: 1000000000000n }] - } - ]; - - const result = await sundaeswap.buildCancelSwapOrder(txOutputs, returnAddress); - - expect(result).toBeDefined(); - expect(result[0].address).toBe(returnAddress); - }); - - it('should fail to cancel an order with invalid UTxO', async () => { - const invalidTxOutputs: UTxO[] = [ - { - txHash: 'invalidTxHash', - address: 'invalidAddress', - datumHash: 'invalidDatumHash', - outputIndex: 0, - assetBalances: [{ asset: 'lovelace', quantity: 1000000000000n }] - } - ]; - try { - await sundaeswap.buildCancelSwapOrder(invalidTxOutputs, returnAddress); - fail('Expected buildCancelSwapOrder to throw an error'); - } catch (error: unknown) { - if (error instanceof Error) { - expect(error.message).toContain('Unable to find relevant UTxO for cancelling the swap order.'); - } - } - - }); - - }); - -}); diff --git a/tests/swap-request.test.ts b/tests/swap-request.test.ts deleted file mode 100644 index 0597387..0000000 --- a/tests/swap-request.test.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { - Asset, - Dexter, - LiquidityPool, - MockDataProvider, - MockWalletProvider, - SwapRequest, - WingRiders, - Minswap -} from '../src'; - -describe('SwapRequest', () => { - - const walletProvider: MockWalletProvider = new MockWalletProvider(); - walletProvider.loadWalletFromSeedPhrase(['']); - const dexter: Dexter = (new Dexter()) - .withDataProvider(new MockDataProvider()) - .withWalletProvider(walletProvider); - const asset: Asset = new Asset('f66d78b4a3cb3d37afa0ec36461e51ecbde00f26c8f0a68f94b69880', '69555344', 6); - - describe('Parameter setting', () => { - - const liquidityPool: LiquidityPool = new LiquidityPool( - WingRiders.identifier, - 'lovelace', - asset, - 1_000000n, - 1_000000n, - 'addr1', - ); - const swapRequest: SwapRequest = dexter.newSwapRequest() - .forLiquidityPool(liquidityPool); - - it('Can set liquidity pool', () => { - expect(swapRequest.liquidityPool.uuid).toBe(liquidityPool.uuid); - }); - - it('Can set swap tokens', () => { - swapRequest.withSwapInToken('lovelace'); - - expect(swapRequest.swapInToken).toBe('lovelace'); - expect((swapRequest.swapOutToken as Asset).identifier()).toBe(asset.identifier()); - }); - - it('Fails on invalid swap in token', () => { - expect(() => { swapRequest.withSwapInToken(new Asset('test1', 'test2')); }).toThrowError(); - }); - - it('Can flip swap tokens', () => { - swapRequest.withSwapInToken('lovelace') - .flip(); - - expect((swapRequest.swapInToken as Asset).identifier()).toBe(asset.identifier()); - expect(swapRequest.swapOutToken).toBe('lovelace'); - }); - - it('Can set swap in amount', () => { - swapRequest.withSwapInToken('lovelace') - .withSwapInAmount(100n); - - expect(swapRequest.swapInAmount).toBe(100n); - }); - - it('Fails on incorrect swap in amount', () => { - swapRequest.withSwapInToken('lovelace'); - swapRequest.withSwapInAmount(-1n) - - expect(swapRequest.swapInAmount).toBe(0n); - }); - - it('Can set slippage percent', () => { - swapRequest.withSlippagePercent(5.0); - - expect(swapRequest.slippagePercent).toBe(5.0); - }); - - it('Fails on incorrect slippage percent', () => { - expect(() => { swapRequest.withSlippagePercent(-5.0); }).toThrowError(); - }); - - }); - - describe('Alter Order', () => { - - const liquidityPool: LiquidityPool = new LiquidityPool( - Minswap.identifier, - 'lovelace', - asset, - 30817255371488n, - 349805856622734n, - 'addr1', - ); - liquidityPool.poolFeePercent = 0.3; - - const swapRequest: SwapRequest = dexter.newSwapRequest() - .forLiquidityPool(liquidityPool) - .withSwapInToken('lovelace') - .withSwapInAmount(10_000_000_000000n) - .withSlippagePercent(0.5); - - it('Can flip swap in & swap out amounts', () => { - swapRequest.flip(); - - expect(swapRequest.swapOutToken).toBe('lovelace'); - expect(swapRequest.swapInAmount).toBe(168542118380811n); - expect(swapRequest.getEstimatedReceive()).toBe(10_000_000_000000n); - }); - - }); - -}); diff --git a/tests/vyfinance.test.ts b/tests/vyfinance.test.ts deleted file mode 100644 index 0b8773e..0000000 --- a/tests/vyfinance.test.ts +++ /dev/null @@ -1,185 +0,0 @@ -import { - AddressType, - Asset, - DatumParameterKey, - DatumParameters, - Dexter, - LiquidityPool, - MockDataProvider, - MockWalletProvider, - PayToAddress, - SwapRequest, - UTxO, - VyFinance, -} from '../src'; - -describe('VyFinance', () => { - - const walletProvider: MockWalletProvider = new MockWalletProvider(); - walletProvider.loadWalletFromSeedPhrase(['']); - const dexter: Dexter = (new Dexter()) - .withDataProvider(new MockDataProvider()) - .withWalletProvider(walletProvider); - const asset: Asset = new Asset('f66d78b4a3cb3d37afa0ec36461e51ecbde00f26c8f0a68f94b69880', '69555344', 6); - - describe('Set Swap In', () => { - - const liquidityPool: LiquidityPool = new LiquidityPool( - VyFinance.identifier, - 'lovelace', - asset, - 519219742499n, - 39619096012n, - 'addr1', - ); - liquidityPool.poolFeePercent = 0.3; - liquidityPool.marketOrderAddress = 'addr1testorder'; - - const swapRequest: SwapRequest = dexter.newSwapRequest() - .forLiquidityPool(liquidityPool) - .withSwapInToken('lovelace') - .withSwapInAmount(100_000_000000n) - .withSlippagePercent(0.5); - - it('Can calculate swap parameters', () => { - expect(+swapRequest.getPriceImpactPercent().toFixed(2)).toEqual(16.11); - expect(swapRequest.getEstimatedReceive()).toEqual(6382126148n); - expect(swapRequest.getMinimumReceive()).toEqual(6350374276n); - }); - - it('Can build swap order', () => { - const vyfi: VyFinance = new VyFinance(); - const defaultSwapParameters: DatumParameters = { - [DatumParameterKey.SenderPubKeyHash]: walletProvider.publicKeyHash(), - [DatumParameterKey.SenderStakingKeyHash]: walletProvider.stakingKeyHash(), - [DatumParameterKey.ReceiverPubKeyHash]: walletProvider.publicKeyHash(), - [DatumParameterKey.ReceiverStakingKeyHash]: walletProvider.stakingKeyHash(), - [DatumParameterKey.SwapInAmount]: swapRequest.swapInAmount, - [DatumParameterKey.MinReceive]: swapRequest.getMinimumReceive(), - [DatumParameterKey.SwapInTokenPolicyId]: '', - [DatumParameterKey.SwapInTokenAssetName]: '', - [DatumParameterKey.SwapOutTokenPolicyId]: asset.policyId, - [DatumParameterKey.SwapOutTokenAssetName]: asset.nameHex, - }; - - return vyfi.buildSwapOrder(liquidityPool, defaultSwapParameters) - .then((payments: PayToAddress[]) => { - expect(() => { vyfi.buildSwapOrder(liquidityPool, defaultSwapParameters); }).not.toThrowError(); - expect(payments[0].addressType).toBe(AddressType.Contract); - expect(payments[0].assetBalances[0].quantity).toBe(100_003_900000n); - expect(payments[0].datum).toBe('d8799f44ed56bac6d87c9f1b000000017a830584ffff'); - }); - }); - - }); - - describe('Set Swap Out', () => { - - const liquidityPool: LiquidityPool = new LiquidityPool( - VyFinance.identifier, - 'lovelace', - asset, - 519179782499n, - 39622139292n, - 'addr1', - ); - liquidityPool.poolFeePercent = 0.3; - - const swapRequest: SwapRequest = dexter.newSwapRequest() - .forLiquidityPool(liquidityPool) - .withSwapInToken('lovelace') - .withSwapOutAmount(1_000_000000n) - .withSlippagePercent(0.5); - - it('Can calculate swap parameters', () => { - expect(swapRequest.swapInAmount).toEqual(13482992348n); - }); - - }); - - describe('VyFinance Cancel Order', () => { - let vyFinance: VyFinance; - const returnAddress = 'addr1'; - beforeEach(() => { - vyFinance = new VyFinance(); - vyFinance.api.liquidityPools = async () => { - const liquidityPool = new LiquidityPool( - VyFinance.identifier, - 'lovelace', - new Asset('f66d78b4a3cb3d37afa0ec36461e51ecbde00f26c8f0a68f94b69880', '69555344'), - 519219742499n, - 39619096012n, - 'mockPoolAddress', - 'mockMarketOrderAddress', - 'mockLimitOrderAddress', - ); - liquidityPool.extra = { - nft: { - policyId: 'mockNftPolicyId' - } - }; - - return [liquidityPool]; - }; - }); - - it('should successfully cancel an order', async () => { - const MockUTxO: UTxO[] = [{ - txHash: 'mockTxHash', - address: 'mockMarketOrderAddress', - datumHash: 'mockDatumHash', - outputIndex: 0, - assetBalances: [{asset: 'lovelace', quantity: 1000000000000n}] - }]; - - const cancelOrder = await vyFinance.buildCancelSwapOrder(MockUTxO, returnAddress); - expect(cancelOrder).toBeDefined(); - expect(cancelOrder[0].address).toBe('addr1'); - expect(cancelOrder[0].assetBalances[0].quantity).toBe(1000000000000n); - }); - - it('should fail to cancel an order when the liquidity pool is not found', async () => { - const mockUTxO: UTxO[] = [{ - txHash: 'mockTxHash', - address: 'mockAddress', - datumHash: 'mockDatumHash', - outputIndex: 0, - assetBalances: [{asset: 'lovelace', quantity: 1000000000000n}] - }]; - - try { - await vyFinance.buildCancelSwapOrder(mockUTxO, returnAddress); - fail('Expected buildCancelSwapOrder to throw an error'); - } catch (error: unknown) { - if (error instanceof Error) { - expect(error.message).toContain('Unable to find relevant liquidity pool for cancelling the swap order.'); - } - } - - }); - - it('should fail to cancel an order with invalid UTxO', async () => { - const invalidTxOutputs: UTxO[] = [ - { - txHash: 'invalidTxHash', - address: 'invalidAddress', - datumHash: 'invalidDatumHash', - outputIndex: 0, - assetBalances: [{ asset: 'lovelace', quantity: 1000000000000n }] - } - ]; - - try { - await vyFinance.buildCancelSwapOrder(invalidTxOutputs, returnAddress); - fail('Expected buildCancelSwapOrder to throw an error'); - } catch (error: unknown) { - if (error instanceof Error) { - expect(error.message).toContain('Unable to find relevant UTxO for cancelling the swap order.'); - } - } - - }); - - }); - -}); diff --git a/tests/wingriders.test.ts b/tests/wingriders.test.ts deleted file mode 100644 index 06b054b..0000000 --- a/tests/wingriders.test.ts +++ /dev/null @@ -1,166 +0,0 @@ -import { - Dexter, - LiquidityPool, - WingRiders, - MockDataProvider, - SwapRequest, - Asset, - MockWalletProvider, - DatumParameters, - DatumParameterKey, - PayToAddress, - AddressType, UTxO, -} from '../src'; - -describe('WingRiders', () => { - - const walletProvider: MockWalletProvider = new MockWalletProvider(); - walletProvider.loadWalletFromSeedPhrase(['']); - const dexter: Dexter = (new Dexter()) - .withDataProvider(new MockDataProvider()) - .withWalletProvider(walletProvider); - const asset: Asset = new Asset('f66d78b4a3cb3d37afa0ec36461e51ecbde00f26c8f0a68f94b69880', '69555344', 6); - - describe('Set Swap In', () => { - - const liquidityPool: LiquidityPool = new LiquidityPool( - WingRiders.identifier, - 'lovelace', - asset, - 923224398616n, - 7942169n, - 'addr1', - ); - liquidityPool.poolFeePercent = 0.35; - - const swapRequest: SwapRequest = dexter.newSwapRequest() - .forLiquidityPool(liquidityPool) - .withSwapInToken('lovelace') - .withSwapInAmount(10_000_000000n) - .withSlippagePercent(0.5); - - it('Can calculate swap parameters', () => { - expect(+swapRequest.getPriceImpactPercent().toFixed(2)).toEqual(1.43); - expect(swapRequest.getEstimatedReceive()).toEqual(84809n); - expect(swapRequest.getMinimumReceive()).toEqual(84387n); - }); - - it('Can build swap order', () => { - const wingriders: WingRiders = new WingRiders(); - const defaultSwapParameters: DatumParameters = { - [DatumParameterKey.SenderPubKeyHash]: walletProvider.publicKeyHash(), - [DatumParameterKey.SenderStakingKeyHash]: walletProvider.stakingKeyHash(), - [DatumParameterKey.ReceiverPubKeyHash]: walletProvider.publicKeyHash(), - [DatumParameterKey.ReceiverStakingKeyHash]: walletProvider.stakingKeyHash(), - [DatumParameterKey.SwapInAmount]: swapRequest.swapInAmount, - [DatumParameterKey.MinReceive]: swapRequest.getMinimumReceive(), - [DatumParameterKey.SwapInTokenPolicyId]: '', - [DatumParameterKey.SwapInTokenAssetName]: '', - [DatumParameterKey.SwapOutTokenPolicyId]: asset.policyId, - [DatumParameterKey.SwapOutTokenAssetName]: asset.nameHex, - }; - - return wingriders.buildSwapOrder(liquidityPool, defaultSwapParameters) - .then((payments: PayToAddress[]) => { - expect(() => { wingriders.buildSwapOrder(liquidityPool, defaultSwapParameters); }).not.toThrowError(); - expect(payments[0].addressType).toBe(AddressType.Contract); - expect(payments[0].assetBalances[0].quantity).toEqual(10004000000n); - }); - }); - - it('Can calculate price impact with 0 decimals', () => { - const hosky: Asset = new Asset('a0028f350aaabe0545fdcb56b039bfb08e4bb4d8c4d7c3c7d481c235', '484f534b59', 0); - const hoskyPool: LiquidityPool = new LiquidityPool( - WingRiders.identifier, - 'lovelace', - hosky, - 52428070796n, - 1424861277563n, - 'addr1', - ); - hoskyPool.poolFeePercent = 0.35; - - const swap: SwapRequest = dexter.newSwapRequest() - .forLiquidityPool(hoskyPool) - .withSwapInToken('lovelace') - .withSwapInAmount(1_000_000000n) - .withSlippagePercent(0.5); - - expect(+swap.getPriceImpactPercent().toFixed(2)).toEqual(2.23); - }); - - }); - - describe('Set Swap Out', () => { - - const liquidityPool: LiquidityPool = new LiquidityPool( - WingRiders.identifier, - 'lovelace', - asset, - 925723148616n, - 7920796n, - 'addr1', - ); - liquidityPool.poolFeePercent = 0.35; - - const swapRequest: SwapRequest = dexter.newSwapRequest() - .forLiquidityPool(liquidityPool) - .withSwapInToken('lovelace') - .withSwapOutAmount(1_000000n) - .withSlippagePercent(0.5); - - it('Can calculate swap parameters', () => { - expect(swapRequest.swapInAmount).toEqual(134229438286n); - }); - - }); - - describe('Wingriders Cancel Order', () => { - let wingRiders: WingRiders; - const returnAddress = 'addr1'; - beforeEach(() => { - wingRiders = new WingRiders(); - }); - - it('should successfully cancel an order', async () => { - let marketOrderAddress = wingRiders.orderAddress; - const txOutputs: UTxO[] = [ - { - txHash: 'mockTxHash123', - address: marketOrderAddress, - datumHash: 'mockDatumHash123', - outputIndex: 0, - assetBalances: [{ asset: 'lovelace', quantity: 1000000000000n }] - } - ]; - - const result = await wingRiders.buildCancelSwapOrder(txOutputs, returnAddress); - - expect(result).toBeDefined(); - expect(result[0].address).toBe(returnAddress); - }); - - it('should fail to cancel an order with invalid UTxO', async () => { - const invalidTxOutputs: UTxO[] = [ - { - txHash: 'invalidTxHash', - address: 'invalidAddress', - datumHash: 'invalidDatumHash', - outputIndex: 0, - assetBalances: [{ asset: 'lovelace', quantity: 1000000000000n }] - } - ]; - try { - await wingRiders.buildCancelSwapOrder(invalidTxOutputs, returnAddress); - fail('Expected buildCancelSwapOrder to throw an error'); - } catch (error: unknown) { - if (error instanceof Error) { - expect(error.message).toContain('Unable to find relevant UTxO for cancelling the swap order.'); - } - } - - }); - - }); - -}); From 3c4f9ba35dd0e6e3efce6a89bea3f9247381687d Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 15 Apr 2025 14:14:42 -0400 Subject: [PATCH 2/4] Iris version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1d7efd5..0e63339 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "prepublishOnly": "npm run test" }, "dependencies": { - "@indigo-labs/iris-sdk": "file:../iris-sdk", + "@indigo-labs/iris-sdk": "^1.0.4", "@types/blake2b": "^2.1.3", "@types/crypto-js": "^4.1.1", "axios": "^0.26.1", From d514dd172fdf8f6e4b2d4638d5220532bab2fea6 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 15 Apr 2025 15:26:03 -0400 Subject: [PATCH 3/4] Package lock --- package-lock.json | 677 +++++++++++++++++++++++++++++++--------------- 1 file changed, 462 insertions(+), 215 deletions(-) diff --git a/package-lock.json b/package-lock.json index a5829e1..24c575a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "5.4.10", "license": "MIT", "dependencies": { - "@indigo-labs/iris-sdk": "file:../iris-sdk", + "@indigo-labs/iris-sdk": "^1.0.4", "@types/blake2b": "^2.1.3", "@types/crypto-js": "^4.1.1", "axios": "^0.26.1", @@ -37,16 +37,6 @@ "typescript": "^5.0.3" } }, - "../iris-sdk": { - "version": "1.0.3", - "license": "MIT", - "dependencies": { - "axios": "^1.6.2" - }, - "devDependencies": { - "typescript": "^5.3.3" - } - }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -75,30 +65,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.5.tgz", - "integrity": "sha512-XvcZi1KWf88RVbF9wn8MN6tYFloU5qX8KjuF3E1PVBmJ9eypXfs4GRiJwLuTZL0iSnJUKn1BFPa5BPZZJyFzPg==", + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", + "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", - "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", + "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.26.0", - "@babel/generator": "^7.26.0", - "@babel/helper-compilation-targets": "^7.25.9", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.10", + "@babel/helper-compilation-targets": "^7.26.5", "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.0", - "@babel/parser": "^7.26.0", - "@babel/template": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.26.0", + "@babel/helpers": "^7.26.10", + "@babel/parser": "^7.26.10", + "@babel/template": "^7.26.9", + "@babel/traverse": "^7.26.10", + "@babel/types": "^7.26.10", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -114,13 +104,13 @@ } }, "node_modules/@babel/generator": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.5.tgz", - "integrity": "sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", + "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", "dev": true, "dependencies": { - "@babel/parser": "^7.26.5", - "@babel/types": "^7.26.5", + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -142,12 +132,12 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz", - "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz", + "integrity": "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.26.5", + "@babel/compat-data": "^7.26.8", "@babel/helper-validator-option": "^7.25.9", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", @@ -158,17 +148,17 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz", - "integrity": "sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.0.tgz", + "integrity": "sha512-vSGCvMecvFCd/BdpGlhpXYNhhC4ccxyvQWpbGL4CWbvfEoLFWUZuSuf7s9Aw70flgQF+6vptvgK2IfOnKlRmBg==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", "@babel/helper-member-expression-to-functions": "^7.25.9", "@babel/helper-optimise-call-expression": "^7.25.9", - "@babel/helper-replace-supers": "^7.25.9", + "@babel/helper-replace-supers": "^7.26.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", - "@babel/traverse": "^7.25.9", + "@babel/traverse": "^7.27.0", "semver": "^6.3.1" }, "engines": { @@ -179,9 +169,9 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.26.3.tgz", - "integrity": "sha512-G7ZRb40uUgdKOQqPLjfD12ZmGA54PzqDFUv2BKImnC9QIfGhIHKvVML0oN8IUiDq4iRqpq74ABpvOaerfWdong==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.0.tgz", + "integrity": "sha512-fO8l08T76v48BhpNRW/nQ0MxfnSdoSKUJBMjubOAYffsVuGG5qOfMq7N6Es7UJvi7Y8goXXo07EfcHZXDPuELQ==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", @@ -196,9 +186,9 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.3.tgz", - "integrity": "sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.4.tgz", + "integrity": "sha512-jljfR1rGnXXNWnmQg2K3+bvhkxB51Rl32QRaOTuwwjviGrHzIbSc8+x9CpraDtbT7mfyjXObULP4w/adunNwAw==", "dev": true, "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", @@ -364,25 +354,25 @@ } }, "node_modules/@babel/helpers": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", - "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz", + "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==", "dev": true, "dependencies": { - "@babel/template": "^7.25.9", - "@babel/types": "^7.26.0" + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.5.tgz", - "integrity": "sha512-SRJ4jYmXRqV1/Xc+TIVG84WjHBXKlxO9sHQnA2Pf12QQEAp1LOh6kDzNHXcUnbH1QI0FDoPPVOt+vyUDucxpaw==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", + "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", "dev": true, "dependencies": { - "@babel/types": "^7.26.5" + "@babel/types": "^7.27.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -751,14 +741,14 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.9.tgz", - "integrity": "sha512-RXV6QAzTBbhDMO9fWwOmwwTuYaiPbggWQ9INdZqAYeSHyG7FzQ+nOZaUUjNwKv9pV3aE4WFqFm1Hnbci5tBCAw==", + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.26.8.tgz", + "integrity": "sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-plugin-utils": "^7.26.5", "@babel/helper-remap-async-to-generator": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/traverse": "^7.26.8" }, "engines": { "node": ">=6.9.0" @@ -800,12 +790,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.9.tgz", - "integrity": "sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.0.tgz", + "integrity": "sha512-u1jGphZ8uDI2Pj/HJj6YQ6XQLZCNjOlprjxB5SVz6rq2T6SwAR+CdrWK0CP7F+9rDVMXdB0+r6Am5G5aobOjAQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.26.5" }, "engines": { "node": ">=6.9.0" @@ -990,12 +980,12 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.9.tgz", - "integrity": "sha512-LqHxduHoaGELJl2uhImHwRQudhCM50pT46rIBNvtT/Oql3nqiS3wOwP+5ten7NpYSXrrVLgtZU3DZmPtWZo16A==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.26.9.tgz", + "integrity": "sha512-Hry8AusVm8LW5BVFgiyUReuoGzPUpdHQQqJY5bZnbbf+ngOHWuCuYFKw/BqaaWlvEUrF91HMhDtEaI1hZzNbLg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-plugin-utils": "^7.26.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" }, "engines": { @@ -1337,12 +1327,12 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.9.tgz", - "integrity": "sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.0.tgz", + "integrity": "sha512-LX/vCajUJQDqE7Aum/ELUMZAY19+cDpghxrnyt5I1tV6X5PyC86AOoWXWFYFeIvauyeSA6/ktn4tQVn/3ZifsA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-plugin-utils": "^7.26.5", "regenerator-transform": "^0.15.2" }, "engines": { @@ -1430,12 +1420,12 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.9.tgz", - "integrity": "sha512-o97AE4syN71M/lxrCtQByzphAdlYluKPDBzDVzMmfCobUjjhAryZV0AIpRPrxN0eAkxXO6ZLEScmt+PNhj2OTw==", + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.26.8.tgz", + "integrity": "sha512-OmGDL5/J0CJPJZTHZbi2XpO0tyT2Ia7fzpW5GURwdtp2X3fMmN8au/ej6peC/T33/+CRiIpA8Krse8hFGVmT5Q==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.26.5" }, "engines": { "node": ">=6.9.0" @@ -1445,12 +1435,12 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.9.tgz", - "integrity": "sha512-v61XqUMiueJROUv66BVIOi0Fv/CUuZuZMl5NkRoCVxLAnMexZ0A3kMe7vvZ0nulxMuMp0Mk6S5hNh48yki08ZA==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.0.tgz", + "integrity": "sha512-+LLkxA9rKJpNoGsbLnAgOCdESl73vwYn+V6b+5wHbrE7OGKVDPHIQvbFSzqE6rwqaCw2RE+zdJrlLkcf8YOA0w==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.26.5" }, "engines": { "node": ">=6.9.0" @@ -1460,13 +1450,13 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.26.5.tgz", - "integrity": "sha512-GJhPO0y8SD5EYVCy2Zr+9dSZcEgaSmq5BLR0Oc25TOEhC+ba49vUAGZFjy8v79z9E1mdldq4x9d1xgh4L1d5dQ==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.27.0.tgz", + "integrity": "sha512-fRGGjO2UEGPjvEcyAZXRXAS8AfdaQoq7HnxAbJoAoW10B9xOKesmmndJv+Sym2a+9FHWZ9KbyyLCe9s0Sn5jtg==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.27.0", "@babel/helper-plugin-utils": "^7.26.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", "@babel/plugin-syntax-typescript": "^7.25.9" @@ -1542,14 +1532,14 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.0.tgz", - "integrity": "sha512-H84Fxq0CQJNdPFT2DrfnylZ3cf5K43rGfWK4LJGPpjKHiZlk0/RzwEus3PDDZZg+/Er7lCA03MVacueUuXdzfw==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.9.tgz", + "integrity": "sha512-vX3qPGE8sEKEAZCWk05k3cpTAE3/nOYca++JA+Rd0z2NCNzabmYvEiSShKzm10zdquOIAVXsy2Ei/DTW34KlKQ==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.26.0", - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", + "@babel/compat-data": "^7.26.8", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-plugin-utils": "^7.26.5", "@babel/helper-validator-option": "^7.25.9", "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9", "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9", @@ -1561,9 +1551,9 @@ "@babel/plugin-syntax-import-attributes": "^7.26.0", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", "@babel/plugin-transform-arrow-functions": "^7.25.9", - "@babel/plugin-transform-async-generator-functions": "^7.25.9", + "@babel/plugin-transform-async-generator-functions": "^7.26.8", "@babel/plugin-transform-async-to-generator": "^7.25.9", - "@babel/plugin-transform-block-scoped-functions": "^7.25.9", + "@babel/plugin-transform-block-scoped-functions": "^7.26.5", "@babel/plugin-transform-block-scoping": "^7.25.9", "@babel/plugin-transform-class-properties": "^7.25.9", "@babel/plugin-transform-class-static-block": "^7.26.0", @@ -1574,21 +1564,21 @@ "@babel/plugin-transform-duplicate-keys": "^7.25.9", "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9", "@babel/plugin-transform-dynamic-import": "^7.25.9", - "@babel/plugin-transform-exponentiation-operator": "^7.25.9", + "@babel/plugin-transform-exponentiation-operator": "^7.26.3", "@babel/plugin-transform-export-namespace-from": "^7.25.9", - "@babel/plugin-transform-for-of": "^7.25.9", + "@babel/plugin-transform-for-of": "^7.26.9", "@babel/plugin-transform-function-name": "^7.25.9", "@babel/plugin-transform-json-strings": "^7.25.9", "@babel/plugin-transform-literals": "^7.25.9", "@babel/plugin-transform-logical-assignment-operators": "^7.25.9", "@babel/plugin-transform-member-expression-literals": "^7.25.9", "@babel/plugin-transform-modules-amd": "^7.25.9", - "@babel/plugin-transform-modules-commonjs": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.26.3", "@babel/plugin-transform-modules-systemjs": "^7.25.9", "@babel/plugin-transform-modules-umd": "^7.25.9", "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9", "@babel/plugin-transform-new-target": "^7.25.9", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.25.9", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.26.6", "@babel/plugin-transform-numeric-separator": "^7.25.9", "@babel/plugin-transform-object-rest-spread": "^7.25.9", "@babel/plugin-transform-object-super": "^7.25.9", @@ -1604,17 +1594,17 @@ "@babel/plugin-transform-shorthand-properties": "^7.25.9", "@babel/plugin-transform-spread": "^7.25.9", "@babel/plugin-transform-sticky-regex": "^7.25.9", - "@babel/plugin-transform-template-literals": "^7.25.9", - "@babel/plugin-transform-typeof-symbol": "^7.25.9", + "@babel/plugin-transform-template-literals": "^7.26.8", + "@babel/plugin-transform-typeof-symbol": "^7.26.7", "@babel/plugin-transform-unicode-escapes": "^7.25.9", "@babel/plugin-transform-unicode-property-regex": "^7.25.9", "@babel/plugin-transform-unicode-regex": "^7.25.9", "@babel/plugin-transform-unicode-sets-regex": "^7.25.9", "@babel/preset-modules": "0.1.6-no-external-plugins", "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-corejs3": "^0.11.0", "babel-plugin-polyfill-regenerator": "^0.6.1", - "core-js-compat": "^3.38.1", + "core-js-compat": "^3.40.0", "semver": "^6.3.1" }, "engines": { @@ -1639,16 +1629,16 @@ } }, "node_modules/@babel/preset-typescript": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.26.0.tgz", - "integrity": "sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.27.0.tgz", + "integrity": "sha512-vxaPFfJtHhgeOVXRKuHpHPAOgymmy8V8I65T1q53R7GCZlefKeCaTyDs3zOPHTTbmquvNlQYC5klEvWsBAtrBQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-plugin-utils": "^7.26.5", "@babel/helper-validator-option": "^7.25.9", "@babel/plugin-syntax-jsx": "^7.25.9", - "@babel/plugin-transform-modules-commonjs": "^7.25.9", - "@babel/plugin-transform-typescript": "^7.25.9" + "@babel/plugin-transform-modules-commonjs": "^7.26.3", + "@babel/plugin-transform-typescript": "^7.27.0" }, "engines": { "node": ">=6.9.0" @@ -1658,9 +1648,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", - "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz", + "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -1669,30 +1659,30 @@ } }, "node_modules/@babel/template": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", - "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", + "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.25.9", - "@babel/parser": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/code-frame": "^7.26.2", + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.5.tgz", - "integrity": "sha512-rkOSPOw+AXbgtwUga3U4u8RpoK9FEFWBNAlTpcnkLFjL5CT+oyHNuUUC/xx6XefEJ16r38r8Bc/lfp6rYuHeJQ==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", + "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", "dev": true, "dependencies": { "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.5", - "@babel/parser": "^7.26.5", - "@babel/template": "^7.25.9", - "@babel/types": "^7.26.5", + "@babel/generator": "^7.27.0", + "@babel/parser": "^7.27.0", + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -1701,9 +1691,9 @@ } }, "node_modules/@babel/types": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.5.tgz", - "integrity": "sha512-L6mZmwFDK6Cjh1nRCLXpa6no13ZIioJDz7mdkzHv399pThrTa/k0nUlNaenOeh2kWu/iaOQYElEpKPUswUa9Vg==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", + "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.25.9", @@ -1742,8 +1732,22 @@ } }, "node_modules/@indigo-labs/iris-sdk": { - "resolved": "../iris-sdk", - "link": true + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@indigo-labs/iris-sdk/-/iris-sdk-1.0.4.tgz", + "integrity": "sha512-Tkg8BB622KHnTGDRqGJ5OmYETOGgPw1ON8+ZC25wJ3uMbY4lTg//KfUa/hycin13y9RtnoM0SFxiMYbdiOryYQ==", + "dependencies": { + "axios": "^1.6.2" + } + }, + "node_modules/@indigo-labs/iris-sdk/node_modules/axios": { + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz", + "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", @@ -1966,9 +1970,9 @@ } }, "node_modules/@jest/reporters/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -2257,9 +2261,9 @@ } }, "node_modules/@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", "dev": true, "dependencies": { "@babel/types": "^7.0.0" @@ -2276,9 +2280,9 @@ } }, "node_modules/@types/babel__traverse": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", - "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz", + "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", "dev": true, "dependencies": { "@babel/types": "^7.20.7" @@ -2338,18 +2342,18 @@ } }, "node_modules/@types/lodash": { - "version": "4.17.14", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.14.tgz", - "integrity": "sha512-jsxagdikDiDBeIRaPYtArcT8my4tN1og7MtMRquFT3XNA6axxyHDRUemqDz/taRDdOUn0GnGHRCuff4q48sW9A==", + "version": "4.17.16", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.16.tgz", + "integrity": "sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==", "dev": true }, "node_modules/@types/node": { - "version": "22.10.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.6.tgz", - "integrity": "sha512-qNiuwC4ZDAUNcY47xgaSuS92cjf8JbSUoaKS77bmLG1rU7MlATVSiw/IlrjtIyyskXBZ8KkNfjK/P5na7rgXbQ==", + "version": "22.14.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.1.tgz", + "integrity": "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==", "dev": true, "dependencies": { - "undici-types": "~6.20.0" + "undici-types": "~6.21.0" } }, "node_modules/@types/stack-utils": { @@ -2374,9 +2378,9 @@ "dev": true }, "node_modules/acorn": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "version": "8.14.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", + "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -2474,13 +2478,13 @@ } }, "node_modules/asn1js": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.5.tgz", - "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.6.tgz", + "integrity": "sha512-UOCGPYbl0tv8+006qks/dTgV9ajs97X2p0FAbyS2iyCRrmLSRolDaHdp+v/CLgnzHc3fVB+CwYiUmei7ndFcgA==", "dependencies": { - "pvtsutils": "^1.3.2", + "pvtsutils": "^1.3.6", "pvutils": "^1.1.3", - "tslib": "^2.4.0" + "tslib": "^2.8.1" }, "engines": { "node": ">=12.0.0" @@ -2492,6 +2496,11 @@ "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", "dev": true }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, "node_modules/axios": { "version": "0.26.1", "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", @@ -2567,13 +2576,13 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.12", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.12.tgz", - "integrity": "sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og==", + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.13.tgz", + "integrity": "sha512-3sX/eOms8kd3q2KZ6DAhKPc0dgm525Gqq5NtWKZ7QYYZEv57OQ54KtblzJzH1lQF/eQxO8KjWGIK9IPUJNus5g==", "dev": true, "dependencies": { "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.3", + "@babel/helper-define-polyfill-provider": "^0.6.4", "semver": "^6.3.1" }, "peerDependencies": { @@ -2581,25 +2590,25 @@ } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.10.6", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", - "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.11.1.tgz", + "integrity": "sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==", "dev": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.2", - "core-js-compat": "^3.38.0" + "@babel/helper-define-polyfill-provider": "^0.6.3", + "core-js-compat": "^3.40.0" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.3.tgz", - "integrity": "sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.4.tgz", + "integrity": "sha512-7gD3pRadPrbjhjLyxebmx/WrFYcuSjZ0XbdUujQMZ/fcE9oeewk2U/7PCvez84UeuK3oSjmPZ0Ch0dlupQvGzw==", "dev": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.3" + "@babel/helper-define-polyfill-provider": "^0.6.4" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -2769,6 +2778,18 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -2788,9 +2809,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001692", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001692.tgz", - "integrity": "sha512-A95VKan0kdtrsnMubMKxEKUKImOPSuCpYgxSQBo036P5YYgVIcOYJEgt/txJWqObiRQeISNCfef9nvlQ0vbV7A==", + "version": "1.0.30001713", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001713.tgz", + "integrity": "sha512-wCIWIg+A4Xr7NfhTuHdX+/FKh3+Op3LBbSp2N5Pfx6T/LhdQy3GTyoTg48BReaW/MyMNZAkTadsBtai3ldWK0Q==", "dev": true, "funding": [ { @@ -2872,9 +2893,9 @@ } }, "node_modules/cjs-module-lexer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", - "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", "dev": true }, "node_modules/cliui": { @@ -2925,6 +2946,17 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/commander": { "version": "9.5.0", "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", @@ -2947,12 +2979,12 @@ "dev": true }, "node_modules/core-js-compat": { - "version": "3.40.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.40.0.tgz", - "integrity": "sha512-0XEDpr5y5mijvw8Lbc6E5AkjrHfp7eEoPlu36SWeAbcL8fn1G1ANe8DBlo2XoNN89oVpxWwOjYIPVzR4ZvsKCQ==", + "version": "3.41.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.41.0.tgz", + "integrity": "sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A==", "dev": true, "dependencies": { - "browserslist": "^4.24.3" + "browserslist": "^4.24.4" }, "funding": { "type": "opencollective", @@ -3053,6 +3085,14 @@ "node": ">=0.10.0" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -3092,6 +3132,19 @@ "node": ">=8" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/ejs": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", @@ -3108,9 +3161,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.82", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.82.tgz", - "integrity": "sha512-Zq16uk1hfQhyGx5GpwPAYDwddJuSGhtRhgOA2mCxANYaDT79nAeGnaXogMGng4KqLaJUVnOnuL0+TDop9nLOiA==", + "version": "1.5.137", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.137.tgz", + "integrity": "sha512-/QSJaU2JyIuTbbABAo/crOs+SuAZLS+fVVS10PVrIT9hrRkmZl8Hb0xPSkKRUUWHQtYzXHpQUW3Dy5hwMzGZkA==", "dev": true }, "node_modules/emittery": { @@ -3140,6 +3193,47 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -3251,9 +3345,9 @@ "dev": true }, "node_modules/fastq": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz", - "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -3364,6 +3458,20 @@ } } }, + "node_modules/form-data": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", + "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/formdata-polyfill": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", @@ -3399,7 +3507,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -3422,6 +3529,29 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", @@ -3431,6 +3561,18 @@ "node": ">=8.0.0" } }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", @@ -3443,6 +3585,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/get-tsconfig": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz", + "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -3505,6 +3659,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -3520,11 +3685,35 @@ "node": ">=8" } }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, "dependencies": { "function-bind": "^1.1.2" }, @@ -4261,9 +4450,9 @@ } }, "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -4512,9 +4701,9 @@ } }, "node_modules/make-dir/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -4538,6 +4727,14 @@ "tmpl": "1.0.5" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -4566,6 +4763,25 @@ "node": ">=8.6" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", @@ -4839,9 +5055,9 @@ } }, "node_modules/pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", "dev": true, "engines": { "node": ">= 6" @@ -4925,6 +5141,11 @@ "node": ">= 6" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/pure-rand": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", @@ -5133,6 +5354,15 @@ "node": ">=8" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/resolve.exports": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", @@ -5143,9 +5373,9 @@ } }, "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "dev": true, "engines": { "iojs": ">=1.0.0", @@ -5389,9 +5619,9 @@ } }, "node_modules/ts-jest": { - "version": "29.2.5", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.5.tgz", - "integrity": "sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA==", + "version": "29.3.2", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.3.2.tgz", + "integrity": "sha512-bJJkrWc6PjFVz5g2DGCNUo8z7oFEYaz1xP1NpeDU7KNLMWPpEyV8Chbpkn8xjzgRDpQhnGMyvyldoL7h8JXyug==", "dev": true, "dependencies": { "bs-logger": "^0.2.6", @@ -5401,7 +5631,8 @@ "json5": "^2.2.3", "lodash.memoize": "^4.1.2", "make-error": "^1.3.6", - "semver": "^7.6.3", + "semver": "^7.7.1", + "type-fest": "^4.39.1", "yargs-parser": "^21.1.1" }, "bin": { @@ -5437,9 +5668,9 @@ } }, "node_modules/ts-jest/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -5448,6 +5679,18 @@ "node": ">=10" } }, + "node_modules/ts-jest/node_modules/type-fest": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.40.0.tgz", + "integrity": "sha512-ABHZ2/tS2JkvH1PEjxFDTUWC8dB5OsIGZP4IFLhR293GqT5Y5qB1WwL2kMPYhQW9DVgVD8Hd7I8gjwPIf5GFkw==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", @@ -5492,13 +5735,14 @@ } }, "node_modules/tsc-alias": { - "version": "1.8.10", - "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.8.10.tgz", - "integrity": "sha512-Ibv4KAWfFkFdKJxnWfVtdOmB0Zi1RJVxcbPGiCDsFpCQSsmpWyuzHG3rQyI5YkobWwxFPEyQfu1hdo4qLG2zPw==", + "version": "1.8.15", + "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.8.15.tgz", + "integrity": "sha512-yKLVx8ddUurRwhVcS6JFF2ZjksOX2ZWDRIdgt+PQhJBDegIdAdilptiHsuAbx9UFxa16GFrxeKQ2kTcGvR6fkQ==", "dev": true, "dependencies": { "chokidar": "^3.5.3", "commander": "^9.0.0", + "get-tsconfig": "^4.10.0", "globby": "^11.0.4", "mylas": "^2.1.9", "normalize-path": "^3.0.0", @@ -5506,6 +5750,9 @@ }, "bin": { "tsc-alias": "dist/bin/index.js" + }, + "engines": { + "node": ">=16.20.2" } }, "node_modules/tslib": { @@ -5535,9 +5782,9 @@ } }, "node_modules/typescript": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", - "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -5548,9 +5795,9 @@ } }, "node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true }, "node_modules/unicode-canonical-property-names-ecmascript": { @@ -5594,9 +5841,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", - "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "dev": true, "funding": [ { @@ -5724,9 +5971,9 @@ } }, "node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", "engines": { "node": ">=10.0.0" }, From bccabe9a24299eff646ee7294bab72d2ec8d6cd6 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 8 May 2025 21:39:14 -0400 Subject: [PATCH 4/4] Add exports --- src/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/index.ts b/src/index.ts index 2c6ecb9..80e3f5a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,6 +13,8 @@ export * from './definition-builder'; export * from './providers/wallet/base-wallet-provider'; export * from './providers/wallet/mock-wallet-provider'; export * from './providers/wallet/lucid-provider'; +export * from './providers/data/blockfrost-provider'; +export * from './providers/data/kupo-provider'; /** * Request exports.