Skip to content
This repository has been archived by the owner on Jun 11, 2024. It is now read-only.

Commit

Permalink
Merge pull request #57 from LiskHQ/feature/intro-auxillary-functions
Browse files Browse the repository at this point in the history
Implement internal auxiliary functions - Closes #30
  • Loading branch information
emiliolisk committed Sep 12, 2022
2 parents 21b705f + b4d3068 commit e0aa748
Show file tree
Hide file tree
Showing 13 changed files with 303 additions and 32 deletions.
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
}
},
"dependencies": {
"@liskhq/lisk-cryptography": "^4.0.0-alpha.2",
"@liskhq/lisk-framework-dashboard-plugin": "^0.2.0-alpha.0",
"@liskhq/lisk-framework-faucet-plugin": "^0.2.0-alpha.0",
"@liskhq/lisk-framework-forger-plugin": "^0.3.0-alpha.0",
Expand Down
17 changes: 11 additions & 6 deletions src/app/app.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import { Application, PartialApplicationConfig } from 'lisk-sdk';
import { registerModules } from './modules';
import { registerPlugins } from './plugins';

import { Application, PartialApplicationConfig, TokenModule, ValidatorsModule } from 'lisk-sdk';

import { DexModule } from './modules';

export const getApplication = (config: PartialApplicationConfig): Application => {
const { app } = Application.defaultApplication(config);
registerModules(app);
registerPlugins(app);
const dexModule = new DexModule();
const tokenModule = new TokenModule();
const validatorModule = new ValidatorsModule();

dexModule.addDependencies(tokenModule.api, validatorModule.api);
app.registerModule(dexModule);

return app;
};
};
8 changes: 1 addition & 7 deletions src/app/modules.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1 @@
/* eslint-disable @typescript-eslint/no-empty-function */
import { Application } from 'lisk-sdk';
import { DexModule } from './modules/dex/module';

export const registerModules = (app: Application): void => {
app.registerModule(new DexModule());
};
export { DexModule } from './modules/dex/module';
9 changes: 9 additions & 0 deletions src/app/modules/dex/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,12 @@ export const MAX_TICK = 887272 // The maximum possible tick value as a sint32.
export const MIN_SQRT_RATIO = BigInt(4295128738) // Todo: check with devs The minimum possible price value in the Q96 representation.
export const MAX_SQRT_RATIO = BigInt('1461446703529909599612049957420313862569572983184') // Todo: check with devs The maximum possible price value in the Q96 representation.
export const PRICE_VALUE_FOR_BIT_POSITION_IN_Q96 = []; // TBA Array of uint256 values with the pre-computed values of price for certain values of tickValue in the Q96 representation.

export const defaultConfig = {
feeTiers: {
100: 2,
500: 10,
3000: 60,
10000: 200
}
};
39 changes: 27 additions & 12 deletions src/app/modules/dex/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,45 @@
import {
BaseModule,
ModuleMetadata,
TokenAPI,
ValidatorsAPI,
utils
} from 'lisk-sdk';

import {
FeeTiers,
} from './types';

import {
MODULE_ID_DEX,
MODULE_NAME_DEX,
defaultConfig
} from './constants';

import { DexAPI } from './api';
import { DexEndpoint } from './endpoint';
import {
DexAPI
} from './api';
import {
DexEndpoint
} from './endpoint';
import {
ModuleConfig,
ModuleInitArgs
} from './types';

export class DexModule extends BaseModule {
public name = MODULE_NAME_DEX;
public id = MODULE_ID_DEX;
public endpoint = new DexEndpoint(this.id);
public api = new DexAPI(this.id);
private _feeTiers: FeeTiers = {};
public _tokenAPI!: TokenAPI;
public _validatorsAPI!: ValidatorsAPI;
public _moduleConfig!: ModuleConfig;

// eslint-disable-next-line @typescript-eslint/member-ordering
public commands = [];

public addDependencies(tokenAPI: TokenAPI, validatorsAPI: ValidatorsAPI) {
this._tokenAPI = tokenAPI;
this._validatorsAPI = validatorsAPI;
}

public metadata(): ModuleMetadata {
return {
id: this.id,
Expand All @@ -51,10 +66,10 @@ export class DexModule extends BaseModule {
}

// eslint-disable-next-line @typescript-eslint/require-await
public async init() {
this._feeTiers[100] = 2;
this._feeTiers[500] = 10;
this._feeTiers[3000] = 60;
this._feeTiers[10000] = 200;
public async init(args: ModuleInitArgs) {
const {
moduleConfig
} = args;
this._moduleConfig = utils.objects.mergeDeep({}, defaultConfig, moduleConfig) as ModuleConfig;
}
}
25 changes: 24 additions & 1 deletion src/app/modules/dex/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
* Removal or modification of this copyright notice is prohibited.
*/

import { JSONObject } from 'lisk-sdk';

export interface FeeTiers {
[id: number]: number;
}
Expand All @@ -20,4 +22,25 @@ export type Q96 = bigint;
export type TokenID = Buffer;
export type PoolID = Buffer;
export type PositionID = Buffer;
export type Address = Buffer;
export type Address = Buffer;

export interface LegacyStoreData {
legacyAddress: string;
balance: bigint;
}

export interface ReclaimParamsData {
amount: bigint;
}

export type TokenIDReclaim = Buffer;

export interface ModuleConfig {
protocolFeeAddress: Address;
}

export type ModuleConfigJSON = JSONObject<ModuleConfig>;

export interface ModuleInitArgs {
moduleConfig: Record<string, unknown>;
}
21 changes: 21 additions & 0 deletions src/app/modules/dex/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright © 2022 Lisk Foundation
*
* See the LICENSE file at the top-level directory of this distribution
* for licensing information.
*
* Unless otherwise agreed in a custom licensing agreement with the Lisk Foundation,
* no part of this software, including this file, may be copied, modified,
* propagated, or distributed except according to the terms contained in the
* LICENSE file.
*
* Removal or modification of this copyright notice is prohibited.
*/
import { ModuleConfig, ModuleConfigJSON } from './types';

export function getModuleConfig(config: ModuleConfigJSON): ModuleConfig {
return {
...config,
tokenIDReclaim: Buffer.from(config.tokenIDReclaim, 'hex'),
};
}
118 changes: 118 additions & 0 deletions src/app/modules/dex/utils/auxiliaryFunctions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* Copyright © 2022 Lisk Foundation
*
* See the LICENSE file at the top-level directory of this distribution
* for licensing information.
*
* Unless otherwise agreed in a custom licensing agreement with the Lisk Foundation,
* no part of this software, including this file, may be copied, modified,
* propagated, or distributed except according to the terms contained in the
* LICENSE file.
*
* Removal or modification of this copyright notice is prohibited.
*/


import {
TokenAPI
} from 'lisk-sdk';

import {
utils
} from '@liskhq/lisk-cryptography';

import {
NUM_BYTES_ADDRESS,
NUM_BYTES_TOKEN_ID,
NUM_BYTES_POSITION_ID,
MODULE_ID_DEX
} from '../constants';

import {
uint32beInv
} from "./bigEndian";

import {
PoolID,
PositionID,
Address,
TokenID,
ModuleConfig
} from "../types";

export const poolIdToAddress = (poolId: PoolID): Address => {
const _address: Buffer = utils.hash(poolId);
return _address.slice(0, NUM_BYTES_ADDRESS);
}

export const getToken0Id = (poolId: PoolID): TokenID => poolId.slice(0, NUM_BYTES_TOKEN_ID + 1);

export const getToken1Id = (poolId: PoolID): TokenID => poolId.slice(NUM_BYTES_TOKEN_ID, (2 * NUM_BYTES_TOKEN_ID) + 1);

export const getFeeTier = (poolId: PoolID): number => {
const _buffer: Buffer = poolId.slice(-4);
const _hexBuffer: string = _buffer.toString('hex');

return uint32beInv(_hexBuffer);
}

export const getPositionIndex = (positionId: PositionID): number => {
const _buffer: Buffer = positionId.slice(2 * NUM_BYTES_POSITION_ID, NUM_BYTES_ADDRESS);
const _hexBuffer: string = _buffer.toString('hex');

return uint32beInv(_hexBuffer);
}

export const transferToPool = async (tokenAPI: TokenAPI, apiContext, senderAddress: Address, poolId: PoolID, tokenId: TokenID, amount: bigint): Promise < void > => {
const poolAddress = poolIdToAddress(poolId);
await tokenAPI.transfer(apiContext, senderAddress, poolAddress, tokenId, amount);
await tokenAPI.lock(apiContext, poolAddress, MODULE_ID_DEX, tokenId, amount);
}

export const transferFromPool = async (
tokenAPI: TokenAPI,
apiContext,
poolId: PoolID,
recipientAddress: Address,
tokenId: TokenID,
amount: bigint
): Promise < void > => {
const poolAddress = poolIdToAddress(poolId)
await tokenAPI.unlock(apiContext, poolAddress, MODULE_ID_DEX, tokenId, amount)
await tokenAPI.transfer(apiContext, poolAddress, recipientAddress, tokenId, amount)
}

export const transferPoolToPool = async (
tokenAPI: TokenAPI,
apiContext,
poolIdSend: PoolID,
poolIdReceive: PoolID,
tokenId: TokenID,
amount: bigint
): Promise < void > => {
const poolAddressSend = poolIdToAddress(poolIdSend)
const poolAddressReceive = poolIdToAddress(poolIdReceive)
await tokenAPI.unlock(apiContext, poolAddressSend, MODULE_ID_DEX, tokenId, amount)
await tokenAPI.transfer(apiContext, poolAddressSend, poolAddressReceive, tokenId, amount)
await tokenAPI.lock(apiContext, poolAddressReceive, MODULE_ID_DEX, tokenId, amount)
}

export const transferToProtocolFeeAccount = async (
tokenAPI: TokenAPI,
apiContext,
settings: ModuleConfig,
senderAddress: Address,
tokenId: TokenID,
amount: bigint
): Promise < void > => {
await tokenAPI.transfer(apiContext, senderAddress, settings.protocolFeeAddress, tokenId, amount)
}

// Convert a hex string to a byte array
export const hexToBytes = (hex) => {
const bytes: number[] = [];
for (let c = 0; c < hex.length; c += 2)
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
bytes.push(parseInt(hex.substr(c, 2), 16));
return bytes;
}
50 changes: 50 additions & 0 deletions src/app/modules/dex/utils/math.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright © 2022 Lisk Foundation
*
* See the LICENSE file at the top-level directory of this distribution
* for licensing information.
*
* Unless otherwise agreed in a custom licensing agreement with the Lisk Foundation,
* no part of this software, including this file, may be copied, modified,
* propagated, or distributed except according to the terms contained in the
* LICENSE file.
*
* Removal or modification of this copyright notice is prohibited.
*/

import JSBI from 'jsbi';
import {toBigIntBE, toBigIntLE, toBufferBE, toBufferLE} from 'bigint-buffer';

import { NUM_BYTES_Q96, PRICE_VALUE_FOR_BIT_POSITION_IN_Q96, MIN_TICK, MAX_TICK } from '../constants';
import { sqrt } from "./math_constants";

import { Q96 } from '../types';
import { qn_r, mul_n, inv_n } from './q96';

export const computeSqrtPrice = (a: JSBI): Buffer => {
const sq_a = sqrt(a);
const a_hex: string = sq_a.toString(16);

return toBufferBE(BigInt(a_hex), NUM_BYTES_Q96);
}

export const tickToPrice = (tickValue: number): Q96 => {

if(tickValue < MIN_TICK || tickValue > MAX_TICK){
//return;
}

let absTick: number = Math.abs(tickValue)
let sqrtPrice: JSBI = qn_r(1);

PRICE_VALUE_FOR_BIT_POSITION_IN_Q96.forEach((e, i) => {
if ((absTick >> i) & 1){
sqrtPrice = mul_n(sqrtPrice, e);
}
});

if(tickValue > 0)
sqrtPrice = inv_n(sqrtPrice)

return sqrtPrice
}
27 changes: 27 additions & 0 deletions test/unit/modules/dex/auxiliaryFunctions.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import {
getToken0Id,
getToken1Id,
getFeeTier,
hexToBytes
} from '../../../../src/app/modules/dex/utils/auxiliaryFunctions';

import {
PoolID, TokenID
} from '../../../../src/app/modules/dex/types';

describe('dex:auxiliaryFunctions', () => {
describe('constructor', () => {
const poolId: PoolID = Buffer.from(hexToBytes('0x00000000000000000000000100000000000000c8'));
const token0Id: TokenID = Buffer.from(hexToBytes('0x0000000000000000'));
const token1Id: TokenID = Buffer.from(hexToBytes('0x0000000100000000'));
it('getToken0Id', async () => {
expect(getToken0Id(poolId)).toEqual(token0Id);
});
it('getToken1Id', async () => {
expect(getToken1Id(poolId)).toEqual(token1Id);
});
it('getFeeTier', async () => {
expect(getFeeTier(poolId)).toEqual(Number('0x000000c8'));
});
});
});
Loading

0 comments on commit e0aa748

Please sign in to comment.