Skip to content

Commit

Permalink
feat: upgrades types to correct sdk types
Browse files Browse the repository at this point in the history
  • Loading branch information
kenodressel committed Feb 14, 2024
1 parent 1760101 commit 3233306
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 114 deletions.
119 changes: 50 additions & 69 deletions src/lib/contracts.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import NETWORKS from './networks';
import { AeSdk, Node } from '@aeternity/aepp-sdk';
import { CallData, ContractAddress, WalletAddress, nonNullable } from './utils';
import {
AeSdk,
Node,
ContractMethodsBase,
} from '@aeternity/aepp-sdk';
import { ContractAddress, nonNullable } from './utils';
import * as routerInterface from 'dex-contracts-v2/build/AedexV2Router.aci.json';
import * as factoryInterface from 'dex-contracts-v2/build/AedexV2Factory.aci.json';
import * as pairInterface from 'dex-contracts-v2/build/AedexV2Pair.aci.json';
import ContractWithMethods from '@aeternity/aepp-sdk/es/contract/Contract';

let client: AeSdk;
let node: Node;
Expand All @@ -23,32 +28,21 @@ const getClient = async (): Promise<[AeSdk, Node]> => {
};

export type RouterMethods = {
factory: () => ContractMethodResult<ContractAddress>;
factory: () => ContractAddress;
};

export type FactoryMethods = {
allPairs: () => ContractMethodResult<ContractAddress[]>;
get_all_pairs: () => ContractAddress[];
};

export type ContractMethodResult<T> = Promise<{
result: {
callerId: WalletAddress;
callerNonce: number;
contractId: ContractAddress;
gasPrice: number;
gasUsed: number;
height: number;
log: any[];
returnType: 'ok' | 'revert';
returnValue: CallData;
};
decodedResult: T;
}>;
export type PairMethods = {
token0: () => ContractMethodResult<ContractAddress>;
token1: () => ContractMethodResult<ContractAddress>;
totalSupply: () => ContractMethodResult<bigint>;
reserves: () => ContractMethodResult<{ reserve0: bigint; reserve1: bigint }>;
token0: () => ContractAddress;
token1: () => ContractAddress;
total_supply: () => bigint;
get_reserves: () => {
reserve0: bigint;
reserve1: bigint;
};
};

export type MetaInfo = {
Expand All @@ -58,76 +52,60 @@ export type MetaInfo = {
};

export type Aex9Methods = {
metaInfo: () => ContractMethodResult<MetaInfo>;
};

const wrapRouter = (router: any): RouterMethods => {
return {
factory: router.factory,
};
};
const wrapFactory = (factory: any): FactoryMethods => {
return {
allPairs: factory.get_all_pairs,
};
};

const wrapPair = (pair: any): PairMethods => {
return {
token0: pair.token0,
token1: pair.token1,
totalSupply: pair.total_supply,
reserves: pair.get_reserves,
};
};

const wrapAex9 = (token: any): Aex9Methods => {
return {
metaInfo: token.meta_info,
};
meta_info: () => MetaInfo;
};

export type Context = {
router: RouterMethods;
factory: FactoryMethods;
getPair: (address: ContractAddress) => Promise<PairMethods>;
getToken: (address: ContractAddress) => Promise<Aex9Methods>;
router: ContractWithMethods<RouterMethods>;
factory: ContractWithMethods<FactoryMethods>;
getPair: (
address: ContractAddress,
) => Promise<ContractWithMethods<PairMethods>>;
getToken: (
address: ContractAddress,
) => Promise<ContractWithMethods<Aex9Methods>>;
node: Node;
};

const createGetToken =
(
tokens: { [key: string]: Aex9Methods | undefined },
getInstance: (source: string, address: string) => Promise<any>,
tokens: { [key: string]: ContractWithMethods<Aex9Methods> | undefined },
getInstance: Awaited<ReturnType<typeof instanceFactory>>,
) =>
async (tokenAddress: string): Promise<Aex9Methods> => {
async (
tokenAddress: ContractAddress,
): Promise<ContractWithMethods<Aex9Methods>> => {
const cached = tokens[tokenAddress];
if (cached) {
return cached;
}
const token = wrapAex9(await getInstance(pairInterface, tokenAddress));
const token = await getInstance<Aex9Methods>(pairInterface, tokenAddress);
tokens[tokenAddress] = token;
return token;
};

const createGetPair =
(
pairs: { [key: string]: PairMethods | undefined },
getInstance: (source: string, address: string) => any,
pairs: { [key: string]: ContractWithMethods<PairMethods> | undefined },
getInstance: Awaited<ReturnType<typeof instanceFactory>>,
) =>
async (pairAddress: string): Promise<PairMethods> => {
async (
pairAddress: ContractAddress,
): Promise<ContractWithMethods<PairMethods>> => {
const cached = pairs[pairAddress];
if (cached) {
return cached;
}
const pair = wrapPair(await getInstance(pairInterface, pairAddress));
const pair = await getInstance<PairMethods>(pairInterface, pairAddress);
pairs[pairAddress] = pair;
return pair;
};

const instanceFactory = async (client: AeSdk) => {
return (aci: any, contractAddress: ContractAddress) =>
client.initializeContract({ aci, address: contractAddress });
return <T extends ContractMethodsBase>(
aci: any,
contractAddress: ContractAddress,
) => client.initializeContract<T>({ aci, address: contractAddress });
};

export const getContext = async (): Promise<Context> => {
Expand All @@ -137,21 +115,24 @@ export const getContext = async (): Promise<Context> => {
}
const [client, node] = await getClient();
const getInstance = await instanceFactory(client);
const router = await getInstance(
const router = await getInstance<RouterMethods>(
routerInterface,
nonNullable<ContractAddress>(routerAddress as ContractAddress),
);
const factory = await getInstance(
const factory = await getInstance<FactoryMethods>(
factoryInterface,
nonNullable<ContractAddress>(
process.env.FACTORY_ADDRESS as ContractAddress,
),
);
const pairs: { [key: string]: PairMethods | undefined } = {};
const tokens: { [key: string]: Aex9Methods | undefined } = {};
const pairs: { [key: string]: ContractWithMethods<PairMethods> | undefined } =
{};
const tokens: {
[key: string]: ContractWithMethods<Aex9Methods> | undefined;
} = {};
return {
router: wrapRouter(router),
factory: wrapFactory(factory),
router,
factory,
getPair: createGetPair(pairs, getInstance),
getToken: createGetToken(tokens, getInstance),
node,
Expand Down
26 changes: 16 additions & 10 deletions src/worker/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@ import * as mdw from './middleware';

import { Logger } from '@nestjs/common';
import { ContractAddress } from 'src/lib/utils';
import ContractWithMethods from '@aeternity/aepp-sdk/es/contract/Contract';
const logger = new Logger('Worker');

const updateTokenMetadata = async (
address: ContractAddress,
tokenMethods: Aex9Methods,
tokenMethods: ContractWithMethods<Aex9Methods>,
) => {
try {
const {
decodedResult: { name, symbol, decimals },
} = await tokenMethods.metaInfo();
} = await tokenMethods.meta_info();

const tokenFromDb = await dal.token.upsertToken(
address,
Expand All @@ -39,7 +40,7 @@ const upsertTokenInformation = async (
if (token) {
return token.id;
}
let tokenMethods: Aex9Methods;
let tokenMethods: ContractWithMethods<Aex9Methods>;
try {
tokenMethods = await ctx.getToken(address);
} catch (error) {
Expand Down Expand Up @@ -112,17 +113,22 @@ const refreshPairLiquidity = async (
height?: number,
) => {
const pair = await ctx.getPair(dbPair.address as ContractAddress);
const { decodedResult: totalSupply } = await pair.totalSupply();
const { decodedResult: totalSupply } = await pair.total_supply();
const {
decodedResult: { reserve0, reserve1 },
result: { height: heightFromDryRun },
} = await pair.reserves();
result,
} = await pair.get_reserves();
const syncHeight = height || result?.height;
if (!syncHeight) {
console.error('Could not get height');
return;
}
const ret = await dal.pair.synchronise(
dbPair.id,
totalSupply,
reserve0,
reserve1,
height || heightFromDryRun,
syncHeight,
);
logger.debug(
`Pair ${ret.token0.symbol}/${ret.token1.symbol} [${
Expand All @@ -138,7 +144,7 @@ const refreshPairLiquidity = async (

const refreshPairs = async (ctx: Context): Promise<ContractAddress[]> => {
logger.log(`Getting all pairs from Factory...`);
const { decodedResult: allFactoryPairs } = await ctx.factory.allPairs();
const { decodedResult: allFactoryPairs } = await ctx.factory.get_all_pairs();
logger.log(`${allFactoryPairs.length} pairs found on DEX`);
const allDbPairsLen = await dal.pair.count(true);
//get new pairs, and reverse it , because allFactoryPairs is reversed by the factory contract
Expand All @@ -157,15 +163,15 @@ const refreshPairs = async (ctx: Context): Promise<ContractAddress[]> => {
const pairWithTokens = await Promise.all(
newAddresses.map(
async (
pairAddress,
pairAddress: ContractAddress,
): Promise<[ContractAddress, [ContractAddress, ContractAddress]]> => [
pairAddress,
await getPairTokens(ctx, pairAddress),
],
),
);

const tokenSet = new Set(
const tokenSet: Set<ContractAddress> = new Set(
pairWithTokens.reduce(
(acc: ContractAddress[], data) => acc.concat(data[1]),
[],
Expand Down
17 changes: 7 additions & 10 deletions test/context-mockup.spec.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
import { Context, PairMethods } from '../src/lib/contracts';
import { mockDeep } from 'jest-mock-extended';
import {
mockContext,
ContextData,
mockupContractMethod,
} from './utils/context.mockup';
import { mockContext, ContextData, mockupContractMethod } from './utils';
import * as data from './data/context-mockups';
import ContractWithMethods from '@aeternity/aepp-sdk/es/contract/Contract';

describe('Context', () => {
it('sample mockup', async () => {
const mocked = mockDeep<Context>();

const mockedPM = mockDeep<PairMethods>();
const mockedPM = mockDeep<ContractWithMethods<PairMethods>>();
mockedPM.token0
.calledWith()
.mockReturnValue(Promise.resolve(mockupContractMethod('ct_sample')));
Expand All @@ -35,14 +32,14 @@ const testContextDataMockup = (label: string, contextData: ContextData) => {
});

it('test factory.allPairs()', async () => {
const { decodedResult: pairs } = await context.factory.allPairs();
const { decodedResult: pairs } = await context.factory.get_all_pairs();
expect(pairs).toEqual(contextData.pairs.map((x) => x.address).reverse());
});

for (const token of contextData.tokens) {
it(`test getToken('${token.address}')`, async () => {
const methods = await context.getToken(token.address);
expect((await methods.metaInfo()).decodedResult).toEqual(
expect((await methods.meta_info()).decodedResult).toEqual(
token.metaInfo,
);
});
Expand All @@ -57,10 +54,10 @@ const testContextDataMockup = (label: string, contextData: ContextData) => {
expect((await pairMethods.token1()).decodedResult).toBe(
contextData.tokens[pair.t1].address,
);
expect((await pairMethods.totalSupply()).decodedResult).toBe(
expect((await pairMethods.total_supply()).decodedResult).toBe(
pair.totalSupply,
);
expect((await pairMethods.reserves()).decodedResult).toEqual({
expect((await pairMethods.get_reserves()).decodedResult).toEqual({
reserve0: pair.reserve0,
reserve1: pair.reserve1,
});
Expand Down
8 changes: 4 additions & 4 deletions test/contracts.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ describe('with real Context on testnet', () => {
});
it('should have at least 16 pairs', async () => {
expect(
(await ctx().factory.allPairs()).decodedResult.length,
(await ctx().factory.get_all_pairs()).decodedResult.length,
).toBeGreaterThanOrEqual(16);
});
it('pair should return right token addresses', async () => {
const { decodedResult: allPairs } = await ctx().factory.allPairs();
const { decodedResult: allPairs } = await ctx().factory.get_all_pairs();
const pairAddress = allPairs[allPairs.length - 1];
expect(pairAddress).toBe(
'ct_efYtiwDg4YZxDWE3iLPzvrjb92CJPvzGwriv4ZRuvuTDMNMb9',
Expand All @@ -47,7 +47,7 @@ describe('with real Context on testnet', () => {
'ct_7tTzPfvv3Vx8pCEcuk1kmgtn4sFsYCQDzLi1LvFs8T5PJqgsC',
);

const { decodedResult: metaInfo } = await tokenMethods.metaInfo();
const { decodedResult: metaInfo } = await tokenMethods.meta_info();
expect(metaInfo).toEqual({
decimals: 18n,
name: 'TestAEX9-B',
Expand All @@ -58,7 +58,7 @@ describe('with real Context on testnet', () => {
const tokenMethods = await ctx().getToken(
'ct_JDp175ruWd7mQggeHewSLS1PFXt9AzThCDaFedxon8mF8xTRF',
);
const { decodedResult: metaInfo } = await tokenMethods.metaInfo();
const { decodedResult: metaInfo } = await tokenMethods.meta_info();
expect(metaInfo).toEqual({
decimals: 18n,
name: 'Wrapped Aeternity',
Expand Down
2 changes: 1 addition & 1 deletion test/swap-routes.e2e-spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import * as request from 'supertest';
import { AppModule } from './../src/api/app.module';
import { AppModule } from '../src/api/app.module';

import { mockContext, listToken } from './utils';
import worker from '../src/worker';
Expand Down
2 changes: 1 addition & 1 deletion test/tokens.e2e-spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import * as request from 'supertest';
import { AppModule } from './../src/api/app.module';
import { AppModule } from '../src/api/app.module';

import worker from '../src/worker';
import { clean as cleanDb } from './utils/db';
Expand Down
Loading

0 comments on commit 3233306

Please sign in to comment.