From 13d7a55d6e8c80a0e822294018dda12272d3f08d Mon Sep 17 00:00:00 2001 From: Filippo Fontana Date: Tue, 12 Nov 2024 15:21:09 +0100 Subject: [PATCH] fix: improve handling of undefined get services --- src/@types/gobal.d.ts | 11 +- src/helpers/types.ts | 5 +- src/index.ts | 4 +- src/mappings/handlers/blockHandlers.ts | 5 +- src/mappings/handlers/ethHandlers.ts | 269 +++++++++--------- src/mappings/handlers/evmHandlers.ts | 6 +- src/mappings/handlers/investmentsHandlers.ts | 4 + src/mappings/handlers/loansHandlers.ts | 20 +- src/mappings/handlers/poolsHandlers.ts | 2 + src/mappings/services/accountService.test.ts | 5 +- src/mappings/services/assetCashflowService.ts | 9 +- src/mappings/services/assetService.test.ts | 7 +- src/mappings/services/assetService.ts | 13 +- .../services/currencyBalanceService.ts | 5 +- src/mappings/services/currencyService.test.ts | 4 +- src/mappings/services/currencyService.ts | 5 +- src/mappings/services/epochService.ts | 13 +- src/mappings/services/poolFeeService.ts | 4 +- src/mappings/services/poolService.test.ts | 14 +- src/mappings/services/poolService.ts | 29 +- src/mappings/services/trancheService.test.ts | 14 +- src/mappings/services/trancheService.ts | 15 +- tsconfig.json | 2 +- yarn.lock | 21 +- 24 files changed, 286 insertions(+), 200 deletions(-) diff --git a/src/@types/gobal.d.ts b/src/@types/gobal.d.ts index 2bfeafcc..a8b57a8d 100644 --- a/src/@types/gobal.d.ts +++ b/src/@types/gobal.d.ts @@ -1,4 +1,13 @@ -export {} +import { ApiPromise } from '@polkadot/api' +import type { Provider } from '@ethersproject/providers' +import { ApiDecoration } from '@polkadot/api/types' +import '@subql/types-core/dist/global' +export type ApiAt = ApiDecoration<'promise'> & { + rpc: ApiPromise['rpc'] +} declare global { + const api: ApiAt | Provider + const unsafeApi: ApiPromise | undefined function getNodeEvmChainId(): Promise } +export {} diff --git a/src/helpers/types.ts b/src/helpers/types.ts index 10f3acbd..8292712f 100644 --- a/src/helpers/types.ts +++ b/src/helpers/types.ts @@ -3,6 +3,7 @@ import { AugmentedCall, AugmentedRpc, PromiseRpcResult } from '@polkadot/api/typ import { Enum, Null, Struct, u128, u32, u64, U8aFixed, Option, Vec, Bytes, Result, bool } from '@polkadot/types' import { AccountId32, Perquintill, Balance } from '@polkadot/types/interfaces' import { ITuple, Observable } from '@polkadot/types/types' +import type { ApiAt } from '../@types/gobal' export interface PoolDetails extends Struct { reserve: { total: u128; available: u128; max: u128 } @@ -503,7 +504,7 @@ export type PoolFeesList = Vec export type OracleFedEvent = ITuple<[feeder: DevelopmentRuntimeOriginCaller, key: OracleKey, value: u128]> -export type ExtendedRpc = typeof api.rpc & { +export type ExtendedRpc = ApiAt['rpc'] & { pools: { trancheTokenPrice: PromiseRpcResult< AugmentedRpc<(poolId: number | string, trancheId: number[]) => Observable> @@ -512,7 +513,7 @@ export type ExtendedRpc = typeof api.rpc & { } } -export type ExtendedCall = typeof api.call & { +export type ExtendedCall = ApiAt['call'] & { loansApi: { portfolio: AugmentedCall<'promise', (poolId: string) => Observable>>> expectedCashflows: AugmentedCall< diff --git a/src/index.ts b/src/index.ts index 761dea75..7acbe0fa 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,8 +5,8 @@ import type { u64 } from '@polkadot/types' import type { Provider } from '@ethersproject/providers' const isSubstrateNode = 'query' in api -const isEvmNode = typeof (api as unknown as Provider).getNetwork === 'function' -const ethNetworkProm = isEvmNode ? (api as unknown as Provider).getNetwork() : null +const isEvmNode = typeof (api as Provider).getNetwork === 'function' +const ethNetworkProm = isEvmNode ? (api as Provider).getNetwork() : null global.fetch = fetch as unknown as typeof global.fetch global.atob = atob as typeof global.atob diff --git a/src/mappings/handlers/blockHandlers.ts b/src/mappings/handlers/blockHandlers.ts index e4d3fd92..146cbfc5 100644 --- a/src/mappings/handlers/blockHandlers.ts +++ b/src/mappings/handlers/blockHandlers.ts @@ -23,7 +23,9 @@ import { EpochService } from '../services/epochService' import { SnapshotPeriodService } from '../services/snapshotPeriodService' import { TrancheBalanceService } from '../services/trancheBalanceService' import { InvestorPositionService } from '../services/investorPositionService' +import { ApiAt } from '../../@types/gobal' +const cfgApi = api as ApiAt const timekeeper = TimekeeperService.init() export const handleBlock = errorHandler(_handleBlock) @@ -35,7 +37,7 @@ async function _handleBlock(block: SubstrateBlock): Promise { const newPeriod = (await timekeeper).processBlock(block.timestamp) if (newPeriod) { - const specVersion = api.runtimeVersion.specVersion.toNumber() + const specVersion = cfgApi.runtimeVersion.specVersion.toNumber() logger.info( `# It's a new period on block ${blockNumber}: ${block.timestamp.toISOString()} (specVersion: ${specVersion})` ) @@ -103,6 +105,7 @@ async function _handleBlock(block: SubstrateBlock): Promise { pool.resetUnrealizedProfit() for (const loanId in activeLoanData) { const asset = await AssetService.getById(pool.id, loanId) + if(!asset) continue if (!asset.currentPrice) throw new Error('Asset current price not set') if (!asset.notional) throw new Error('Asset notional not set') await asset.loadSnapshot(lastPeriodStart) diff --git a/src/mappings/handlers/ethHandlers.ts b/src/mappings/handlers/ethHandlers.ts index 5407e6c4..f74ce79e 100644 --- a/src/mappings/handlers/ethHandlers.ts +++ b/src/mappings/handlers/ethHandlers.ts @@ -33,131 +33,138 @@ async function _handleEthBlock(block: EthereumBlock): Promise { const newPeriod = (await timekeeper).processBlock(date) const blockPeriodStart = getPeriodStart(date) - if (newPeriod) { - logger.info(`It's a new period on EVM block ${blockNumber}: ${date.toISOString()}`) - const blockchain = await BlockchainService.getOrInit('1') - const currency = await CurrencyService.getOrInitEvm(blockchain.id, DAIMainnetAddress, DAISymbol, DAIName) - - const snapshotPeriod = SnapshotPeriodService.init(blockPeriodStart) - await snapshotPeriod.save() - - // update pool states - const poolUpdateCalls: PoolMulticall[] = [] + if (!newPeriod) return + logger.info(`It's a new period on EVM block ${blockNumber}: ${date.toISOString()}`) + const blockchain = await BlockchainService.getOrInit(chainId) + const currency = await CurrencyService.getOrInitEvm(blockchain.id, DAIMainnetAddress, DAISymbol, DAIName) + + const snapshotPeriod = SnapshotPeriodService.init(blockPeriodStart) + await snapshotPeriod.save() + + // update pool states + const processedPools: PoolService[] = [] + const poolUpdateCalls: PoolMulticall[] = [] + + for (const tinlakePool of tinlakePools) { + if (blockNumber < tinlakePool.startBlock) continue + const pool = await PoolService.getOrSeed(tinlakePool.id, false, false, blockchain.id) + processedPools.push(pool) + + const latestNavFeed = getLatestContract(tinlakePool.navFeed, blockNumber) + const latestReserve = getLatestContract(tinlakePool.reserve, blockNumber) + + // initialize new pool + if (!pool.isActive) { + await pool.initTinlake(tinlakePool.shortName, currency.id, date, blockNumber) + await pool.save() + + const senior = await TrancheService.getOrSeed(pool.id, 'senior', blockchain.id) + await senior.initTinlake(pool.id, `${pool.name} (Senior)`, 1, BigInt(tinlakePool.seniorInterestRate)) + await senior.save() + + const junior = await TrancheService.getOrSeed(pool.id, 'junior', blockchain.id) + await junior.initTinlake(pool.id, `${pool.name} (Junior)`, 0) + await junior.save() + } - for (const tinlakePool of tinlakePools) { - if (block.number >= tinlakePool.startBlock) { - const pool = await PoolService.getOrSeed(tinlakePool.id, false, false, blockchain.id) + //Append navFeed Call for pool + if (latestNavFeed && latestNavFeed.address) { + poolUpdateCalls.push({ + id: pool.id, + type: 'currentNAV', + call: { + target: latestNavFeed.address, + callData: NavfeedAbi__factory.createInterface().encodeFunctionData('currentNAV'), + }, + result: '', + }) + } + //Append totalBalance Call for pool + if (latestReserve && latestReserve.address) { + poolUpdateCalls.push({ + id: pool.id, + type: 'totalBalance', + call: { + target: latestReserve.address, + callData: ReserveAbi__factory.createInterface().encodeFunctionData('totalBalance'), + }, + result: '', + }) + } + } - // initialize new pool - if (!pool.isActive) { - await pool.initTinlake(tinlakePool.shortName, currency.id, date, blockNumber) - await pool.save() + //Execute available calls + const callResults: PoolMulticall[] = await processCalls(poolUpdateCalls).catch((err) => { + logger.error(`poolUpdateCalls failed: ${err}`) + return [] + }) - const senior = await TrancheService.getOrSeed(pool.id, 'senior', blockchain.id) - await senior.initTinlake(pool.id, `${pool.name} (Senior)`, 1, BigInt(tinlakePool.seniorInterestRate)) - await senior.save() + for (const callResult of callResults) { + // const tinlakePool = tinlakePools.find((p) => p.id === callResult.id) + // if (!tinlakePool) throw missingPool + const pool = processedPools.find( p => callResult.id === p.id) + if (!pool) throw missingPool - const junior = await TrancheService.getOrSeed(pool.id, 'junior', blockchain.id) - await junior.initTinlake(pool.id, `${pool.name} (Junior)`, 0) - await junior.save() - } + const tinlakePool = tinlakePools.find((p) => p.id === pool.id) + const latestNavFeed = getLatestContract(tinlakePool!.navFeed, blockNumber) + const latestReserve = getLatestContract(tinlakePool!.navFeed, blockNumber) - const latestNavFeed = getLatestContract(tinlakePool.navFeed, blockNumber) - const latestReserve = getLatestContract(tinlakePool.reserve, blockNumber) - - if (latestNavFeed && latestNavFeed.address) { - poolUpdateCalls.push({ - id: tinlakePool.id, - type: 'currentNAV', - call: { - target: latestNavFeed.address, - callData: NavfeedAbi__factory.createInterface().encodeFunctionData('currentNAV'), - }, - result: '', - }) - } - if (latestReserve && latestReserve.address) { - poolUpdateCalls.push({ - id: tinlakePool.id, - type: 'totalBalance', - call: { - target: latestReserve.address, - callData: ReserveAbi__factory.createInterface().encodeFunctionData('totalBalance'), - }, - result: '', - }) - } - } + // Update pool vurrentNav + if (callResult.type === 'currentNAV' && latestNavFeed) { + const currentNAV = + pool.id === ALT_1_POOL_ID && blockNumber > ALT_1_END_BLOCK + ? BigInt(0) + : NavfeedAbi__factory.createInterface().decodeFunctionResult('currentNAV', callResult.result)[0].toBigInt() + pool.portfolioValuation = currentNAV + pool.netAssetValue = + pool.id === ALT_1_POOL_ID && blockNumber > ALT_1_END_BLOCK + ? BigInt(0) + : (pool.portfolioValuation ?? BigInt(0)) + (pool.totalReserve ?? BigInt(0)) + await pool.updateNormalizedNAV() + await pool.save() + logger.info(`Updating pool ${pool.id} with portfolioValuation: ${pool.portfolioValuation}`) } - if (poolUpdateCalls.length > 0) { - const callResults = await processCalls(poolUpdateCalls) - for (const callResult of callResults) { - const tinlakePool = tinlakePools.find((p) => p.id === callResult.id) - if (!tinlakePool) throw missingPool - const latestNavFeed = getLatestContract(tinlakePool.navFeed, blockNumber) - const latestReserve = getLatestContract(tinlakePool.reserve, blockNumber) - const pool = await PoolService.getOrSeed(tinlakePool.id, false, false, blockchain.id) - - // Update pool - if (callResult.type === 'currentNAV' && latestNavFeed) { - const currentNAV = - tinlakePool.id === ALT_1_POOL_ID && blockNumber > ALT_1_END_BLOCK - ? BigInt(0) - : NavfeedAbi__factory.createInterface() - .decodeFunctionResult('currentNAV', callResult.result)[0] - .toBigInt() - pool.portfolioValuation = currentNAV - pool.netAssetValue = - tinlakePool.id === ALT_1_POOL_ID && blockNumber > ALT_1_END_BLOCK - ? BigInt(0) - : (pool.portfolioValuation ?? BigInt(0)) + (pool.totalReserve ?? BigInt(0)) - await pool.updateNormalizedNAV() - await pool.save() - logger.info(`Updating pool ${tinlakePool?.id} with portfolioValuation: ${pool.portfolioValuation}`) - } - if (callResult.type === 'totalBalance' && latestReserve) { - const totalBalance = - tinlakePool.id === ALT_1_POOL_ID && blockNumber > ALT_1_END_BLOCK - ? BigInt(0) - : ReserveAbi__factory.createInterface() - .decodeFunctionResult('totalBalance', callResult.result)[0] - .toBigInt() - pool.totalReserve = totalBalance - pool.netAssetValue = (pool.portfolioValuation ?? BigInt(0)) + (pool.totalReserve ?? BigInt(0)) - await pool.updateNormalizedNAV() - await pool.save() - logger.info(`Updating pool ${tinlakePool?.id} with totalReserve: ${pool.totalReserve}`) - } - // Update loans (only index if fully synced) - if (latestNavFeed && latestNavFeed.address && date.toDateString() === new Date().toDateString()) { - await updateLoans( - tinlakePool?.id as string, - date, - blockNumber, - tinlakePool?.shelf[0].address as string, - tinlakePool?.pile[0].address as string, - latestNavFeed.address - ) - } - } + // Update pool reserve + if (callResult.type === 'totalBalance' && latestReserve) { + const totalBalance = + pool.id === ALT_1_POOL_ID && blockNumber > ALT_1_END_BLOCK + ? BigInt(0) + : ReserveAbi__factory.createInterface().decodeFunctionResult('totalBalance', callResult.result)[0].toBigInt() + pool.totalReserve = totalBalance + pool.netAssetValue = (pool.portfolioValuation ?? BigInt(0)) + (pool.totalReserve ?? BigInt(0)) + await pool.updateNormalizedNAV() + await pool.save() + logger.info(`Updating pool ${pool.id} with totalReserve: ${pool.totalReserve}`) } - // Take snapshots - await evmStateSnapshotter( - 'periodId', - snapshotPeriod.id, - Pool, - PoolSnapshot, - block, - [['isActive', '=', true]], - 'poolId' - ) - //await evmStateSnapshotter('Asset', 'AssetSnapshot', block, 'isActive', true, 'assetId') - - //Update tracking of period and continue - await (await timekeeper).update(snapshotPeriod.start) + // Update loans (only index if fully synced) + if (latestNavFeed && latestNavFeed.address && date.toDateString() === new Date().toDateString()) { + await updateLoans( + pool.id, + date, + blockNumber, + tinlakePool!.shelf[0].address, + tinlakePool!.pile[0].address, + latestNavFeed.address + ) + } } + + // Take snapshots + await evmStateSnapshotter( + 'periodId', + snapshotPeriod.id, + Pool, + PoolSnapshot, + block, + [['isActive', '=', true]], + 'poolId' + ) + //await evmStateSnapshotter('Asset', 'AssetSnapshot', block, 'isActive', true, 'assetId') + + //Update tracking of period and continue + await (await timekeeper).update(snapshotPeriod.start) } type NewLoanData = { @@ -181,6 +188,7 @@ async function updateLoans( logger.info(`Found ${newLoans.length} new loans for pool ${poolId}`) const pool = await PoolService.getById(poolId) + if(!pool) throw missingPool const isAlt1AndAfterEndBlock = poolId === ALT_1_POOL_ID && blockNumber > ALT_1_END_BLOCK const nftIdCalls: PoolMulticall[] = [] @@ -197,7 +205,10 @@ async function updateLoans( } if (nftIdCalls.length > 0) { const newLoanData: NewLoanData[] = [] - const nftIdResponses = await processCalls(nftIdCalls) + const nftIdResponses: PoolMulticall[] = await processCalls(nftIdCalls).catch((err) => { + logger.error(`nftIdCalls failed: ${err}`) + return [] + }) for (const response of nftIdResponses) { if (response.result) { const data: NewLoanData = { @@ -229,7 +240,10 @@ async function updateLoans( result: '', }) } - const maturityDateResponses = await processCalls(maturityDateCalls) + const maturityDateResponses: PoolMulticall[] = await processCalls(maturityDateCalls).catch((err) => { + logger.error(`naturityDateCalls failed: ${err}`) + return [] + }) maturityDateResponses.map((response) => { if (response.result) { const loan = newLoanData.find((loan) => loan.id === response.id) @@ -305,7 +319,10 @@ async function updateLoans( }) }) if (loanDetailsCalls.length > 0) { - const loanDetailsResponses = await processCalls(loanDetailsCalls) + const loanDetailsResponses: PoolMulticall[] = await processCalls(loanDetailsCalls).catch((err) => { + logger.error(`loanDetailsCalls failed: ${err}`) + return [] + }) const loanDetails: LoanDetails = {} for (const loanDetailsResponse of loanDetailsResponses) { const loanId = loanDetailsResponse.id @@ -356,7 +373,7 @@ async function updateLoans( loan.outstandingDebt = debt const currentDebt = loan.outstandingDebt ?? BigInt(0) const rateGroup = loanDetails[loanIndex].loanRates - const pileContract = PileAbi__factory.connect(pile, api as unknown as Provider) + const pileContract = PileAbi__factory.connect(pile, api as Provider) if (!rateGroup) throw new Error(`Missing rateGroup for loan ${loan.id}`) const rates = await pileContract.rates(rateGroup) loan.interestRatePerSec = rates.ratePerSecond.toBigInt() @@ -398,7 +415,7 @@ async function updateLoans( async function getNewLoans(existingLoans: number[], shelfAddress: string) { let loanIndex = existingLoans.length || 1 const contractLoans: number[] = [] - const shelfContract = ShelfAbi__factory.connect(shelfAddress, api as unknown as Provider) + const shelfContract = ShelfAbi__factory.connect(shelfAddress, api as Provider) // eslint-disable-next-line while (true) { let response: Awaited> @@ -420,9 +437,7 @@ async function getNewLoans(existingLoans: number[], shelfAddress: string) { } function getLatestContract(contractArray: ContractArray[], blockNumber: number) { - return contractArray.reduce((prev, current: ContractArray) => - current.startBlock <= blockNumber && current.startBlock > (prev?.startBlock ?? 0) ? current : prev - ) + return contractArray.find((entry) => entry.startBlock <= blockNumber) } function chunkArray(array: T[], chunkSize: number): T[][] { @@ -434,11 +449,10 @@ function chunkArray(array: T[], chunkSize: number): T[][] { } async function processCalls(callsArray: PoolMulticall[], chunkSize = 30): Promise { + if (callsArray.length === 0) return [] const callChunks = chunkArray(callsArray, chunkSize) - for (let i = 0; i < callChunks.length; i++) { - const chunk = callChunks[i] - const multicall = MulticallAbi__factory.connect(multicallAddress, api as unknown as Provider) - // eslint-disable-next-line + for (const [i, chunk] of callChunks.entries()) { + const multicall = MulticallAbi__factory.connect(multicallAddress, api as Provider) let results: [BigNumber, string[]] & { blockNumber: BigNumber returnData: string[] @@ -452,7 +466,6 @@ async function processCalls(callsArray: PoolMulticall[], chunkSize = 30): Promis logger.error(`Error fetching chunk ${i}: ${e}`) } } - return callsArray } diff --git a/src/mappings/handlers/evmHandlers.ts b/src/mappings/handlers/evmHandlers.ts index 6ea4f1a6..9a7bf1a8 100644 --- a/src/mappings/handlers/evmHandlers.ts +++ b/src/mappings/handlers/evmHandlers.ts @@ -7,7 +7,7 @@ import { PoolService } from '../services/poolService' import { TrancheService } from '../services/trancheService' import { InvestorTransactionData, InvestorTransactionService } from '../services/investorTransactionService' import { CurrencyService } from '../services/currencyService' -import { BlockchainService, LOCAL_CHAIN_ID } from '../services/blockchainService' +import { BlockchainService } from '../services/blockchainService' import { CurrencyBalanceService } from '../services/currencyBalanceService' import type { Provider } from '@ethersproject/providers' import { TrancheBalanceService } from '../services/trancheBalanceService' @@ -15,7 +15,7 @@ import { escrows } from '../../config' import { InvestorPositionService } from '../services/investorPositionService' import { getPeriodStart } from '../../helpers/timekeeperService' -const _ethApi = api as unknown as Provider +const _ethApi = api as Provider //const networkPromise = typeof ethApi.getNetwork === 'function' ? ethApi.getNetwork() : null export const handleEvmDeployTranche = errorHandler(_handleEvmDeployTranche) @@ -24,7 +24,6 @@ async function _handleEvmDeployTranche(event: DeployTrancheLog): Promise { const [_poolId, _trancheId, tokenAddress] = event.args const poolManagerAddress = event.address - await BlockchainService.getOrInit(LOCAL_CHAIN_ID) const chainId = await getNodeEvmChainId() if (!chainId) throw new Error('Unable to retrieve chainId') const evmBlockchain = await BlockchainService.getOrInit(chainId) @@ -79,6 +78,7 @@ async function _handleEvmTransfer(event: TransferLog): Promise { if (!evmToken.poolId || !evmToken.trancheId) throw new Error('This is not a tranche token') const trancheId = evmToken.trancheId.split('-')[1] const tranche = await TrancheService.getById(evmToken.poolId, trancheId) + if (!tranche) throw new Error('Tranche not found!') const orderData: Omit = { poolId: evmToken.poolId, diff --git a/src/mappings/handlers/investmentsHandlers.ts b/src/mappings/handlers/investmentsHandlers.ts index a8f61e9c..7e1a37bf 100644 --- a/src/mappings/handlers/investmentsHandlers.ts +++ b/src/mappings/handlers/investmentsHandlers.ts @@ -28,6 +28,7 @@ async function _handleInvestOrderUpdated(event: SubstrateEvent) { @@ -114,7 +117,7 @@ async function _handleLoanBorrowed(event: SubstrateEvent): Pr const [poolId, loanId, borrowAmount] = event.event.data const timestamp = event.block.timestamp if (!timestamp) throw new Error(`Block ${event.block.block.header.number.toString()} has no timestamp`) - const specVersion = api.runtimeVersion.specVersion.toNumber() + const specVersion = cfgApi.runtimeVersion.specVersion.toNumber() const pool = await PoolService.getById(poolId.toString()) if (!pool) throw missingPool @@ -132,6 +135,8 @@ async function _handleLoanBorrowed(event: SubstrateEvent): Pr // Update loan amount const asset = await AssetService.getById(poolId.toString(), loanId.toString()) + if (!asset) throw new Error('Unable to retrieve asset!') + await asset.activate() const assetTransactionBaseData = { @@ -193,7 +198,7 @@ async function _handleLoanRepaid(event: SubstrateEvent) { const [poolId, loanId, { principal, interest, unscheduled }] = event.event.data const timestamp = event.block.timestamp if (!timestamp) throw new Error(`Block ${event.block.block.header.number.toString()} has no timestamp`) - const specVersion = api.runtimeVersion.specVersion.toNumber() + const specVersion = cfgApi.runtimeVersion.specVersion.toNumber() const pool = await PoolService.getById(poolId.toString()) if (!pool) throw missingPool @@ -211,6 +216,7 @@ async function _handleLoanRepaid(event: SubstrateEvent) { if (!epoch) throw new Error('Epoch not found!') const asset = await AssetService.getById(poolId.toString(), loanId.toString()) + if (!asset) throw new Error('Unable to retrieve asset!') const assetTransactionBaseData = { poolId: poolId.toString(), assetId: loanId.toString(), @@ -280,6 +286,7 @@ async function _handleLoanWrittenOff(event: SubstrateEvent) logger.info(`Loan writtenoff event for pool: ${poolId.toString()} loanId: ${loanId.toString()}`) const { percentage, penalty } = status const asset = await AssetService.getById(poolId.toString(), loanId.toString()) + if (!asset) throw new Error('Unable to retrieve asset!') await asset.writeOff(percentage.toBigInt(), penalty.toBigInt()) await asset.save() @@ -307,6 +314,7 @@ async function _handleLoanClosed(event: SubstrateEvent) { const account = await AccountService.getOrInit(event.extrinsic.extrinsic.signer.toHex()) const asset = await AssetService.getById(poolId.toString(), loanId.toString()) + if (!asset) throw new Error('Unable to retrieve asset!') await asset.close() await asset.save() @@ -330,7 +338,7 @@ async function _handleLoanClosed(event: SubstrateEvent) { export const handleLoanDebtTransferred = errorHandler(_handleLoanDebtTransferred) async function _handleLoanDebtTransferred(event: SubstrateEvent) { - const specVersion = api.runtimeVersion.specVersion.toNumber() + const specVersion = cfgApi.runtimeVersion.specVersion.toNumber() const [poolId, fromLoanId, toLoanId, _repaidAmount, _borrowAmount] = event.event.data const timestamp = event.block.timestamp @@ -356,7 +364,9 @@ async function _handleLoanDebtTransferred(event: SubstrateEvent const account = await AccountService.getOrInit(event.extrinsic.extrinsic.signer.toHex()) const asset = await AssetService.getById(poolId.toString(), loanId.toString()) + if (!asset) throw new Error('Unable to retrieve asset!') assertPropInitialized(pool, 'currentEpoch', 'number') const epoch = await EpochService.getById(pool.id, pool.currentEpoch!) @@ -656,6 +669,7 @@ async function _handleLoanDebtDecreased(event: SubstrateEvent const account = await AccountService.getOrInit(event.extrinsic.extrinsic.signer.toHex()) const asset = await AssetService.getById(poolId.toString(), loanId.toString()) + if (!asset) throw new Error('Unable to retrieve asset!') assertPropInitialized(pool, 'currentEpoch', 'number') const epoch = await EpochService.getById(pool.id, pool.currentEpoch!) diff --git a/src/mappings/handlers/poolsHandlers.ts b/src/mappings/handlers/poolsHandlers.ts index aef9d296..b65e5eea 100644 --- a/src/mappings/handlers/poolsHandlers.ts +++ b/src/mappings/handlers/poolsHandlers.ts @@ -55,6 +55,8 @@ async function _handlePoolCreated(event: SubstrateEvent): Prom for (const { id: feeId, name } of poolFeesMetadata) { const poolFee = await PoolFeeService.getById(pool.id, feeId.toString(10)) + if (!poolFee) throw new Error('poolFee not found!') + await poolFee.setName(name) await poolFee.save() } diff --git a/src/mappings/services/accountService.test.ts b/src/mappings/services/accountService.test.ts index ff240133..92f06bfd 100644 --- a/src/mappings/services/accountService.test.ts +++ b/src/mappings/services/accountService.test.ts @@ -1,8 +1,11 @@ +import { ApiAt } from '../../@types/gobal' import { AccountService } from './accountService' +const cfgApi = api as ApiAt + global.getNodeEvmChainId = () => Promise.resolve('2030') // eslint-disable-next-line @typescript-eslint/no-explicit-any -api.query['evmChainId'] = { chainId: jest.fn(() => ({ toString: () => '2030' })) } as any +cfgApi.query['evmChainId'] = { chainId: jest.fn(() => ({ toString: () => '2030' })) } as any test('Account is created in database', async () => { const id = 'ABCDE' diff --git a/src/mappings/services/assetCashflowService.ts b/src/mappings/services/assetCashflowService.ts index be284377..457987ca 100644 --- a/src/mappings/services/assetCashflowService.ts +++ b/src/mappings/services/assetCashflowService.ts @@ -1,6 +1,9 @@ +import type { ApiAt } from '../../@types/gobal' import { ExtendedCall } from '../../helpers/types' import { AssetCashflow } from '../../types/models/AssetCashflow' +const cfgApi = api as ApiAt + export class AssetCashflowService extends AssetCashflow { static init(assetId: string, timestamp: Date, principal: bigint, interest: bigint) { const id = `${assetId}-${timestamp.valueOf()}` @@ -9,12 +12,12 @@ export class AssetCashflowService extends AssetCashflow { } static async recordAssetCashflows(_assetId: string) { - const specVersion = api.runtimeVersion.specVersion.toNumber() + const specVersion = cfgApi.runtimeVersion.specVersion.toNumber() if (specVersion < 1103) return const [poolId, assetId] = _assetId.split('-') logger.info(`Recording AssetCashflows for Asset ${_assetId}`) - const apiCall = api.call as ExtendedCall - logger.info(`Calling runtime API loansApi.expectedCashflows(${poolId}, ${assetId})`) + const apiCall = cfgApi.call as ExtendedCall + logger.info(`Calling runtime API loanscfgApi.expectedCashflows(${poolId}, ${assetId})`) const response = await apiCall.loansApi.expectedCashflows(poolId, assetId) logger.info(JSON.stringify(response)) if(!response.isOk) return diff --git a/src/mappings/services/assetService.test.ts b/src/mappings/services/assetService.test.ts index ab8b8356..4d72ca77 100644 --- a/src/mappings/services/assetService.test.ts +++ b/src/mappings/services/assetService.test.ts @@ -1,6 +1,9 @@ +import { ApiAt } from '../../@types/gobal' import { AssetType, AssetValuationMethod } from '../../types' import { AssetService } from './assetService' +const cfgApi = api as ApiAt + const poolId = '1111111111' const loanId = 'ABCD' const nftClassId = BigInt(1) @@ -8,7 +11,7 @@ const nftItemId = BigInt(2) const timestamp = new Date() const metadata = 'AAAAAA' -api.query['uniques'] = { +cfgApi.query['uniques'] = { instanceMetadataOf: jest.fn(() => ({ isNone: false, unwrap: () => ({ data: { toUtf8: () => metadata } }), @@ -41,7 +44,7 @@ describe('Given a new loan, when initialised', () => { test('when the metadata is fetched, then the correct values are set', async () => { await loan.updateItemMetadata() - expect(api.query.uniques.instanceMetadataOf).toHaveBeenCalledWith(nftClassId, nftItemId) + expect(cfgApi.query.uniques.instanceMetadataOf).toHaveBeenCalledWith(nftClassId, nftItemId) expect(loan.metadata).toBe(metadata) }) diff --git a/src/mappings/services/assetService.ts b/src/mappings/services/assetService.ts index 720c618e..9e388c56 100644 --- a/src/mappings/services/assetService.ts +++ b/src/mappings/services/assetService.ts @@ -6,6 +6,9 @@ import { Asset, AssetType, AssetValuationMethod, AssetStatus, AssetSnapshot } fr import { ActiveLoanData } from './poolService' import { cid, readIpfs } from '../../helpers/ipfsFetch' import { assertPropInitialized } from '../../helpers/validation' +import { ApiAt } from '../../@types/gobal' + +const cfgApi = api as ApiAt export const ONCHAIN_CASH_ASSET_ID = '0' export class AssetService extends Asset { @@ -81,7 +84,7 @@ export class AssetService extends Asset { } static async getById(poolId: string, assetId: string) { - const asset = (await this.get(`${poolId}-${assetId}`)) as AssetService + const asset = (await this.get(`${poolId}-${assetId}`)) as AssetService | undefined return asset } @@ -94,7 +97,7 @@ export class AssetService extends Asset { ], { limit: 100 } ) - ).pop() as AssetService + ).pop() as AssetService | undefined return asset } @@ -157,7 +160,7 @@ export class AssetService extends Asset { public async updateActiveAssetData(activeAssetData: ActiveLoanData[keyof ActiveLoanData]) { // Current price was always 0 until spec version 1025 - const specVersion = api.runtimeVersion.specVersion.toNumber() + const specVersion = cfgApi.runtimeVersion.specVersion.toNumber() if (specVersion < 1025) delete activeAssetData.currentPrice // Set all active asset values @@ -184,7 +187,7 @@ export class AssetService extends Asset { `collectionId ${this.collateralNftClassId!.toString()}, ` + `itemId: ${this.collateralNftItemId!.toString()}` ) - const itemMetadata = await api.query.uniques.instanceMetadataOf>( + const itemMetadata = await cfgApi.query.uniques.instanceMetadataOf>( this.collateralNftClassId, this.collateralNftItemId ) @@ -250,7 +253,7 @@ export class AssetService extends Asset { public async updateExternalAssetPricingFromState() { logger.info(`Executing state call loans.activeLoans to update asset ${this.id} pricing information`) - const loansCall = await api.query.loans.activeLoans(this.poolId) + const loansCall = await cfgApi.query.loans.activeLoans(this.poolId) const assetTuple = loansCall.find((tuple) => tuple[0].toString(10) === this.id.split('-')[1]) if (!assetTuple) throw new Error(`Asset ${this.id} not found in pool active loans!`) const loanData = assetTuple[1] diff --git a/src/mappings/services/currencyBalanceService.ts b/src/mappings/services/currencyBalanceService.ts index 89439814..332a8625 100644 --- a/src/mappings/services/currencyBalanceService.ts +++ b/src/mappings/services/currencyBalanceService.ts @@ -1,7 +1,10 @@ +import { ApiAt } from '../../@types/gobal' import { AccountData } from '../../helpers/types' import { CurrencyBalance } from '../../types/models/CurrencyBalance' import { formatEnumPayload } from './currencyService' +const cfgApi = api as ApiAt + export class CurrencyBalanceService extends CurrencyBalance { static init(address: string, currency: string) { logger.info(`Initialising new CurrencyBalance: ${address}-${currency} to 0`) @@ -27,7 +30,7 @@ export class CurrencyBalanceService extends CurrencyBalance { public async getBalance() { const [_chainId, currencyType, ...currencySpec] = this.currencyId.split('-') const enumPayload = formatEnumPayload(currencyType, ...currencySpec) - const balanceResponse = await api.query.ormlTokens.accounts(this.accountId, enumPayload) + const balanceResponse = await cfgApi.query.ormlTokens.accounts(this.accountId, enumPayload) this.amount = balanceResponse.free.toBigInt() logger.info(`Fetched initial balance of for CurrencyBalance ${this.id} of ${this.amount.toString(10)}`) } diff --git a/src/mappings/services/currencyService.test.ts b/src/mappings/services/currencyService.test.ts index 21d0f066..be815990 100644 --- a/src/mappings/services/currencyService.test.ts +++ b/src/mappings/services/currencyService.test.ts @@ -1,9 +1,11 @@ +import { ApiAt } from '../../@types/gobal' import { CurrencyService } from './currencyService' +const cfgApi = api as ApiAt const entityName = 'Currency' // eslint-disable-next-line @typescript-eslint/no-explicit-any -api.query['ormlAssetRegistry'] = { metadata: jest.fn(() => ({ isSome: false })) } as any +cfgApi.query['ormlAssetRegistry'] = { metadata: jest.fn(() => ({ isSome: false })) } as any const stdDecimals = 18 diff --git a/src/mappings/services/currencyService.ts b/src/mappings/services/currencyService.ts index d58bd645..7a4bbc69 100644 --- a/src/mappings/services/currencyService.ts +++ b/src/mappings/services/currencyService.ts @@ -3,6 +3,9 @@ import { AssetMetadata } from '@polkadot/types/interfaces' import { Currency } from '../../types/models/Currency' import { WAD_DIGITS } from '../../config' import type { TokensCurrencyId } from '../../helpers/types' +import { ApiAt } from '../../@types/gobal' + +const cfgApi = api as ApiAt export class CurrencyService extends Currency { static init(chainId: string, currencyId: string, decimals: number, symbol?: string, name?: string) { @@ -20,7 +23,7 @@ export class CurrencyService extends Currency { let currency: CurrencyService = (await this.get(id)) as CurrencyService if (!currency) { const enumPayload = formatEnumPayload(currencyType, ...currencyValue) - const assetMetadata = (await api.query.ormlAssetRegistry.metadata(enumPayload)) as Option + const assetMetadata = (await cfgApi.query.ormlAssetRegistry.metadata(enumPayload)) as Option const decimals = assetMetadata.isSome ? assetMetadata.unwrap().decimals.toNumber() : WAD_DIGITS const symbol = assetMetadata.isSome ? assetMetadata.unwrap().symbol.toUtf8() : undefined const name = assetMetadata.isSome ? assetMetadata.unwrap().name.toUtf8() : undefined diff --git a/src/mappings/services/epochService.ts b/src/mappings/services/epochService.ts index 31c3ebac..7b499b8e 100644 --- a/src/mappings/services/epochService.ts +++ b/src/mappings/services/epochService.ts @@ -5,6 +5,9 @@ import { WAD } from '../../config' import { OrdersFulfillment } from '../../helpers/types' import { Epoch, EpochState } from '../../types' import { assertPropInitialized } from '../../helpers/validation' +import { ApiAt } from '../../@types/gobal' + +const cfgApi = api as ApiAt export class EpochService extends Epoch { private states: EpochState[] @@ -73,16 +76,16 @@ export class EpochService extends Epoch { logger.info(`Fetching data for tranche: ${epochState.trancheId}`) const trancheCurrency = [this.poolId, epochState.trancheId] const [investOrderId, redeemOrderId] = await Promise.all([ - api.query.investments.investOrderId(trancheCurrency), - api.query.investments.redeemOrderId(trancheCurrency), + cfgApi.query.investments.investOrderId(trancheCurrency), + cfgApi.query.investments.redeemOrderId(trancheCurrency), ]) logger.info(`investOrderId: ${investOrderId.toNumber()}, redeemOrderId: ${redeemOrderId.toNumber()}`) const [investOrderFulfillment, redeemOrderFulfillment] = await Promise.all([ - api.query.investments.clearedInvestOrders>( + cfgApi.query.investments.clearedInvestOrders>( trancheCurrency, investOrderId.toNumber() - 1 ), - api.query.investments.clearedRedeemOrders>( + cfgApi.query.investments.clearedRedeemOrders>( trancheCurrency, redeemOrderId.toNumber() - 1 ), @@ -105,7 +108,7 @@ export class EpochService extends Epoch { ) epochState.sumFulfilledRedeemOrdersCurrency = this.computeCurrencyAmount( epochState.sumFulfilledRedeemOrders, - epochState.tokenPrice + epochState.tokenPrice! ) assertPropInitialized(this, 'sumInvestedAmount', 'bigint') this.sumInvestedAmount! += epochState.sumFulfilledInvestOrders diff --git a/src/mappings/services/poolFeeService.ts b/src/mappings/services/poolFeeService.ts index a09ac3f1..0fbfe8f0 100644 --- a/src/mappings/services/poolFeeService.ts +++ b/src/mappings/services/poolFeeService.ts @@ -40,7 +40,7 @@ export class PoolFeeService extends PoolFee { blockchain = '0' ) { const { poolId, feeId } = data - let poolFee = (await this.get(`${poolId}-${feeId}`)) as PoolFeeService + let poolFee = (await this.get(`${poolId}-${feeId}`)) as PoolFeeService | undefined if (!poolFee) { poolFee = this.init(data, type, status, blockchain) } else { @@ -50,7 +50,7 @@ export class PoolFeeService extends PoolFee { } static getById(poolId: string, feeId: string) { - return this.get(`${poolId}-${feeId}`) as Promise + return this.get(`${poolId}-${feeId}`) as Promise } static async propose(data: PoolFeeData, type: keyof typeof PoolFeeType) { diff --git a/src/mappings/services/poolService.test.ts b/src/mappings/services/poolService.test.ts index a9d7b5bd..1beb35f2 100644 --- a/src/mappings/services/poolService.test.ts +++ b/src/mappings/services/poolService.test.ts @@ -1,6 +1,8 @@ +import { ApiAt } from '../../@types/gobal' import { PoolService } from './poolService' +const cfgApi = api as ApiAt -api.query['poolSystem'] = { +cfgApi.query['poolSystem'] = { pool: jest.fn(() => ({ isSome: true, isNone: false, @@ -21,7 +23,7 @@ api.query['poolSystem'] = { // eslint-disable-next-line @typescript-eslint/no-explicit-any } as any -api.query['poolRegistry'] = { +cfgApi.query['poolRegistry'] = { poolMetadata: jest.fn(() => ({ isSome: true, isNone: false, @@ -30,7 +32,7 @@ api.query['poolRegistry'] = { // eslint-disable-next-line @typescript-eslint/no-explicit-any } as any -api.query['loans'] = { +cfgApi.query['loans'] = { portfolioValuation: jest.fn(() => ({ value: { toBigInt: () => BigInt(100000000000000), @@ -69,7 +71,7 @@ describe('Given a new pool, when initialised', () => { test('when the pool data is initialised, then the correct values are fetched and set', async () => { await pool.initData() - expect(api.query.poolSystem.pool).toBeCalledWith(poolId) + expect(cfgApi.query.poolSystem.pool).toBeCalledWith(poolId) expect(pool).toMatchObject({ currencyId: 'AUSD', metadata: 'AAA', @@ -87,13 +89,13 @@ describe('Given a new pool, when initialised', () => { describe('Given an existing pool,', () => { test.skip('when the nav is updated, then the value is fetched and set correctly', async () => { await pool.updateNAV() - expect(api.query.loans.portfolioValuation).toHaveBeenCalled() + expect(cfgApi.query.loans.portfolioValuation).toHaveBeenCalled() expect(pool.portfolioValuation).toBe(BigInt(100000000000000)) }) test('when the pool state is updated, then the values are fetched and set correctly', async () => { await pool.updateState() - expect(api.query.poolSystem.pool).toHaveBeenCalledWith(poolId) + expect(cfgApi.query.poolSystem.pool).toHaveBeenCalledWith(poolId) expect(pool).toMatchObject({ totalReserve: BigInt(91000000000000), availableReserve: BigInt(92000000000000), diff --git a/src/mappings/services/poolService.ts b/src/mappings/services/poolService.ts index 3afab14e..72707239 100644 --- a/src/mappings/services/poolService.ts +++ b/src/mappings/services/poolService.ts @@ -16,6 +16,9 @@ import { EpochService } from './epochService' import { WAD_DIGITS } from '../../config' import { CurrencyService } from './currencyService' import { assertPropInitialized } from '../../helpers/validation' +import { ApiAt } from '../../@types/gobal' + +const cfgApi = api as ApiAt export class PoolService extends Pool { static seed(poolId: string, blockchain = '0') { @@ -134,8 +137,8 @@ export class PoolService extends Pool { public async initData() { logger.info(`Initialising data for pool: ${this.id}`) const [poolReq, metadataReq] = await Promise.all([ - api.query.poolSystem.pool>(this.id), - api.query.poolRegistry.poolMetadata>(this.id), + cfgApi.query.poolSystem.pool>(this.id), + cfgApi.query.poolRegistry.poolMetadata>(this.id), ]) if (poolReq.isNone) throw new Error('No pool data available to create the pool') @@ -186,7 +189,7 @@ export class PoolService extends Pool { } static async getById(poolId: string) { - return this.get(poolId) as Promise + return this.get(poolId) as Promise } static async getAll() { @@ -204,7 +207,7 @@ export class PoolService extends Pool { } public async updateState() { - const poolResponse = await api.query.poolSystem.pool>(this.id) + const poolResponse = await cfgApi.query.poolSystem.pool>(this.id) logger.info(`Updating state for pool: ${this.id}`) if (poolResponse.isSome) { const poolData = poolResponse.unwrap() @@ -216,8 +219,8 @@ export class PoolService extends Pool { } public async updateNAV() { - const specVersion = api.runtimeVersion.specVersion.toNumber() - const specName = api.runtimeVersion.specName.toString() + const specVersion = cfgApi.runtimeVersion.specVersion.toNumber() + const specName = cfgApi.runtimeVersion.specName.toString() switch (specName) { case 'centrifuge-devel': await (specVersion < 1038 ? this.updateNAVQuery() : this.updateNAVCall()) @@ -236,7 +239,7 @@ export class PoolService extends Pool { assertPropInitialized(this, 'portfolioValuation', 'bigint') assertPropInitialized(this, 'totalReserve', 'bigint') - const navResponse = await api.query.loans.portfolioValuation(this.id) + const navResponse = await cfgApi.query.loans.portfolioValuation(this.id) const newPortfolioValuation = navResponse.value.toBigInt() - this.offchainCashValue! this.deltaPortfolioValuationByPeriod = newPortfolioValuation - this.portfolioValuation! @@ -396,7 +399,7 @@ export class PoolService extends Pool { public async fetchTranchesFrom1400(): Promise { logger.info(`Fetching tranches for pool: ${this.id} with specVersion >= 1400`) - const poolResponse = await api.query.poolSystem.pool>(this.id) + const poolResponse = await cfgApi.query.poolSystem.pool>(this.id) if (poolResponse.isNone) throw new Error('Unable to fetch pool data!') const poolData = poolResponse.unwrap() const { ids, tranches } = poolData.tranches @@ -428,7 +431,7 @@ export class PoolService extends Pool { public async fetchTranchesBefore1400(): Promise { logger.info(`Fetching tranches for pool: ${this.id} with specVersion < 1400`) - const poolResponse = await api.query.poolSystem.pool>(this.id) + const poolResponse = await cfgApi.query.poolSystem.pool>(this.id) if (poolResponse.isNone) throw new Error('Unable to fetch pool data!') const poolData = poolResponse.unwrap() const { ids, tranches } = poolData.tranches @@ -459,7 +462,7 @@ export class PoolService extends Pool { } public async getTranches() { - const specVersion = api.runtimeVersion.specVersion.toNumber() + const specVersion = cfgApi.runtimeVersion.specVersion.toNumber() let tranches: TrancheData[] if (specVersion >= 1400) { tranches = await this.fetchTranchesFrom1400() @@ -530,9 +533,9 @@ export class PoolService extends Pool { } public async getAccruedFees() { - const apiCall = api.call as ExtendedCall - const specVersion = api.runtimeVersion.specVersion.toNumber() - const specName = api.runtimeVersion.specName.toString() + const apiCall = cfgApi.call as ExtendedCall + const specVersion = cfgApi.runtimeVersion.specVersion.toNumber() + const specName = cfgApi.runtimeVersion.specName.toString() switch (specName) { case 'centrifuge-devel': if (specVersion < 1040) return [] diff --git a/src/mappings/services/trancheService.test.ts b/src/mappings/services/trancheService.test.ts index 5d074054..86818f7a 100644 --- a/src/mappings/services/trancheService.test.ts +++ b/src/mappings/services/trancheService.test.ts @@ -1,16 +1,18 @@ +import { ApiAt } from '../../@types/gobal' import { errorLogger } from '../../helpers/errorHandler' import { ExtendedCall } from '../../helpers/types' import { TrancheService } from './trancheService' +const cfgApi = api as ApiAt -api.query['ormlTokens'] = { +cfgApi.query['ormlTokens'] = { totalIssuance: jest.fn(() => ({ toBigInt: () => BigInt('9999000000000000000000') })), // eslint-disable-next-line @typescript-eslint/no-explicit-any } as any // eslint-disable-next-line @typescript-eslint/no-explicit-any -api['runtimeVersion'] = { specVersion: { toNumber: ()=> 1029 } } as any +cfgApi['runtimeVersion'] = { specVersion: { toNumber: () => 1029 } } as any -api.call['poolsApi'] = { +cfgApi.call['poolsApi'] = { trancheTokenPrices: jest.fn(() => ({ isSome: true, isNone: false, @@ -56,14 +58,14 @@ describe('Given a new tranche, when initialised', () => { test('then reset accumulators are set to 0', () => { const resetAccumulators = Object.getOwnPropertyNames(tranches[0]).filter((prop) => prop.endsWith('ByPeriod')) for (const resetAccumulator of resetAccumulators) { - expect(tranches[0][resetAccumulator as keyof typeof tranches[0]]).toBe(BigInt(0)) - expect(tranches[1][resetAccumulator as keyof typeof tranches[1]]).toBe(BigInt(0)) + expect(tranches[0][resetAccumulator as keyof (typeof tranches)[0]]).toBe(BigInt(0)) + expect(tranches[1][resetAccumulator as keyof (typeof tranches)[1]]).toBe(BigInt(0)) } }) test('when the supply data is fetched, then the correct values are fetched and set', async () => { await tranches[0].updateSupply() - expect(api.query.ormlTokens.totalIssuance).toHaveBeenCalledWith({ Tranche: [poolId, trancheIds[0]] }) + expect(cfgApi.query.ormlTokens.totalIssuance).toHaveBeenCalledWith({ Tranche: [poolId, trancheIds[0]] }) expect(tranches[0]).toMatchObject({ tokenSupply: BigInt('9999000000000000000000') }) }) diff --git a/src/mappings/services/trancheService.ts b/src/mappings/services/trancheService.ts index 80c876b4..1fcdcf8a 100644 --- a/src/mappings/services/trancheService.ts +++ b/src/mappings/services/trancheService.ts @@ -5,6 +5,9 @@ import { WAD } from '../../config' import { ExtendedCall } from '../../helpers/types' import { Tranche, TrancheSnapshot } from '../../types' import { TrancheData } from './poolService' +import { ApiAt } from '../../@types/gobal' + +const cfgApi = api as ApiAt const MAINNET_CHAINID = '0xb3db41421702df9a7fcac62b53ffeac85f7853cc4e689e0b93aeb3db18c09d82' @@ -58,33 +61,33 @@ export class TrancheService extends Tranche { } static async getById(poolId: string, trancheId: string) { - const tranche = (await this.get(`${poolId}-${trancheId}`)) as TrancheService + const tranche = (await this.get(`${poolId}-${trancheId}`)) as TrancheService | undefined return tranche } static async getByPoolId(poolId: string): Promise { - const tranches = await paginatedGetter(this, [['poolId', '=', poolId]]) as TrancheService[] + const tranches = (await paginatedGetter(this, [['poolId', '=', poolId]])) as TrancheService[] return tranches } static async getActivesByPoolId(poolId: string): Promise { - const tranches = await paginatedGetter(this, [ + const tranches = (await paginatedGetter(this, [ ['poolId', '=', poolId], ['isActive', '=', true], - ]) as TrancheService[] + ])) as TrancheService[] return tranches } public async updateSupply() { logger.info(`Updating supply for tranche ${this.id}`) const requestPayload = { Tranche: [this.poolId, this.trancheId] } - const supplyResponse = await api.query.ormlTokens.totalIssuance(requestPayload) + const supplyResponse = await cfgApi.query.ormlTokens.totalIssuance(requestPayload) this.tokenSupply = supplyResponse.toBigInt() return this } public async updatePrice(price: bigint, block?: number) { - const specVersion = api.runtimeVersion.specVersion.toNumber() + const specVersion = cfgApi.runtimeVersion.specVersion.toNumber() if (MAINNET_CHAINID === chainId && !!block) { if (block < 4058350) return this.updatePriceFixDecimalError(price, block) if (specVersion >= 1025 && specVersion < 1029) return await this.updatePriceFixForFees(price) diff --git a/tsconfig.json b/tsconfig.json index 0a06ee28..1c25e74a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,7 +17,7 @@ "smoke-tests/*.ts", "smoke-tests/*.d.ts", "node_modules/@subql/types-core/dist/global.d.ts", - "node_modules/@subql/types/dist/global.d.ts", + //"node_modules/@subql/types/dist/global.d.ts", "smoke-tests/.test.ts" ], "exclude": ["src/api-interfaces/**"], diff --git a/yarn.lock b/yarn.lock index 206d327c..3500994c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2454,17 +2454,17 @@ "@types/node" "*" "@types/node-fetch@^2.6.11": - version "2.6.11" - resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.11.tgz#9b39b78665dae0e82a08f02f4967d62c66f95d24" - integrity sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g== + version "2.6.12" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.12.tgz#8ab5c3ef8330f13100a7479e2cd56d3386830a03" + integrity sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA== dependencies: "@types/node" "*" form-data "^4.0.0" -"@types/node@*", "@types/node@^22.5.5": - version "22.8.4" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.8.4.tgz#ab754f7ac52e1fe74174f761c5b03acaf06da0dc" - integrity sha512-SpNNxkftTJOPk0oN+y2bIqurEXHTA2AOZ3EJDDKeJ5VzkvvORSvmQXGQarcOzWV1ac7DCaPBEdMDxBsM+d8jWw== +"@types/node@*": + version "22.9.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.9.0.tgz#b7f16e5c3384788542c72dc3d561a7ceae2c0365" + integrity sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ== dependencies: undici-types "~6.19.8" @@ -2480,6 +2480,13 @@ dependencies: undici-types "~6.19.2" +"@types/node@^22.5.5": + version "22.8.4" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.8.4.tgz#ab754f7ac52e1fe74174f761c5b03acaf06da0dc" + integrity sha512-SpNNxkftTJOPk0oN+y2bIqurEXHTA2AOZ3EJDDKeJ5VzkvvORSvmQXGQarcOzWV1ac7DCaPBEdMDxBsM+d8jWw== + dependencies: + undici-types "~6.19.8" + "@types/normalize-package-data@^2.4.0": version "2.4.4" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901"