UNPKG

@swaptoshi/dex-module

Version:

Klayr decentralized exchange (dex) on-chain module

179 lines 9.81 kB
"use strict"; 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