mirror of
https://github.com/alexgo-io/alex-sdk.git
synced 2026-01-12 14:25:02 +08:00
Tests/sdk features stage 2 (#11)
* tests: enhance tests for existing functions * tests: add test cases for existing functions * tests: add test cases for three new functions * tests: Introduce mock for getFeeRate function * tests: implement workaround for Jest BigInt assertion issue * tests: wip test cases getRoute, getAmountTo, runSwap * tests: mocked functions runSwap, getLatestPrices * temp commit * tests: mocked functions getBalances, fetchSwappableCurrency * tests: add additional tests for error scenarios * tests: add more coverage to runSwap SDK method * temp commit * temp commit * sync merge * code linted + documentation update * tests: SDK getWayPoints method * tests: add lint fix command * tests: add getFeeRate with custom route * test: add external error tests * fix: minor changes * conflicts resolved --------- Co-authored-by: ignacio.pena@coinfabrik.com <ignacio.pena@coinfabrik.com> Co-authored-by: simsbluebox <simsbluebox@gmail.com> Co-authored-by: david weil <david.weil@endlesstruction.com.ar>
This commit is contained in:
111
README.md
111
README.md
@@ -10,101 +10,28 @@ You can install Alex-SDK using npm:
|
|||||||
npm install alex-sdk
|
npm install alex-sdk
|
||||||
```
|
```
|
||||||
|
|
||||||
## Methods
|
## Functions
|
||||||
|
|
||||||
### `fetchSwappableCurrency()`
|
The AlexSDK class includes the following functions:
|
||||||
|
|
||||||
Fetches the list of currencies that can be swapped on the DEX.
|
```typescript
|
||||||
|
export declare class AlexSDK {
|
||||||
|
fetchSwappableCurrency(): Promise<TokenInfo[]>;
|
||||||
|
getAllPossibleRoutes(from: Currency, to: Currency): Promise<AMMRoute[]>;
|
||||||
|
getAmountTo(from: Currency, fromAmount: bigint, to: Currency): Promise<bigint>;
|
||||||
|
getBalances(stxAddress: string): Promise<Partial<{ [currency in Currency]: bigint }>>;
|
||||||
|
getFeeRate(from: Currency, to: Currency): Promise<bigint>;
|
||||||
|
getLatestPrices(): Promise<Partial<{ [currency in Currency]: number }>>;
|
||||||
|
getRoute(from: Currency, to: Currency): Promise<AMMRoute>;
|
||||||
|
getRouter(from: Currency, to: Currency): Promise<Currency[]>; // deprecated
|
||||||
|
getWayPoints(route: AMMRoute): Promise<TokenInfo[]>;
|
||||||
|
runSwap(stxAddress: string, currencyX: Currency,
|
||||||
|
currencyY: Currency, fromAmount: bigint,
|
||||||
|
minDy: bigint, customRoute: AMMRoute): Promise<TxToBroadCast>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
- **Returns**: `Promise<TokenInfo[]>` - A promise that resolves to an array of TokenInfo objects, representing the swappable currencies.
|
(detailed list [here](./documentation.md)).
|
||||||
|
|
||||||
### `getAllPossibleRoutes(from: Currency, to: Currency)`
|
|
||||||
|
|
||||||
Retrieves all possible routes for swapping from one currency to another.
|
|
||||||
|
|
||||||
- **Parameters**:
|
|
||||||
|
|
||||||
- `from: Currency` - The currency to swap from.
|
|
||||||
- `to: Currency` - The currency to swap to.
|
|
||||||
|
|
||||||
- **Returns**: `Promise<AMMRoute[]>` - A promise that resolves to an array of AMMRoute objects, representing all possible routes for the swap.
|
|
||||||
|
|
||||||
### `getRoute(from: Currency, to: Currency)`
|
|
||||||
|
|
||||||
Retrieves the best route for swapping from one currency to another.
|
|
||||||
|
|
||||||
- **Parameters**:
|
|
||||||
|
|
||||||
- `from: Currency` - The currency to swap from.
|
|
||||||
- `to: Currency` - The currency to swap to.
|
|
||||||
|
|
||||||
- **Returns**: `Promise<AMMRoute>` - A promise that resolves to an AMMRoute object, representing the best route for the swap.
|
|
||||||
|
|
||||||
### `getWayPoints(route: AMMRoute)`
|
|
||||||
|
|
||||||
Displays the detailed route information.
|
|
||||||
|
|
||||||
- **Parameters**:
|
|
||||||
|
|
||||||
- `route: AMMRoute` - The route to display.
|
|
||||||
|
|
||||||
- **Returns**: `Promise<TokenInfo[]>` - A promise that resolves to an array of TokenInfo objects, representing the detailed information of the route.
|
|
||||||
|
|
||||||
### `getFeeRate(from: Currency, to: Currency, customRoute?: AMMRoute)`
|
|
||||||
|
|
||||||
Calculates the fee rate for a swap between two currencies.
|
|
||||||
|
|
||||||
- **Parameters**:
|
|
||||||
|
|
||||||
- `from: Currency` - The currency to swap from.
|
|
||||||
- `to: Currency` - The currency to swap to.
|
|
||||||
- `customRoute?: AMMRoute` - An optional custom route for the swap.
|
|
||||||
|
|
||||||
- **Returns**: `Promise<bigint>` - A promise that resolves to a bigint representing the fee rate for the swap.
|
|
||||||
|
|
||||||
### `getAmountTo(from: Currency, fromAmount: bigint, to: Currency, customRoute?: AMMRoute)`
|
|
||||||
|
|
||||||
Calculates the amount of the destination currency that will be received for a given amount of the source currency.
|
|
||||||
|
|
||||||
- **Parameters**:
|
|
||||||
|
|
||||||
- `from: Currency` - The currency to swap from.
|
|
||||||
- `fromAmount: bigint` - The amount of the source currency to swap.
|
|
||||||
- `to: Currency` - The currency to swap to.
|
|
||||||
- `customRoute?: AMMRoute` - An optional custom route for the swap.
|
|
||||||
|
|
||||||
- **Returns**: `Promise<bigint>` - A promise that resolves to a bigint representing the amount of the destination currency that will be received.
|
|
||||||
|
|
||||||
### `runSwap(stxAddress: string, currencyX: Currency, currencyY: Currency, fromAmount: bigint, minDy: bigint, customRoute?: AMMRoute)`
|
|
||||||
|
|
||||||
Executes a swap transaction between two currencies.
|
|
||||||
|
|
||||||
- **Parameters**:
|
|
||||||
|
|
||||||
- `stxAddress: string` - The Stacks (STX) address to execute the swap from.
|
|
||||||
- `currencyX: Currency` - The currency to swap from.
|
|
||||||
- `currencyY: Currency` - The currency to swap to.
|
|
||||||
- `fromAmount: bigint` - The amount of the source currency to swap.
|
|
||||||
- `minDy: bigint` - The minimum amount of the destination currency to receive.
|
|
||||||
- `customRoute?: AMMRoute` - An optional custom route for the swap.
|
|
||||||
|
|
||||||
- **Returns**: `Promise<TxToBroadCast>` - A promise that resolves to a TxToBroadCast object, representing the transaction to be broadcasted.
|
|
||||||
|
|
||||||
### `getLatestPrices()`
|
|
||||||
|
|
||||||
Retrieves the latest prices for all supported currencies.
|
|
||||||
|
|
||||||
- **Returns**: `Promise<Partial<{ [currency in Currency]: number }>>` - A promise that resolves to an object containing the latest prices for each currency.
|
|
||||||
|
|
||||||
### `getBalances(stxAddress: string)`
|
|
||||||
|
|
||||||
Retrieves the balances of all supported currencies for a given Stacks (STX) address.
|
|
||||||
|
|
||||||
- **Parameters**:
|
|
||||||
|
|
||||||
- `stxAddress: string` - The Stacks (STX) address to retrieve the balances for.
|
|
||||||
|
|
||||||
- **Returns**: `Promise<Partial<{ [currency in Currency]: bigint }>>` - A promise that resolves to an object containing the balances of each currency for the given address.
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
|||||||
@@ -6,15 +6,18 @@ The AlexSDK class includes the following functions:
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
export declare class AlexSDK {
|
export declare class AlexSDK {
|
||||||
fetchSwappableCurrency(): Promise<TokenInfo[]>;
|
fetchSwappableCurrency(): Promise<TokenInfo[]>;
|
||||||
getAmountTo(from: Currency, fromAmount: bigint, to: Currency): Promise<bigint>;
|
getAllPossibleRoutes(from: Currency, to: Currency): Promise<AMMRoute[]>;
|
||||||
getBalances(stxAddress: string): Promise<Partial<{ [currency in Currency]: bigint }>>;
|
getAmountTo(from: Currency, fromAmount: bigint, to: Currency): Promise<bigint>;
|
||||||
getFeeRate(from: Currency, to: Currency): Promise<bigint>;
|
getBalances(stxAddress: string): Promise<Partial<{ [currency in Currency]: bigint }>>;
|
||||||
getLatestPrices(): Promise<Partial<{ [currency in Currency]: number }>>;
|
getFeeRate(from: Currency, to: Currency): Promise<bigint>;
|
||||||
getRoute(from: Currency, to: Currency): Promise<Currency[]>;
|
getLatestPrices(): Promise<Partial<{ [currency in Currency]: number }>>;
|
||||||
runSwap(stxAddress: string, currencyX: Currency,
|
getRoute(from: Currency, to: Currency): Promise<AMMRoute>;
|
||||||
currencyY: Currency, fromAmount: bigint,
|
getRouter(from: Currency, to: Currency): Promise<Currency[]>; // deprecated
|
||||||
minDy: bigint, customRoute: Currency[]): Promise<TxToBroadCast>;
|
getWayPoints(route: AMMRoute): Promise<TokenInfo[]>;
|
||||||
|
runSwap(stxAddress: string, currencyX: Currency,
|
||||||
|
currencyY: Currency, fromAmount: bigint,
|
||||||
|
minDy: bigint, customRoute: AMMRoute): Promise<TxToBroadCast>;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
testEnvironment: 'node',
|
testEnvironment: 'node',
|
||||||
|
verbose: true,
|
||||||
|
maxWorkers: 1
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,7 +15,9 @@
|
|||||||
"build": "dts build",
|
"build": "dts build",
|
||||||
"prepare": "pnpm run build",
|
"prepare": "pnpm run build",
|
||||||
"test": "dts test",
|
"test": "dts test",
|
||||||
|
"test:coverage": "dts test --coverage",
|
||||||
"lint": "dts lint",
|
"lint": "dts lint",
|
||||||
|
"lint-fix": "dts lint --fix",
|
||||||
"size": "size-limit",
|
"size": "size-limit",
|
||||||
"gen:contract": "rm -rf src/generated/smartContract/* && tsx ./scripts/gen-contract.ts && prettier --write 'src/generated/smartContract'",
|
"gen:contract": "rm -rf src/generated/smartContract/* && tsx ./scripts/gen-contract.ts && prettier --write 'src/generated/smartContract'",
|
||||||
"analyze": "size-limit --why",
|
"analyze": "size-limit --why",
|
||||||
@@ -62,6 +64,7 @@
|
|||||||
"ajv": "^8.16.0",
|
"ajv": "^8.16.0",
|
||||||
"dts-cli": "^2.0.5",
|
"dts-cli": "^2.0.5",
|
||||||
"esm": "^3.2.25",
|
"esm": "^3.2.25",
|
||||||
|
"fetch-mock": "^10.0.7",
|
||||||
"husky": "^8.0.3",
|
"husky": "^8.0.3",
|
||||||
"prettier": "^2.8.4",
|
"prettier": "^2.8.4",
|
||||||
"size-limit": "^8.2.4",
|
"size-limit": "^8.2.4",
|
||||||
|
|||||||
40
test/alexSDK.mock-exceptions.test.ts
Normal file
40
test/alexSDK.mock-exceptions.test.ts
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import { AlexSDK, Currency } from '../src';
|
||||||
|
import * as ammRouteResolver from '../src/utils/ammRouteResolver';
|
||||||
|
import { configs } from '../src/config';
|
||||||
|
|
||||||
|
const sdk = new AlexSDK();
|
||||||
|
|
||||||
|
const tokenAlex = 'age000-governance-token' as Currency;
|
||||||
|
const tokenWUSDA = 'token-wusda' as Currency;
|
||||||
|
|
||||||
|
const dummyRoute = ['TokenA', 'TokenB', 'TokenC', 'TokenD', 'TokenE', 'TokenF'];
|
||||||
|
jest.mock('../src/utils/ammRouteResolver', () => ({
|
||||||
|
resolveAmmRoute: jest.fn(async () => dummyRoute),
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('AlexSDK - mock exceptions', () => {
|
||||||
|
it('Attempt to Get Fee Rate with more than 4 pools in route', async () => {
|
||||||
|
expect(jest.isMockFunction(ammRouteResolver.resolveAmmRoute)).toBeTruthy();
|
||||||
|
await expect(sdk.getFeeRate(tokenAlex, Currency.STX)).rejects.toThrow(
|
||||||
|
'Too many AMM pools in route'
|
||||||
|
);
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
|
it('Attempt to getAmountTo with more than 4 pools in route', async () => {
|
||||||
|
await expect(
|
||||||
|
sdk.getAmountTo(Currency.STX, BigInt(2) * BigInt(1e8), tokenWUSDA)
|
||||||
|
).rejects.toThrow('Too many AMM pools in route');
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
|
it('Attempt to run swap with more than 4 pools in route', async () => {
|
||||||
|
await expect(
|
||||||
|
sdk.runSwap(
|
||||||
|
configs.CONTRACT_DEPLOYER,
|
||||||
|
tokenAlex,
|
||||||
|
tokenWUSDA,
|
||||||
|
BigInt(2) * BigInt(1e8),
|
||||||
|
BigInt(0)
|
||||||
|
)
|
||||||
|
).rejects.toThrow('Too many AMM pools in route');
|
||||||
|
}, 10000);
|
||||||
|
});
|
||||||
146
test/alexSDK.mock-externals.test.ts
Normal file
146
test/alexSDK.mock-externals.test.ts
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
import { AlexSDK, Currency, TokenInfo } from '../src';
|
||||||
|
import fetchMock from 'fetch-mock';
|
||||||
|
import { configs } from '../src/config';
|
||||||
|
import { fetchBalanceForAccount, getPrices } from '../src/utils/fetchData';
|
||||||
|
import { transferFactory } from '../src/utils/postConditions';
|
||||||
|
|
||||||
|
const sdk = new AlexSDK();
|
||||||
|
|
||||||
|
const tokenAlex = 'age000-governance-token' as Currency;
|
||||||
|
const tokenWUSDA = 'token-wusda' as Currency;
|
||||||
|
|
||||||
|
const tokenMappings: TokenInfo[] = [
|
||||||
|
{
|
||||||
|
id: 'token-x' as Currency,
|
||||||
|
name: 'Token x',
|
||||||
|
icon: 'icon-x',
|
||||||
|
wrapToken: 'wrap-token-x',
|
||||||
|
wrapTokenDecimals: 8,
|
||||||
|
underlyingToken: 'underlying-token-x',
|
||||||
|
underlyingTokenDecimals: 8,
|
||||||
|
isRebaseToken: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const stxAddress = 'SM2MARAVW6BEJCD13YV2RHGYHQWT7TDDNMNRB1MVT';
|
||||||
|
|
||||||
|
describe('AlexSDK - mock externals', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
fetchMock.get(configs.SDK_API_HOST, 500);
|
||||||
|
});
|
||||||
|
afterEach(() => {
|
||||||
|
fetchMock.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Attempt to Get Latest Prices with incorrect Alex SDK Data', async () => {
|
||||||
|
await expect(sdk.getLatestPrices()).rejects.toThrow(
|
||||||
|
'Failed to fetch token mappings'
|
||||||
|
);
|
||||||
|
}, 10000);
|
||||||
|
it('Attempt to Get Fee with incorrect Alex SDK Data', async () => {
|
||||||
|
await expect(sdk.getFeeRate(tokenAlex, Currency.STX)).rejects.toThrow(
|
||||||
|
'Failed to fetch token mappings'
|
||||||
|
);
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
|
it('Attempt to Get Router with incorrect Alex SDK Data', async () => {
|
||||||
|
await expect(sdk.getRouter(tokenAlex, Currency.STX)).rejects.toThrow(
|
||||||
|
'Failed to fetch token mappings'
|
||||||
|
);
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
|
it('Attempt to Get Amount with incorrect Alex SDK Data', async () => {
|
||||||
|
await expect(
|
||||||
|
sdk.getAmountTo(Currency.STX, BigInt(2) * BigInt(1e8), tokenWUSDA)
|
||||||
|
).rejects.toThrow('Failed to fetch token mappings');
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
|
it('Attempt to Run Swap with incorrect Alex SDK Data', async () => {
|
||||||
|
await expect(
|
||||||
|
sdk.runSwap(
|
||||||
|
configs.CONTRACT_DEPLOYER,
|
||||||
|
tokenAlex,
|
||||||
|
tokenWUSDA,
|
||||||
|
BigInt(2) * BigInt(1e8),
|
||||||
|
BigInt(0)
|
||||||
|
)
|
||||||
|
).rejects.toThrow('Failed to fetch token mappings');
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
|
it('Attempt to Get Latest Prices with incorrect Alex SDK Data', async () => {
|
||||||
|
await expect(sdk.getLatestPrices()).rejects.toThrow(
|
||||||
|
'Failed to fetch token mappings'
|
||||||
|
);
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
|
it('Attempt to Get Balances with incorrect Alex SDK Data', async () => {
|
||||||
|
const stxAddress = 'SM2MARAVW6BEJCD13YV2RHGYHQWT7TDDNMNRB1MVT';
|
||||||
|
await expect(sdk.getBalances(stxAddress)).rejects.toThrow(
|
||||||
|
'Failed to fetch token mappings'
|
||||||
|
);
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
|
it('Attempt to Fetch Swappable Currency with incorrect Alex SDK Data', async () => {
|
||||||
|
await expect(sdk.fetchSwappableCurrency()).rejects.toThrow(
|
||||||
|
'Failed to fetch token mappings'
|
||||||
|
);
|
||||||
|
}, 10000);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('AlexSDK - mock externals - BACKEND_API_HOST', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
fetchMock.get(`${configs.BACKEND_API_HOST}/v2/public/token-prices`, {
|
||||||
|
status: 500,
|
||||||
|
body: 'Internal Server Error',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
fetchMock.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Attempt to get token prices with incorrect data', async () => {
|
||||||
|
await expect(getPrices(tokenMappings)).rejects.toThrow(
|
||||||
|
'Failed to fetch token mappings'
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
fetchMock.calls(`${configs.BACKEND_API_HOST}/v2/public/token-prices`)
|
||||||
|
.length
|
||||||
|
).toBe(1);
|
||||||
|
}, 10000);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Transfer Factory', () => {
|
||||||
|
it('Throws error in Transfer Factory', () => {
|
||||||
|
const transfer = transferFactory(tokenMappings);
|
||||||
|
expect(() => transfer(stxAddress, tokenAlex, BigInt(1000))).toThrow(
|
||||||
|
'Token mapping not found'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('AlexSDK - mock externals - STACKS_API_HOST', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
fetchMock.get(
|
||||||
|
`${configs.STACKS_API_HOST}/extended/v1/address/${stxAddress}/balances`,
|
||||||
|
{
|
||||||
|
status: 500,
|
||||||
|
body: 'Internal Server Error',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
fetchMock.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Attempt to Get Balances with incorrect data', async () => {
|
||||||
|
await expect(
|
||||||
|
fetchBalanceForAccount(stxAddress, tokenMappings)
|
||||||
|
).rejects.toThrow(
|
||||||
|
new SyntaxError(
|
||||||
|
'Unexpected token \'I\', "Internal S"... is not valid JSON'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}, 10000);
|
||||||
|
});
|
||||||
160
test/alexSDK.mock-helpers.test.ts
Normal file
160
test/alexSDK.mock-helpers.test.ts
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
import { AlexSDK, Currency } from '../src';
|
||||||
|
import * as FeeHelper from '../src/helpers/FeeHelper';
|
||||||
|
import * as RouteHelper from '../src/helpers/RouteHelper';
|
||||||
|
import * as RateHelper from '../src/helpers/RateHelper';
|
||||||
|
import * as SwapHelper from '../src/helpers/SwapHelper';
|
||||||
|
import * as fetchData from '../src/utils/fetchData';
|
||||||
|
import * as ammRouteResolver from '../src/utils/ammRouteResolver';
|
||||||
|
import { configs } from '../src/config';
|
||||||
|
// @ts-ignore
|
||||||
|
import {
|
||||||
|
dummyAlexSDKData,
|
||||||
|
dummyAmmRoute,
|
||||||
|
dummyBalances,
|
||||||
|
dummyCurrencies,
|
||||||
|
dummyFee,
|
||||||
|
dummyPrices,
|
||||||
|
dummyRate,
|
||||||
|
dummyTx,
|
||||||
|
parsedDummyPrices,
|
||||||
|
dummyTokenA,
|
||||||
|
dummyTokenB,
|
||||||
|
dummyFactorA,
|
||||||
|
dummyFactorB,
|
||||||
|
dummyTokenC,
|
||||||
|
} from './mock-data/alexSDKMockResponses';
|
||||||
|
import { cvToValue, FungibleConditionCode } from '@stacks/transactions';
|
||||||
|
|
||||||
|
const sdk = new AlexSDK();
|
||||||
|
|
||||||
|
const tokenAlex = 'age000-governance-token' as Currency;
|
||||||
|
const tokenWUSDA = 'token-wusda' as Currency;
|
||||||
|
|
||||||
|
// Mocked helpers and utilities for testing SDK functions
|
||||||
|
jest.mock('../src/helpers/FeeHelper', () => ({
|
||||||
|
getLiquidityProviderFee: jest.fn(async () => dummyFee),
|
||||||
|
}));
|
||||||
|
jest.mock('../src/helpers/RouteHelper', () => ({
|
||||||
|
getAllPossibleRoute: jest.fn(async () => [dummyAmmRoute, dummyAmmRoute]),
|
||||||
|
}));
|
||||||
|
jest.mock('../src/helpers/RateHelper', () => ({
|
||||||
|
getYAmountFromXAmount: jest.fn(async () => dummyRate),
|
||||||
|
}));
|
||||||
|
jest.mock('../src/helpers/SwapHelper', () => {
|
||||||
|
const originalModule = jest.requireActual('../src/helpers/SwapHelper');
|
||||||
|
return {
|
||||||
|
runSpot: jest.fn(async (deployer, ...args) => {
|
||||||
|
if (deployer !== configs.CONTRACT_DEPLOYER) {
|
||||||
|
return dummyTx;
|
||||||
|
}
|
||||||
|
return await originalModule.runSpot(deployer, ...args);
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
jest.mock('../src/utils/fetchData', () => {
|
||||||
|
const originalModule = jest.requireActual('../src/utils/fetchData');
|
||||||
|
return {
|
||||||
|
__esModule: true,
|
||||||
|
...originalModule,
|
||||||
|
getPrices: jest.fn(async () => dummyPrices),
|
||||||
|
fetchBalanceForAccount: jest.fn(async () => dummyBalances),
|
||||||
|
getAlexSDKData: jest.fn(async () => dummyAlexSDKData),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
jest.mock('../src/utils/ammRouteResolver', () => ({
|
||||||
|
resolveAmmRoute: jest.fn(() => dummyAmmRoute),
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('AlexSDK - mock helpers', () => {
|
||||||
|
it('Verify response value of getFeeRate function', async () => {
|
||||||
|
expect(jest.isMockFunction(FeeHelper.getLiquidityProviderFee)).toBeTruthy();
|
||||||
|
const result = await sdk.getFeeRate(tokenAlex, Currency.STX);
|
||||||
|
expect(result).toStrictEqual(dummyFee);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Verify response value of getAllPossibleRoute function', async () => {
|
||||||
|
expect(jest.isMockFunction(RouteHelper.getAllPossibleRoute)).toBeTruthy();
|
||||||
|
const result = await sdk.getRoute(Currency.STX, tokenWUSDA);
|
||||||
|
expect(result).toStrictEqual(dummyAmmRoute);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Verify response value of getRouter[deprecated] function', async () => {
|
||||||
|
expect(jest.isMockFunction(RouteHelper.getAllPossibleRoute)).toBeTruthy();
|
||||||
|
const result = await sdk.getRouter(Currency.STX, dummyTokenB);
|
||||||
|
expect(result).toStrictEqual([Currency.STX, dummyTokenC, dummyTokenB]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Verify response value of getAmountTo function', async () => {
|
||||||
|
expect(jest.isMockFunction(RateHelper.getYAmountFromXAmount)).toBeTruthy();
|
||||||
|
const result = await sdk.getAmountTo(
|
||||||
|
Currency.STX,
|
||||||
|
BigInt(2) * BigInt(1e8),
|
||||||
|
tokenWUSDA
|
||||||
|
);
|
||||||
|
expect(result).toStrictEqual(dummyRate);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Verify response value of runSwap function', async () => {
|
||||||
|
expect(jest.isMockFunction(SwapHelper.runSpot)).toBeTruthy();
|
||||||
|
const result = await sdk.runSwap(
|
||||||
|
'SP111111111111111111111111111111111111111',
|
||||||
|
tokenAlex,
|
||||||
|
tokenWUSDA,
|
||||||
|
BigInt(1),
|
||||||
|
BigInt(0)
|
||||||
|
);
|
||||||
|
expect(result).toStrictEqual(dummyTx);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Verify response value of runSwap function (tx construct + rebase)', async () => {
|
||||||
|
expect(jest.isMockFunction(SwapHelper.runSpot)).toBeTruthy();
|
||||||
|
expect(jest.isMockFunction(ammRouteResolver.resolveAmmRoute)).toBeTruthy();
|
||||||
|
const amount = BigInt(2) * BigInt(1e8);
|
||||||
|
const result = await sdk.runSwap(
|
||||||
|
configs.CONTRACT_DEPLOYER,
|
||||||
|
dummyTokenA,
|
||||||
|
dummyTokenB,
|
||||||
|
amount,
|
||||||
|
BigInt(0)
|
||||||
|
);
|
||||||
|
expect(cvToValue(result.functionArgs[3])).toStrictEqual(dummyFactorA);
|
||||||
|
expect(cvToValue(result.functionArgs[4])).toStrictEqual(dummyFactorB);
|
||||||
|
expect(cvToValue(result.functionArgs[5])).toStrictEqual(amount);
|
||||||
|
expect(result.postConditions[0].conditionCode).toStrictEqual(
|
||||||
|
FungibleConditionCode.GreaterEqual
|
||||||
|
);
|
||||||
|
expect(result.postConditions[0].amount).toStrictEqual(BigInt(0));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Verify response value of getLatestPrices function', async () => {
|
||||||
|
expect(jest.isMockFunction(fetchData.getPrices)).toBeTruthy();
|
||||||
|
const result = await sdk.getLatestPrices();
|
||||||
|
expect(result).toStrictEqual(parsedDummyPrices);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Verify response value of getBalances function', async () => {
|
||||||
|
expect(jest.isMockFunction(fetchData.fetchBalanceForAccount)).toBeTruthy();
|
||||||
|
const stxAddress = 'SM2MARAVW6BEJCD13YV2RHGYHQWT7TDDNMNRB1MVT';
|
||||||
|
const result = await sdk.getBalances(stxAddress);
|
||||||
|
expect(result).toStrictEqual(dummyBalances);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Verify response value of fetchSwappableCurrency function', async () => {
|
||||||
|
expect(jest.isMockFunction(fetchData.getAlexSDKData)).toBeTruthy();
|
||||||
|
const result = await sdk.fetchSwappableCurrency();
|
||||||
|
expect(result).toStrictEqual(dummyCurrencies);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Verify response value of getWayPoints function', async () => {
|
||||||
|
expect(jest.isMockFunction(fetchData.getAlexSDKData)).toBeTruthy();
|
||||||
|
expect(jest.isMockFunction(RouteHelper.getAllPossibleRoute)).toBeTruthy();
|
||||||
|
const mockedRoute = await sdk.getRoute(dummyTokenA, dummyTokenB);
|
||||||
|
const result = await sdk.getWayPoints(mockedRoute);
|
||||||
|
expect(result[0].id).toBe(dummyTokenA);
|
||||||
|
expect(result[1].id).toBe(dummyTokenC);
|
||||||
|
expect(result[2].id).toBe(dummyTokenB);
|
||||||
|
expect(result[0].isRebaseToken).toBe(true);
|
||||||
|
expect(result[1].isRebaseToken).toBe(false);
|
||||||
|
expect(result[2].isRebaseToken).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -40,19 +40,29 @@ const tokenDiko = 'token-wdiko' as Currency;
|
|||||||
const wrongTokenAlex = '' as Currency;
|
const wrongTokenAlex = '' as Currency;
|
||||||
|
|
||||||
const sdk = new AlexSDK();
|
const sdk = new AlexSDK();
|
||||||
|
const CLARITY_MAX_UNSIGNED_INT = BigInt(
|
||||||
|
'340282366920938463463374607431768211455'
|
||||||
|
);
|
||||||
|
|
||||||
describe('AlexSDK', () => {
|
describe('AlexSDK', () => {
|
||||||
it('Verify response of getFeeRate function', async () => {
|
it('Verify response of getFeeRate function', async () => {
|
||||||
const result = await sdk.getFeeRate(tokenAlex, Currency.STX);
|
const result = await sdk.getFeeRate(tokenAlex, Currency.STX);
|
||||||
expect(typeof result).toBe('bigint');
|
expect(typeof result).toBe('bigint');
|
||||||
expect(result >= BigInt(0)).toBeTruthy();
|
expect(result >= BigInt(0)).toBeTruthy();
|
||||||
});
|
}, 10000);
|
||||||
|
|
||||||
|
it('Verify response of getFeeRate function (custom route)', async () => {
|
||||||
|
const customRoute = await sdk.getRoute(tokenAlex, Currency.STX);
|
||||||
|
const result = await sdk.getFeeRate(tokenAlex, Currency.STX, customRoute);
|
||||||
|
expect(typeof result).toBe('bigint');
|
||||||
|
expect(result >= BigInt(0)).toBeTruthy();
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
it('Attempt to Get Fee Rate with wrong tokens', async () => {
|
it('Attempt to Get Fee Rate with wrong tokens', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
sdk.getFeeRate(wrongTokenAlex, wrongTokenAlex)
|
sdk.getFeeRate(wrongTokenAlex, wrongTokenAlex)
|
||||||
).rejects.toThrow('No AMM pools in route');
|
).rejects.toThrow('No AMM pools in route');
|
||||||
});
|
}, 10000);
|
||||||
|
|
||||||
it('Verify response of getRoute function', async () => {
|
it('Verify response of getRoute function', async () => {
|
||||||
const result = await sdk.getRoute(Currency.STX, tokenDiko);
|
const result = await sdk.getRoute(Currency.STX, tokenDiko);
|
||||||
@@ -65,13 +75,13 @@ describe('AlexSDK', () => {
|
|||||||
result.forEach((routeSegment) => {
|
result.forEach((routeSegment) => {
|
||||||
expect(typeof routeSegment.pool.tokenY).toBe('string');
|
expect(typeof routeSegment.pool.tokenY).toBe('string');
|
||||||
});
|
});
|
||||||
});
|
}, 10000);
|
||||||
|
|
||||||
it('Attempt to Get Route with wrong tokens', async () => {
|
it('Attempt to Get Route with wrong tokens', async () => {
|
||||||
await expect(sdk.getRoute(wrongTokenAlex, wrongTokenAlex)).rejects.toThrow(
|
await expect(sdk.getRoute(wrongTokenAlex, wrongTokenAlex)).rejects.toThrow(
|
||||||
"Can't find route"
|
"Can't find route"
|
||||||
);
|
);
|
||||||
});
|
}, 10000);
|
||||||
|
|
||||||
it('Verify response of getAmountTo function', async () => {
|
it('Verify response of getAmountTo function', async () => {
|
||||||
const result = await sdk.getAmountTo(
|
const result = await sdk.getAmountTo(
|
||||||
@@ -81,13 +91,13 @@ describe('AlexSDK', () => {
|
|||||||
);
|
);
|
||||||
expect(typeof result).toBe('bigint');
|
expect(typeof result).toBe('bigint');
|
||||||
expect(result > BigInt(0)).toBeTruthy();
|
expect(result > BigInt(0)).toBeTruthy();
|
||||||
});
|
}, 10000);
|
||||||
|
|
||||||
it('Attempt to Get Rate with a wrong From token', async () => {
|
it('Attempt to Get Rate with a wrong From token', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
sdk.getAmountTo(wrongTokenAlex, BigInt(2) * BigInt(1e8), tokenDiko)
|
sdk.getAmountTo(wrongTokenAlex, BigInt(2) * BigInt(1e8), tokenDiko)
|
||||||
).rejects.toThrow('No AMM pool found for the given route');
|
).rejects.toThrow('No AMM pool found for the given route');
|
||||||
});
|
}, 10000);
|
||||||
|
|
||||||
it('Attempt to Get Rate with negative From amount', async () => {
|
it('Attempt to Get Rate with negative From amount', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
@@ -95,19 +105,19 @@ describe('AlexSDK', () => {
|
|||||||
).rejects.toThrow(
|
).rejects.toThrow(
|
||||||
'Cannot construct unsigned clarity integer from negative value'
|
'Cannot construct unsigned clarity integer from negative value'
|
||||||
);
|
);
|
||||||
});
|
}, 10000);
|
||||||
|
|
||||||
it('Attempt to Get Rate with an overflowing From amount (parseReadOnlyResponse)', async () => {
|
it('Attempt to Get Rate with an overflowing From amount (parseReadOnlyResponse)', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
sdk.getAmountTo(Currency.STX, BigInt(999999223372036854775807), tokenDiko)
|
sdk.getAmountTo(Currency.STX, BigInt(999999223372036854775807), tokenDiko)
|
||||||
).rejects.toThrow('ArithmeticOverflow');
|
).rejects.toThrow('ArithmeticOverflow');
|
||||||
});
|
}, 10000);
|
||||||
|
|
||||||
it('Attempt to Get Rate with an overflowing From amount (decoders)', async () => {
|
it('Attempt to Get Rate with an overflowing From amount (decoders)', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
sdk.getAmountTo(Currency.STX, BigInt(99999223372036854775807), tokenDiko)
|
sdk.getAmountTo(Currency.STX, BigInt(99999223372036854775807), tokenDiko)
|
||||||
).rejects.toThrow('ClarityError: 2011');
|
).rejects.toThrow('ClarityError: 2011');
|
||||||
});
|
}, 10000);
|
||||||
|
|
||||||
it('Verify response of runSwap function', async () => {
|
it('Verify response of runSwap function', async () => {
|
||||||
const result = await sdk.runSwap(
|
const result = await sdk.runSwap(
|
||||||
@@ -134,7 +144,68 @@ describe('AlexSDK', () => {
|
|||||||
]).toContain(result.functionName);
|
]).toContain(result.functionName);
|
||||||
expect(Array.isArray(result.functionArgs)).toBeTruthy();
|
expect(Array.isArray(result.functionArgs)).toBeTruthy();
|
||||||
expect(Array.isArray(result.postConditions)).toBeTruthy();
|
expect(Array.isArray(result.postConditions)).toBeTruthy();
|
||||||
});
|
}, 10000);
|
||||||
|
|
||||||
|
it('Attempt to Get Tx with an invalid stx address (checksum mismatch)', async () => {
|
||||||
|
await expect(
|
||||||
|
sdk.runSwap(
|
||||||
|
'SP25DP4A9EXT42KC40QDMYQPMQCT1P0R5234GWEGS',
|
||||||
|
Currency.STX,
|
||||||
|
tokenDiko,
|
||||||
|
BigInt(100),
|
||||||
|
BigInt(0)
|
||||||
|
)
|
||||||
|
).rejects.toThrow('Invalid c32check string: checksum mismatch');
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
|
it('Attempt to run swap with wrong token', async () => {
|
||||||
|
await expect(
|
||||||
|
sdk.runSwap(
|
||||||
|
'SP25DP4A9EXT42KC40QDMYQPMQCT1P0R5234GWEGS',
|
||||||
|
Currency.STX,
|
||||||
|
wrongTokenAlex,
|
||||||
|
BigInt(100),
|
||||||
|
BigInt(0)
|
||||||
|
)
|
||||||
|
).rejects.toThrow("Can't find AMM route");
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
|
it('Attempt to runSwap with an invalid minDy value', async () => {
|
||||||
|
const wrongValue = CLARITY_MAX_UNSIGNED_INT + BigInt(1);
|
||||||
|
await expect(
|
||||||
|
sdk.runSwap(
|
||||||
|
configs.CONTRACT_DEPLOYER,
|
||||||
|
Currency.STX,
|
||||||
|
tokenDiko,
|
||||||
|
BigInt(0),
|
||||||
|
wrongValue
|
||||||
|
)
|
||||||
|
).rejects.toThrow(
|
||||||
|
`Cannot construct unsigned clarity integer greater than ${CLARITY_MAX_UNSIGNED_INT}`
|
||||||
|
);
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
|
it('Verify response of getLatestPrices function', async () => {
|
||||||
|
const result = await sdk.getLatestPrices();
|
||||||
|
expect(result).toBeDefined();
|
||||||
|
expect(typeof result).toBe('object');
|
||||||
|
Object.values(result).forEach((value) => {
|
||||||
|
expect(typeof value).toBe('number');
|
||||||
|
expect(isNaN(Number(value))).toBe(false);
|
||||||
|
});
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
|
it('Verify response of getBalances function', async () => {
|
||||||
|
const stxAddress = 'SM2MARAVW6BEJCD13YV2RHGYHQWT7TDDNMNRB1MVT';
|
||||||
|
const balances = await sdk.getBalances(stxAddress);
|
||||||
|
expect(balances).toBeDefined();
|
||||||
|
expect(typeof balances).toBe('object');
|
||||||
|
Object.keys(balances).forEach((currency) => {
|
||||||
|
if (Object.values(Currency).includes(currency as Currency)) {
|
||||||
|
expect(typeof balances[currency as Currency]).toBe('bigint');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
it('Attempt to Get Tx with an invalid stx address (checksum mismatch)', async () => {
|
it('Attempt to Get Tx with an invalid stx address (checksum mismatch)', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
@@ -168,6 +239,14 @@ describe('AlexSDK', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Attempt to get balances with invalid address', async () => {
|
||||||
|
// TODO: Implement principal address verification in the SDK methods.
|
||||||
|
const wrongAddress = 'ABC';
|
||||||
|
await expect(sdk.getBalances(wrongAddress)).rejects.toThrow(
|
||||||
|
"Cannot read properties of undefined (reading 'balance')"
|
||||||
|
);
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
it('getAlexSDKData response', async () => {
|
it('getAlexSDKData response', async () => {
|
||||||
const response = await getAlexSDKData();
|
const response = await getAlexSDKData();
|
||||||
expect(response).toMatchType('AlexSDKResponse');
|
expect(response).toMatchType('AlexSDKResponse');
|
||||||
@@ -178,4 +257,20 @@ describe('AlexSDK', () => {
|
|||||||
const tokens = await sdk.fetchSwappableCurrency();
|
const tokens = await sdk.fetchSwappableCurrency();
|
||||||
expect(await getPrices(tokens)).toMatchType('BackendAPIPriceResponse');
|
expect(await getPrices(tokens)).toMatchType('BackendAPIPriceResponse');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Verify response of getWayPoints function', async () => {
|
||||||
|
const route = await sdk.getRoute(tokenAlex, Currency.STX);
|
||||||
|
const result = await sdk.getWayPoints(route);
|
||||||
|
expect(result[0].id).toBe(tokenAlex);
|
||||||
|
expect(result[1].id).toBe(Currency.STX);
|
||||||
|
result.forEach((token) => {
|
||||||
|
expect(typeof token.name).toBe('string');
|
||||||
|
expect(typeof token.icon).toBe('string');
|
||||||
|
expect(typeof token.wrapToken).toBe('string');
|
||||||
|
expect(typeof token.underlyingToken).toBe('string');
|
||||||
|
expect(typeof token.underlyingTokenDecimals).toBe('number');
|
||||||
|
expect(token.wrapTokenDecimals).toBe(8);
|
||||||
|
expect(token.isRebaseToken).toBe(false);
|
||||||
|
});
|
||||||
|
}, 10000);
|
||||||
});
|
});
|
||||||
|
|||||||
122
test/mock-data/alexSDKMockResponses.ts
Normal file
122
test/mock-data/alexSDKMockResponses.ts
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
import {
|
||||||
|
AlexSDKResponse,
|
||||||
|
PoolData,
|
||||||
|
PriceData,
|
||||||
|
TokenInfo,
|
||||||
|
} from '../../src/types';
|
||||||
|
import { TxToBroadCast } from '../../src/helpers/SwapHelper';
|
||||||
|
import { Currency } from '../../src';
|
||||||
|
import { AMMRouteSegment } from '../../src/utils/ammRouteResolver';
|
||||||
|
import { configs } from '../../src/config';
|
||||||
|
|
||||||
|
const validDeployer = configs.CONTRACT_DEPLOYER;
|
||||||
|
|
||||||
|
export const dummyFee = BigInt(777);
|
||||||
|
|
||||||
|
export const dummyTokenA = 'TokenA' as Currency;
|
||||||
|
export const dummyTokenB = 'TokenB' as Currency;
|
||||||
|
export const dummyTokenC = 'TokenC' as Currency;
|
||||||
|
|
||||||
|
export const dummyRoute = [dummyTokenA, dummyTokenB, dummyTokenC];
|
||||||
|
|
||||||
|
export const dummyFactorA = BigInt(670000000);
|
||||||
|
export const dummyFactorB = BigInt(680000000);
|
||||||
|
export const dummyAmmRoute: AMMRouteSegment[] = [
|
||||||
|
{
|
||||||
|
neighbour: dummyTokenC,
|
||||||
|
pool: {
|
||||||
|
tokenX: dummyTokenA,
|
||||||
|
tokenY: dummyTokenC,
|
||||||
|
factor: dummyFactorA,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
neighbour: dummyTokenB,
|
||||||
|
pool: {
|
||||||
|
tokenX: dummyTokenC,
|
||||||
|
tokenY: dummyTokenB,
|
||||||
|
factor: dummyFactorB,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const dummyRate = BigInt(1001);
|
||||||
|
|
||||||
|
export const dummyTx: TxToBroadCast = {
|
||||||
|
contractName: 'amm-pool-v2-01',
|
||||||
|
functionName: 'swap-helper',
|
||||||
|
functionArgs: [],
|
||||||
|
contractAddress: validDeployer,
|
||||||
|
postConditions: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const dummyPrices: PriceData[] = [
|
||||||
|
{
|
||||||
|
token: dummyTokenA,
|
||||||
|
price: 1.1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: dummyTokenB,
|
||||||
|
price: 2.2,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
export const parsedDummyPrices = {
|
||||||
|
TokenA: 1.1,
|
||||||
|
TokenB: 2.2,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const dummyBalances = {
|
||||||
|
TokenA: BigInt(86794603901),
|
||||||
|
TokenB: BigInt(86794603902),
|
||||||
|
};
|
||||||
|
|
||||||
|
export const dummyCurrencies: TokenInfo[] = [
|
||||||
|
{
|
||||||
|
id: dummyTokenA,
|
||||||
|
name: 'TKA',
|
||||||
|
icon: '',
|
||||||
|
wrapTokenDecimals: 8,
|
||||||
|
wrapToken: `${validDeployer}.token-a::tka`,
|
||||||
|
underlyingToken: `${validDeployer}.token-a::tka`,
|
||||||
|
underlyingTokenDecimals: 6,
|
||||||
|
isRebaseToken: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: dummyTokenB,
|
||||||
|
name: 'TKB',
|
||||||
|
icon: '',
|
||||||
|
wrapTokenDecimals: 8,
|
||||||
|
wrapToken: `${validDeployer}.token-b::tkb`,
|
||||||
|
underlyingToken: `${validDeployer}.token-b::tkb`,
|
||||||
|
underlyingTokenDecimals: 6,
|
||||||
|
isRebaseToken: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: dummyTokenC,
|
||||||
|
name: 'TKC',
|
||||||
|
icon: '',
|
||||||
|
wrapTokenDecimals: 8,
|
||||||
|
wrapToken: `${validDeployer}.token-c::tkc`,
|
||||||
|
underlyingToken: `${validDeployer}.token-c::tkc`,
|
||||||
|
underlyingTokenDecimals: 6,
|
||||||
|
isRebaseToken: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const dummyPools: PoolData[] = [
|
||||||
|
{
|
||||||
|
tokenX: dummyTokenA,
|
||||||
|
tokenY: dummyTokenC,
|
||||||
|
factor: BigInt(5000000),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tokenX: dummyTokenC,
|
||||||
|
tokenY: dummyTokenB,
|
||||||
|
factor: BigInt(5000000),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const dummyAlexSDKData: AlexSDKResponse = {
|
||||||
|
tokens: dummyCurrencies,
|
||||||
|
pools: dummyPools,
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user