From d310b6adc243ea49cc96c086efc7263f484d0fa1 Mon Sep 17 00:00:00 2001 From: Filippo Date: Thu, 29 Aug 2024 10:50:29 +0200 Subject: [PATCH] fix: asset metadata updates (#248) --- chains-cfg/_root.yaml | 7 +++++- schema.graphql | 4 ++-- src/helpers/types.ts | 4 +++- src/index.ts | 1 + src/mappings/handlers/poolsHandlers.ts | 11 ++++++++-- src/mappings/handlers/uniquesHandlers.ts | 27 ++++++++++++++++++++++++ src/mappings/services/assetService.ts | 14 ++++++++++++ src/mappings/services/poolFeeService.ts | 1 + src/mappings/services/poolService.ts | 16 +++++++++++--- 9 files changed, 76 insertions(+), 9 deletions(-) create mode 100644 src/mappings/handlers/uniquesHandlers.ts diff --git a/chains-cfg/_root.yaml b/chains-cfg/_root.yaml index 160ae57d..5944b53a 100644 --- a/chains-cfg/_root.yaml +++ b/chains-cfg/_root.yaml @@ -174,4 +174,9 @@ dataSources: kind: substrate/EventHandler filter: module: oraclePriceFeed - method: Fed \ No newline at end of file + method: Fed + - handler: handleAssetMetadataSet + kind: substrate/EventHandler + filter: + module: uniques + method: MetadataSet \ No newline at end of file diff --git a/schema.graphql b/schema.graphql index 87090873..4e1eaa51 100644 --- a/schema.graphql +++ b/schema.graphql @@ -449,8 +449,8 @@ type Asset @entity { type: AssetType! valuationMethod: AssetValuationMethod! - collateralNftClassId: BigInt - collateralNftItemId: BigInt + collateralNftClassId: BigInt @index + collateralNftItemId: BigInt @index metadata: String name: String diff --git a/src/helpers/types.ts b/src/helpers/types.ts index b2bd49e3..ca6f2b7e 100644 --- a/src/helpers/types.ts +++ b/src/helpers/types.ts @@ -1,6 +1,6 @@ //find out types: const a = createType(api.registry, '[u8;32]', 18) import { AugmentedCall, AugmentedRpc, PromiseRpcResult } from '@polkadot/api/types' -import { Enum, Null, Struct, u128, u32, u64, U8aFixed, Option, Vec, Bytes, Result } from '@polkadot/types' +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' @@ -480,6 +480,8 @@ export type TokensEndowedDepositedWithdrawnEvent = ITuple< [currencyId: TokensCurrencyId, who: AccountId32, amount: u128] > +export type UniquesMetadataSetEvent = ITuple<[collection: u64, item: u128, data: Bytes, isFrozen: bool]> + export type PoolFeesProposedEvent = ITuple<[poolId: u64, feeId: u64, bucket: PoolFeeBucket, fee: PoolFeeInfo]> export type PoolFeesAddedEvent = ITuple<[poolId: u64, bucket: PoolFeeBucket, feeId: u64, fee: PoolFeeInfo]> export type PoolFeesRemovedEvent = ITuple<[poolId: u64, bucket: PoolFeeBucket, feeId: u64]> diff --git a/src/index.ts b/src/index.ts index 9bc6d02f..1949ce2d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -26,3 +26,4 @@ export * from './mappings/handlers/evmHandlers' export * from './mappings/handlers/ethHandlers' export * from './mappings/handlers/poolFeesHandlers' export * from './mappings/handlers/oracleHandlers' +export * from './mappings/handlers/uniquesHandlers' diff --git a/src/mappings/handlers/poolsHandlers.ts b/src/mappings/handlers/poolsHandlers.ts index 8654efbb..e62425dd 100644 --- a/src/mappings/handlers/poolsHandlers.ts +++ b/src/mappings/handlers/poolsHandlers.ts @@ -14,6 +14,7 @@ import { AssetTransactionData, AssetTransactionService } from '../services/asset import { substrateStateSnapshotter } from '../../helpers/stateSnapshot' import { Pool, PoolSnapshot } from '../../types' import { InvestorPositionService } from '../services/investorPositionService' +import { PoolFeeService } from '../services/poolFeeService' export const handlePoolCreated = errorHandler(_handlePoolCreated) async function _handlePoolCreated(event: SubstrateEvent): Promise { @@ -41,10 +42,16 @@ async function _handlePoolCreated(event: SubstrateEvent): Prom event.block.block.header.number.toNumber() ) await pool.initData() - await pool.initIpfsMetadata().catch((err) => { + const poolFeesMetadata = await pool.initIpfsMetadata().catch>((err) => { logger.error(`IPFS Request failed ${err}`) - return Promise.resolve() + return Promise.resolve([]) }) + + for (const { id: feeId, name } of poolFeesMetadata) { + const poolFee = await PoolFeeService.getById(pool.id, feeId.toString(10)) + await poolFee.setName(name) + await poolFee.save() + } await pool.save() // Initialise the tranches diff --git a/src/mappings/handlers/uniquesHandlers.ts b/src/mappings/handlers/uniquesHandlers.ts new file mode 100644 index 00000000..4c1a677d --- /dev/null +++ b/src/mappings/handlers/uniquesHandlers.ts @@ -0,0 +1,27 @@ +import { SubstrateEvent } from '@subql/types' +import { errorHandler } from '../../helpers/errorHandler' +import { UniquesMetadataSetEvent } from '../../helpers/types' +import { AssetService } from '../services/assetService' + +export const handleAssetMetadataSet = errorHandler(_handleAssetMetadataSet) +async function _handleAssetMetadataSet(event: SubstrateEvent) { + const [_collectionId, _itemId, _metadata] = event.event.data + + const collectionId = _collectionId.toString(10) + const itemId = _itemId.toString(10) + const metadata = _metadata.toUtf8() + + logger.info( + `uniques.MetadataSet event fired for ${collectionId}:${itemId}` + + `at block ${event.block.block.header.number.toNumber()}` + ) + + const asset = await AssetService.getByNftId(collectionId, itemId) + if (!asset) return logger.warn('Corresponding asset not found. Maybe not yet initialised? Skipping...') + + logger.info(`Found corresponding asset ${asset.id}`) + + await asset.setMetadata(metadata) + await asset.updateIpfsAssetName() + await asset.save() +} diff --git a/src/mappings/services/assetService.ts b/src/mappings/services/assetService.ts index 3c882dac..fbc6ff21 100644 --- a/src/mappings/services/assetService.ts +++ b/src/mappings/services/assetService.ts @@ -84,6 +84,16 @@ export class AssetService extends Asset { return asset } + static async getByNftId(collectionId: string, itemId: string) { + const asset = ( + await AssetService.getByFields([ + ['collateralNftClassId', '=', collectionId], + ['collateralNftItemId', '=', itemId], + ]) + ).pop() as AssetService + return asset + } + public borrow(amount: bigint) { logger.info(`Increasing borrowings for asset ${this.id} by ${amount}`) this.borrowedAmountByPeriod += amount @@ -176,6 +186,10 @@ export class AssetService extends Asset { return this } + public setMetadata(metadata: string) { + this.metadata = metadata + } + static extractPrincipalAmount(principalObject: LoanPricingAmount) { let principal: bigint switch (principalObject.type) { diff --git a/src/mappings/services/poolFeeService.ts b/src/mappings/services/poolFeeService.ts index 46d0f8cb..48b01292 100644 --- a/src/mappings/services/poolFeeService.ts +++ b/src/mappings/services/poolFeeService.ts @@ -115,6 +115,7 @@ export class PoolFeeService extends PoolFee { } public setName(name: string) { + logger.info(`Setting name for fee ${this.id} to: ${name}`) this.name = name } diff --git a/src/mappings/services/poolService.ts b/src/mappings/services/poolService.ts index 56e93f2e..1c257373 100644 --- a/src/mappings/services/poolService.ts +++ b/src/mappings/services/poolService.ts @@ -147,7 +147,7 @@ export class PoolService extends Pool { this.metadata = metadata } - public async initIpfsMetadata() { + public async initIpfsMetadata(): Promise { if (!this.metadata) { logger.warn('No IPFS metadata') return @@ -157,16 +157,26 @@ export class PoolService extends Pool { this.assetClass = metadata.pool.asset.class this.assetSubclass = metadata.pool.asset.subClass this.icon = metadata.pool.icon.uri + return metadata.pool.poolFees ?? [] } - public async getIpfsPoolFeeName(poolFeeId: string): Promise { + public async getIpfsPoolFeeMetadata(): Promise { if (!this.metadata) return logger.warn('No IPFS metadata') const metadata = await readIpfs(this.metadata.match(cid)[0]) if (!metadata.pool.poolFees) { + return null + } + return metadata.pool.poolFees + } + + public async getIpfsPoolFeeName(poolFeeId: string): Promise { + if (!this.metadata) return logger.warn('No IPFS metadata') + const poolFeeMetadata = await this.getIpfsPoolFeeMetadata() + if (!poolFeeMetadata) { logger.warn('Missing poolFee object in pool metadata!') return null } - return metadata.pool.poolFees.find((elem) => elem.id.toString(10) === poolFeeId)?.name ?? null + return poolFeeMetadata.find((elem) => elem.id.toString(10) === poolFeeId)?.name ?? null } static async getById(poolId: string) {