From 63a185a343951814c55abd8a73047206c4ef29eb Mon Sep 17 00:00:00 2001 From: Fraz Arshad Date: Sat, 4 May 2024 10:56:08 +0500 Subject: [PATCH] feat: updated method to get escrow addresses --- package.json | 2 + src/mappings/constants.ts | 3 +- src/mappings/mappingHandlers.ts | 119 +++++--------------------------- src/mappings/utils.ts | 13 ++++ 4 files changed, 33 insertions(+), 104 deletions(-) diff --git a/package.json b/package.json index 7a5bd33e8..4bf154b51 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,8 @@ "dependencies": { "@subql/types-cosmos": "^3.2.3", "@types/node": "^17.0.21", + "bech32": "^2.0.0", + "js-sha256": "^0.11.0", "pino": "^7.8.0", "ts-proto": "^1.112.1", "tslib": "^2.3.1" diff --git a/src/mappings/constants.ts b/src/mappings/constants.ts index 924bfa560..d9b27544c 100644 --- a/src/mappings/constants.ts +++ b/src/mappings/constants.ts @@ -47,5 +47,4 @@ export const RECEPIENT_KEY = b64encode("recipient"); export const SENDER_KEY = b64encode("sender"); export const RECEIVER_KEY = b64encode("receiver"); export const AMOUNT_KEY = b64encode("amount"); -export const TRANSFER_PORT_VALUE = 'transfer'; - +export const TRANSFER_PORT_VALUE = "transfer"; diff --git a/src/mappings/mappingHandlers.ts b/src/mappings/mappingHandlers.ts index 9c073c954..2d7551cf3 100644 --- a/src/mappings/mappingHandlers.ts +++ b/src/mappings/mappingHandlers.ts @@ -29,6 +29,7 @@ import { extractBrand, resolveBrandNamesAndValues, dateToDayKey, + getEscrowAddress, } from "./utils"; import { @@ -65,8 +66,15 @@ BigInt.prototype.toJSON = function () { return this.toString(); }; +async function saveIbcChannel(channelName: string) { + const generatedEscrowAddress = getEscrowAddress(TRANSFER_PORT_VALUE, channelName); + + const channelRecord = new IBCChannel(channelName, channelName, generatedEscrowAddress); + channelRecord.save(); +} + export async function handleIbcSendPacketEvent(cosmosEvent: CosmosEvent): Promise { - const { event, block } = cosmosEvent; + const { event, block, tx } = cosmosEvent; if (event.type != EVENT_TYPES.SEND_PACKET) { logger.warn("Not valid send_packet event."); return; @@ -89,48 +97,12 @@ export async function handleIbcSendPacketEvent(cosmosEvent: CosmosEvent): Promis return; } const { amount, denom, receiver, sender } = JSON.parse(packetDataAttr.value); + const sourceChannel = packetSrcChannelAttr.value; - const txns = block.txs; - const ibcTransaction = txns.find( - (txn) => - txn.events.find( - (event) => - event.type === EVENT_TYPES.MESSAGE && - event.attributes.find( - (attribute) => attribute.key === ACTION_KEY && attribute.value === IBC_MESSAGE_TRANSFER_VALUE, - ), - ) && - txn.events.find( - (event) => - event.type === EVENT_TYPES.IBC_TRANSFER && - event.attributes.find((attribute) => attribute.key === SENDER_KEY)?.value === b64encode(sender) && - event.attributes.find((attribute) => attribute.key === RECEIVER_KEY)?.value === b64encode(receiver), - ), - ); - const transferEvents = ibcTransaction?.events.filter((event) => event.type === EVENT_TYPES.TRANSFER); - const escrowTransaction = transferEvents - ?.reverse() - .find( - (event) => - event.attributes.find((attribute) => attribute.key === SENDER_KEY)?.value === b64encode(sender) && - event.attributes.find((attribute) => attribute.key === AMOUNT_KEY)?.value === b64encode(amount + denom), - ); - const encodedEscrowAddress = escrowTransaction?.attributes.find( - (attribute) => attribute.key === RECEPIENT_KEY, - )?.value; - const escrowAddress = encodedEscrowAddress ? b64decode(encodedEscrowAddress) : null; - - if (!escrowAddress) { - logger.error(`No escrow address found for ${packetSrcChannelAttr.value} at block height ${block.header.height}`); - return; - } - const ibcChannel = await IBCChannel.get(packetSrcChannelAttr.value); - if (ibcChannel && ibcChannel.escrowAddress !== escrowAddress) { - throw new Error(`Escrow address does not match that of ${packetSrcChannelAttr.value}`); - } + saveIbcChannel(sourceChannel); const transferRecord = new IBCTransfer( - `${block.block.id}-${packetSrcChannelAttr.value}`, + tx.hash, block.header.time as any, BigInt(block.header.height), packetSrcChannelAttr.value, @@ -141,19 +113,10 @@ export async function handleIbcSendPacketEvent(cosmosEvent: CosmosEvent): Promis TransferType.SEND, ); transferRecord.save(); - - if (!ibcChannel) { - const channelRecord = new IBCChannel( - packetSrcChannelAttr.value, - packetSrcChannelAttr.value, - escrowAddress, - ); - channelRecord.save(); - } } export async function handleIbcReceivePacketEvent(cosmosEvent: CosmosEvent): Promise { - const { event, block } = cosmosEvent; + const { event, block, tx } = cosmosEvent; if (event.type != EVENT_TYPES.RECEIVE_PACKET) { logger.warn("Not valid recv_packet event."); return; @@ -177,53 +140,15 @@ export async function handleIbcReceivePacketEvent(cosmosEvent: CosmosEvent): Pro return; } const { amount, denom, receiver, sender } = JSON.parse(packetDataAttr.value); + const destinationChannel = packetDstChannelAttr.value; - const txns = block.txs; - const ibcTransaction = txns.find( - (txn) => - txn.events.find( - (event) => - event.type === EVENT_TYPES.MESSAGE && - event.attributes.find( - (attribute) => attribute.key === ACTION_KEY && attribute.value === IBC_MESSAGE_RECEIVE_PACKET_VALUE, - ), - ) && - txn.events.find( - (event) => - event.type === EVENT_TYPES.FUNGIBLE_TOKEN_PACKET && - event.attributes.find((attribute) => attribute.key === SENDER_KEY)?.value === b64encode(sender) && - event.attributes.find((attribute) => attribute.key === RECEIVER_KEY)?.value === b64encode(receiver), - ), - ); - const transferEvents = ibcTransaction?.events.filter((event) => event.type === EVENT_TYPES.TRANSFER); - const [, , denomUnit] = denom.split('/') - const escrowTransaction = transferEvents - ?.reverse() - .find( - (event) => - event.attributes.find((attribute) => attribute.key === RECEPIENT_KEY)?.value === b64encode(receiver) && - event.attributes.find((attribute) => attribute.key === AMOUNT_KEY)?.value === b64encode(amount + denomUnit), - ); - const encodedEscrowAddress = escrowTransaction?.attributes.find( - (attribute) => attribute.key === SENDER_KEY, - )?.value; - const escrowAddress = encodedEscrowAddress ? b64decode(encodedEscrowAddress) : null; - - if (!escrowAddress) { - logger.error(`No escrow address found for ${packetDstChannelAttr.value} at block height ${block.header.height}`); - return; - } - - const ibcChannel = await IBCChannel.get(packetDstChannelAttr.value); - if (ibcChannel && ibcChannel.escrowAddress !== escrowAddress) { - throw new Error(`Escrow address does not match that of ${packetDstChannelAttr.value}`); - } + saveIbcChannel(destinationChannel); const transferRecord = new IBCTransfer( - `${block.block.id}-${packetDstChannelAttr.value}`, + tx.hash, block.header.time as any, BigInt(block.header.height), - packetDstChannelAttr.value, + destinationChannel, sender, receiver, denom, @@ -231,18 +156,8 @@ export async function handleIbcReceivePacketEvent(cosmosEvent: CosmosEvent): Pro TransferType.RECEIVE, ); transferRecord.save(); - - if (!ibcChannel) { - const channelRecord = new IBCChannel( - packetDstChannelAttr.value, - packetDstChannelAttr.value, - escrowAddress, - ); - channelRecord.save(); - } } - export async function handleStateChangeEvent(cosmosEvent: CosmosEvent): Promise { const { event, block } = cosmosEvent; diff --git a/src/mappings/utils.ts b/src/mappings/utils.ts index 07c1d8c63..53b62faf1 100644 --- a/src/mappings/utils.ts +++ b/src/mappings/utils.ts @@ -1,3 +1,6 @@ +import { bech32 } from "bech32"; +import sha256 from "js-sha256"; + export function extractBrand(str: string): string { return str.replace("Alleged: ", "").replace(" brand", ""); } @@ -95,3 +98,13 @@ export function dateToDayKey(timestamp: any): number { const day = date.getUTCDate().toString().padStart(2, "0"); return parseInt(`${year}${month}${day}`); } + +export const getEscrowAddress = (port: string, channel: string) => { + const version = "ics20-1"; + const chainPrefix = "agoric"; + const stringtoSha = Buffer.from([...Buffer.from(version), 0, ...Buffer.from(`${port}/${channel}`)]); + const shaHash = sha256.sha256.array(stringtoSha.toString()); + const bechWords = bech32.toWords(shaHash.slice(0, 20)); + const address = bech32.encode(chainPrefix, bechWords); + return address; +};