@swaptoshi/dex-module
Version:
Klayr decentralized exchange (dex) on-chain module
179 lines • 9.81 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.PoolStore = exports.defaultSlot0 = void 0;
const klayr_framework_1 = require("klayr-framework");
const cryptography = require("@klayr/cryptography");
const periphery_1 = require("./library/periphery");
const core_1 = require("./library/core");
const pool_created_1 = require("../events/pool_created");
const schema_1 = require("../schema");
const factory_1 = require("./factory");
const position_manager_1 = require("./position_manager");
const token_symbol_1 = require("./token_symbol");
const constants_1 = require("../constants");
const treasurify_1 = require("../events/treasurify");
const supported_token_1 = require("./supported_token");
exports.defaultSlot0 = Object.freeze({
sqrtPriceX96: '0',
tick: '0',
observationIndex: '0',
observationCardinality: '0',
observationCardinalityNext: '0',
});
class PoolStore extends klayr_framework_1.Modules.BaseStore {
constructor(moduleName, index, stores, events) {
super(moduleName, index);
this.schema = schema_1.poolStoreSchema;
this.dependencyReady = false;
this.stores = stores;
this.events = events;
this.moduleName = moduleName;
}
addDependencies(tokenMethod) {
this.tokenMethod = tokenMethod;
if (this.config !== undefined)
this.dependencyReady = true;
}
init(config) {
this.config = config;
if (this.tokenMethod !== undefined)
this.dependencyReady = true;
}
getKey(tokenA, tokenB, fee) {
return periphery_1.PoolAddress.computeAddress(periphery_1.PoolAddress.getPoolKey(tokenA, tokenB, fee));
}
async getMutableRouter(ctx) {
this._checkDependencies();
const config = await this.config.getConfig(ctx.context);
return (0, factory_1.createMutableRouterInstance)(ctx, this.stores, this.tokenMethod, config, this.moduleName);
}
async getImmutablePool(ctx, tokenA, tokenB, fee) {
this._checkDependencies();
if (!this.schema) {
throw new Error('Schema is not set');
}
const subStore = ctx.context.getStore(this.storePrefix, this.subStorePrefix);
const pool = await subStore.getWithSchema(this.getKey(tokenA, tokenB, fee), this.schema);
const config = await this.config.getConfig(ctx.context);
return (0, factory_1.createImmutablePoolInstance)(ctx, pool, this.stores, this.events, this.tokenMethod, config, this.moduleName);
}
async getMutablePool(ctx, tokenA, tokenB, fee) {
this._checkDependencies();
if (!this.schema) {
throw new Error('Schema is not set');
}
const subStore = ctx.context.getStore(this.storePrefix, this.subStorePrefix);
const pool = await subStore.getWithSchema(this.getKey(tokenA, tokenB, fee), this.schema);
const config = await this.config.getConfig(ctx.context);
return (0, factory_1.createMutablePoolInstance)(ctx, pool, this.stores, this.events, this.tokenMethod, config, this.moduleName);
}
async createPool(ctx, tokenA, tokenASymbol, tokenADecimal, tokenB, tokenBSymbol, tokenBDecimal, fee) {
this._checkDependencies();
if (tokenA.subarray(0, 1).compare(tokenB.subarray(0, 1)) !== 0)
throw new Error('tokenA and tokenB are not from same network');
const config = await this.config.getConfig(ctx.context);
const feeAmountTickSpacing = config.feeAmountTickSpacing.find(t => t.fee === fee);
if (!feeAmountTickSpacing)
throw new Error('tickSpacing unsupported');
const key = this.getKey(tokenA, tokenB, fee);
const orderedTokenKey = periphery_1.PoolAddress.getPoolKey(tokenA, tokenB, fee);
if (await this.has(ctx.context, key))
throw new Error('pool already exists');
const pool = {
...orderedTokenKey,
tickSpacing: feeAmountTickSpacing.tickSpacing,
maxLiquidityPerTick: core_1.Tick.tickSpacingToMaxLiquidityPerTick(feeAmountTickSpacing.tickSpacing),
feeGrowthGlobal0X128: '0',
feeGrowthGlobal1X128: '0',
liquidity: '0',
slot0: { ...exports.defaultSlot0 },
};
await this.set(ctx.context, key, pool);
await this.tokenMethod.initializeUserAccount(ctx.context, key, tokenA);
await this.tokenMethod.initializeUserAccount(ctx.context, key, tokenB);
await this.tokenMethod.initializeUserAccount(ctx.context, constants_1.POSITION_MANAGER_ADDRESS, tokenA);
await this.tokenMethod.initializeUserAccount(ctx.context, constants_1.POSITION_MANAGER_ADDRESS, tokenB);
await this.tokenMethod.initializeUserAccount(ctx.context, constants_1.ROUTER_ADDRESS, tokenA);
await this.tokenMethod.initializeUserAccount(ctx.context, constants_1.ROUTER_ADDRESS, tokenB);
const tokenABalance = await this.tokenMethod.getAvailableBalance(ctx.context, key, tokenA);
const tokenBBalance = await this.tokenMethod.getAvailableBalance(ctx.context, key, tokenB);
if (config.feeProtocolPool) {
const treasury = cryptography.address.getAddressFromKlayr32Address(config.feeProtocolPool, config.feeProtocolPool.substring(0, 3));
await this.tokenMethod.initializeUserAccount(ctx.context, treasury, tokenA);
await this.tokenMethod.initializeUserAccount(ctx.context, treasury, tokenB);
if (tokenABalance > BigInt(0)) {
await this.tokenMethod.transfer(ctx.context, key, treasury, tokenA, tokenABalance);
}
if (tokenBBalance > BigInt(0)) {
await this.tokenMethod.transfer(ctx.context, key, treasury, tokenB, tokenBBalance);
}
}
else {
if (tokenABalance > BigInt(0)) {
await this.tokenMethod.lock(ctx.context, key, this.moduleName, tokenA, tokenABalance);
}
if (tokenBBalance > BigInt(0)) {
await this.tokenMethod.lock(ctx.context, key, this.moduleName, tokenB, tokenBBalance);
}
}
const supportManagerStore = this.stores.get(supported_token_1.SupportedTokenStore);
await supportManagerStore.addSupport(ctx.context, tokenA);
await supportManagerStore.addSupport(ctx.context, tokenB);
const tokenSymbolStore = this.stores.get(token_symbol_1.TokenSymbolStore);
await tokenSymbolStore.registerSymbol(ctx.context, tokenA, tokenASymbol, tokenADecimal);
await tokenSymbolStore.registerSymbol(ctx.context, tokenB, tokenBSymbol, tokenBDecimal);
const positionManagerStore = this.stores.get(position_manager_1.PositionManagerStore);
const positionNameAndSymbol = `${tokenASymbol}/${tokenBSymbol}/${periphery_1.NFTDescriptor.feeToPercentString(fee)}`;
await positionManagerStore.set(ctx.context, positionManagerStore.getKey(key), {
poolAddress: key,
name: `${config.nftPositionMetadata.dex.name} Positions NFT - ${positionNameAndSymbol}`,
symbol: `${config.nftPositionMetadata.dex.symbol.toUpperCase()}POS-${positionNameAndSymbol}`,
});
const events = this.events.get(pool_created_1.PoolCreatedEvent);
events.add(ctx.context, {
...orderedTokenKey,
tickSpacing: feeAmountTickSpacing.tickSpacing,
poolAddress: key,
}, [key]);
return this.getMutablePool(ctx, tokenA, tokenB, fee);
}
async releaseTokenToProtocolTreasury(context, params) {
const config = await this.config.getConfig(context);
if (config.feeProtocolPool) {
if (params.address.compare(constants_1.ROUTER_ADDRESS) !== 0 && !(await this.has(context, params.address))) {
throw new Error('pool doesnt exists, and address is not a router');
}
const poolKey = periphery_1.PoolAddress.decodePoolAddress(params.address);
if ((await this.has(context, params.address)) && (params.token.compare(poolKey.token0) === 0 || params.token.compare(poolKey.token1) === 0)) {
throw new Error(`invalid attempt to treasurify pool's token0 or token1`);
}
let tokenToBeTransferred = BigInt(0);
let tokenToBeUnlocked = BigInt(0);
tokenToBeUnlocked = await this.tokenMethod.getLockedAmount(context, params.address, params.token, this.moduleName);
tokenToBeTransferred = await this.tokenMethod.getAvailableBalance(context, params.address, params.token);
if (tokenToBeTransferred > BigInt(0) || tokenToBeUnlocked > BigInt(0)) {
const treasury = cryptography.address.getAddressFromKlayr32Address(config.feeProtocolPool, config.feeProtocolPool.substring(0, 3));
let amount = tokenToBeTransferred;
if (tokenToBeUnlocked > BigInt(0)) {
await this.tokenMethod.unlock(context, params.address, this.moduleName, params.token, tokenToBeUnlocked);
amount += tokenToBeUnlocked;
}
await this.tokenMethod.transfer(context, params.address, treasury, params.token, amount);
const events = this.events.get(treasurify_1.TreasurifyEvent);
events.add(context, {
poolAddress: params.address,
treasuryAddress: treasury,
token: params.token,
amount: amount.toString(),
}, [params.address, treasury]);
}
}
}
_checkDependencies() {
if (!this.dependencyReady) {
throw new Error('dependencies not configured');
}
}
}
exports.PoolStore = PoolStore;
//# sourceMappingURL=pool.js.map