Skip to content

Commit 066f679

Browse files
refactor: mapping handlers as ES6 modules (#137)
1 parent 29e8ceb commit 066f679

File tree

16 files changed

+572
-554
lines changed

16 files changed

+572
-554
lines changed

src/mappings/bank/balanceChange.ts

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import {CosmosEvent} from "@subql/types-cosmos";
2+
import {NativeBalanceChange} from "../../types";
3+
import {checkBalancesAccount, messageId, parseCoins} from "../utils";
4+
5+
export async function saveNativeBalanceEvent(id: string, address: string, amount: BigInt, denom: string, event: CosmosEvent) {
6+
await checkBalancesAccount(address, event.block.block.header.chainId);
7+
const nativeBalanceChangeEntity = NativeBalanceChange.create({
8+
id,
9+
balanceOffset: amount.valueOf(),
10+
denom,
11+
accountId: address,
12+
eventId: `${messageId(event)}-${event.idx}`,
13+
blockId: event.block.block.id,
14+
transactionId: event.tx.hash,
15+
});
16+
await nativeBalanceChangeEntity.save()
17+
}
18+
19+
export async function handleNativeBalanceDecrement(event: CosmosEvent): Promise<void> {
20+
logger.info(`[handleNativeBalanceDecrement] (tx ${event.tx.hash}): indexing event ${event.idx + 1} / ${event.tx.tx.events.length}`)
21+
logger.debug(`[handleNativeBalanceDecrement] (event.event): ${JSON.stringify(event.event, null, 2)}`)
22+
logger.debug(`[handleNativeBalanceDecrement] (event.log): ${JSON.stringify(event.log, null, 2)}`)
23+
24+
// sample event.event.attributes:
25+
// [
26+
// {"key":"spender","value":"fetch1jv65s3grqf6v6jl3dp4t6c9t9rk99cd85zdctg"},
27+
// {"key":"amount","value":"75462013217046121atestfet"},
28+
// {"key":"spender","value":"fetch1wurz7uwmvchhc8x0yztc7220hxs9jxdjdsrqmn"},
29+
// {"key":"amount","value":"100atestfet"}
30+
// ]
31+
let spendEvents = [];
32+
for (const [i, e] of Object.entries(event.event.attributes)) {
33+
if (e.key !== "spender") {
34+
continue
35+
}
36+
const spender = e.value;
37+
const amountStr = event.event.attributes[parseInt(i) + 1].value;
38+
39+
const coin = parseCoins(amountStr)[0];
40+
const amount = BigInt(0) - BigInt(coin.amount); // save a negative amount for a "spend" event
41+
spendEvents.push({spender: spender, amount: amount, denom: coin.denom})
42+
}
43+
;
44+
45+
for (const [i, spendEvent] of Object.entries(spendEvents)) {
46+
await saveNativeBalanceEvent(`${messageId(event)}-spend-${i}`, spendEvent.spender, spendEvent.amount, spendEvent.denom, event);
47+
}
48+
}
49+
50+
export async function handleNativeBalanceIncrement(event: CosmosEvent): Promise<void> {
51+
logger.info(`[handleNativeBalanceIncrement] (tx ${event.tx.hash}): indexing event ${event.idx + 1} / ${event.tx.tx.events.length}`)
52+
logger.debug(`[handleNativeBalanceIncrement] (event.event): ${JSON.stringify(event.event, null, 2)}`)
53+
logger.debug(`[handleNativeBalanceIncrement] (event.log): ${JSON.stringify(event.log, null, 2)}`)
54+
55+
// sample event.event.attributes:
56+
// [
57+
// {"key":"receiver","value":"fetch1jv65s3grqf6v6jl3dp4t6c9t9rk99cd85zdctg"},
58+
// {"key":"amount","value":"75462013217046121atestfet"},
59+
// {"key":"receiver","value":"fetch1wurz7uwmvchhc8x0yztc7220hxs9jxdjdsrqmn"},
60+
// {"key":"amount","value":"100atestfet"}
61+
// ]
62+
let receiveEvents = [];
63+
for (const [i, e] of Object.entries(event.event.attributes)) {
64+
if (e.key !== "receiver") {
65+
continue
66+
}
67+
const receiver = e.value;
68+
const amountStr = event.event.attributes[parseInt(i) + 1].value;
69+
70+
const coin = parseCoins(amountStr)[0];
71+
const amount = BigInt(coin.amount);
72+
receiveEvents.push({receiver: receiver, amount: amount, denom: coin.denom})
73+
}
74+
;
75+
76+
for (const [i, receiveEvent] of Object.entries(receiveEvents)) {
77+
await saveNativeBalanceEvent(`${messageId(event)}-receive-${i}`, receiveEvent.receiver, receiveEvent.amount, receiveEvent.denom, event);
78+
}
79+
}

src/mappings/bank/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from "./transfer"
2+
export * from "./balanceChange"

src/mappings/bank/transfer.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import {CosmosEvent, CosmosMessage} from "@subql/types-cosmos";
2+
import {NativeTransferMsg} from "../types";
3+
import {messageId} from "../utils";
4+
import {NativeTransfer} from "../../types";
5+
6+
export async function handleNativeTransfer(event: CosmosEvent): Promise<void> {
7+
const msg: CosmosMessage<NativeTransferMsg> = event.msg
8+
logger.info(`[handleNativeTransfer] (tx ${msg.tx.hash}): indexing message ${msg.idx + 1} / ${msg.tx.decodedTx.body.messages.length}`)
9+
logger.debug(`[handleNativeTransfer] (msg.msg): ${JSON.stringify(msg.msg, null, 2)}`)
10+
11+
const fromAddress = msg.msg?.decodedMsg?.fromAddress;
12+
const toAddress = msg.msg?.decodedMsg?.toAddress
13+
const amounts = msg.msg?.decodedMsg?.amount;
14+
15+
if (!fromAddress || !amounts || !toAddress) {
16+
logger.warn(`[handleNativeTransfer] (tx ${event.tx.hash}): cannot index event (event.event): ${JSON.stringify(event.event, null, 2)}`)
17+
return
18+
}
19+
20+
// workaround: assuming one denomination per transfer message
21+
const denom = amounts[0].denom;
22+
const id = messageId(msg);
23+
const transferEntity = NativeTransfer.create({
24+
id,
25+
toAddress,
26+
fromAddress,
27+
amounts,
28+
denom,
29+
messageId: id,
30+
transactionId: msg.tx.hash,
31+
blockId: msg.block.block.id
32+
});
33+
34+
await transferEntity.save();
35+
}

src/mappings/dist/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./rewards";

src/mappings/dist/rewards.ts

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import {CosmosEvent, CosmosMessage} from "@subql/types-cosmos";
2+
import {DistDelegatorClaimMsg} from "../types";
3+
import {messageId, parseCoins} from "../utils";
4+
import {DistDelegatorClaim} from "../../types";
5+
6+
export async function handleDistDelegatorClaim(event: CosmosEvent): Promise<void> {
7+
const msg: CosmosMessage<DistDelegatorClaimMsg> = event.msg;
8+
logger.info(`[handleDistDelegatorClaim] (tx ${msg.tx.hash}): indexing DistDelegatorClaim ${messageId(msg)}`)
9+
logger.debug(`[handleDistDelegatorClaim] (event.msg.msg): ${JSON.stringify(msg.msg, null, 2)}`)
10+
11+
const id = messageId(msg);
12+
const delegatorAddress = msg?.msg?.decodedMsg?.delegatorAddress;
13+
const validatorAddress = msg?.msg?.decodedMsg?.validatorAddress;
14+
15+
if (!delegatorAddress || !validatorAddress) {
16+
logger.warn(`[handleDistDelegatorClaim] (tx ${event.tx.hash}): cannot index event (event.event): ${JSON.stringify(event.event, null, 2)}`)
17+
return
18+
}
19+
20+
const claim = DistDelegatorClaim.create({
21+
id,
22+
delegatorAddress,
23+
validatorAddress,
24+
messageId: id,
25+
transactionId: msg.tx.hash,
26+
blockId: msg.block.block.id,
27+
amount: BigInt(-1),
28+
denom: "",
29+
});
30+
31+
// TODO:
32+
// claim.amount =
33+
// claim.denom =
34+
35+
await claim.save();
36+
}
37+
38+
export async function handleDelegatorWithdrawRewardEvent(event: CosmosEvent): Promise<void> {
39+
logger.debug(`[handleDelegateWithdrawRewardEvent] (event.event): ${JSON.stringify(event.event, null, 2)}`)
40+
logger.debug(`[handleDelegateWithdrawRewardEvent] (event.log): ${JSON.stringify(event.log, null, 2)}`)
41+
42+
const attrs: Record<string, any> = event.event.attributes.reduce((acc, attr) => {
43+
acc[attr.key] = attr.value;
44+
return acc;
45+
}, {});
46+
47+
if (!attrs.amount || !attrs.validator) {
48+
logger.warn(`[handleDelegatorWithdrawRewardEvent] (tx ${event.tx.hash}): cannot index event (event.event): ${JSON.stringify(event.event, null, 2)}`)
49+
return
50+
}
51+
52+
const claims = await DistDelegatorClaim.getByTransactionId(event.tx.hash);
53+
54+
const {amount: amountStr, validator} = attrs as { amount: string, validator: string };
55+
const claim = claims.find((claim) => claim.validatorAddress === validator);
56+
if (typeof (claim) === "undefined") {
57+
// Skip this call as unprocessable and allow indexer to continue.
58+
logger.warn(`[handleDelegateWithdrawRewardEvent] (!SKIPPED!) no claim msgs found in tx: ${event.tx.hash}`);
59+
return;
60+
}
61+
62+
const coins = parseCoins(amountStr);
63+
if (coins.length === 0) {
64+
// Skip this call as unprocessable and allow indexer to continue.
65+
logger.warn(`[handleDelegateWithdrawRewardEvent] (!SKIPPED!) error parsing claim amount: ${amountStr}`);
66+
return;
67+
}
68+
69+
const {amount, denom} = coins[0];
70+
claim.amount = BigInt(amount);
71+
claim.denom = denom;
72+
await claim.save();
73+
}

src/mappings/gov/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./votes"

src/mappings/gov/votes.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import {CosmosEvent, CosmosMessage} from "@subql/types-cosmos";
2+
import {GovProposalVoteMsg} from "../types";
3+
import {messageId} from "../utils";
4+
import {GovProposalVote, GovProposalVoteOption} from "../../types";
5+
6+
export async function handleGovProposalVote(event: CosmosEvent): Promise<void> {
7+
const msg: CosmosMessage<GovProposalVoteMsg> = event.msg;
8+
logger.info(`[handleGovProposalVote] (tx ${msg.tx.hash}): indexing GovProposalVote ${messageId(msg)}`)
9+
logger.debug(`[handleGovProposalVote] (event.msg.msg): ${JSON.stringify(msg.msg, null, 2)}`)
10+
11+
const id = messageId(msg);
12+
const option = msg?.msg?.decodedMsg?.option;
13+
const proposalId = msg?.msg?.decodedMsg?.proposalId, voter = msg?.msg?.decodedMsg?.voter;
14+
15+
if (!option || !proposalId || !voter) {
16+
logger.warn(`[handleGovProposalVote] (tx ${event.tx.hash}): cannot index event (event.event): ${JSON.stringify(event.event, null, 2)}`)
17+
return
18+
}
19+
20+
const vote = GovProposalVote.create({
21+
id,
22+
proposalId: proposalId,
23+
voterAddress: voter,
24+
option: Object.values(GovProposalVoteOption)[option],
25+
messageId: id,
26+
transactionId: msg.tx.hash,
27+
blockId: msg.block.block.id,
28+
});
29+
30+
await vote.save();
31+
}

src/mappings/ibc/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./transfer"

src/mappings/ibc/transfer.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import {CosmosEvent} from "@subql/types-cosmos";
2+
import {IbcTransfer} from "../../types";
3+
import {messageId} from "../utils";
4+
5+
export async function handleIBCTransfer(event: CosmosEvent): Promise<void> {
6+
const msg = event.msg;
7+
logger.info(`[handleIBCTransfer] (tx ${msg.tx.hash}): indexing message ${msg.idx + 1} / ${msg.tx.decodedTx.body.messages.length}`)
8+
logger.debug(`[handleIBCTransfer] (msg.msg): ${JSON.stringify(msg.msg, null, 2)}`)
9+
10+
const decodedMsg = msg.msg.decodedMsg;
11+
const sourcePort = decodedMsg.sourcePort;
12+
const sourceChannel = decodedMsg.sourceChannel;
13+
const tokenAmount = decodedMsg.token?.amount;
14+
const tokenDenom = decodedMsg.token?.denom;
15+
const sender = decodedMsg.sender;
16+
const receiver = decodedMsg.receiver;
17+
18+
if (!sourcePort || !sourceChannel || !tokenAmount || !tokenDenom || !sender || !receiver) {
19+
logger.warn(`[handleIBCTransfer] (tx ${msg.tx.hash}): cannot index message (msg.msg): ${JSON.stringify(msg.msg, null, 2)}`)
20+
return
21+
}
22+
23+
const id = messageId(msg);
24+
const transferEntity = IbcTransfer.create({
25+
id,
26+
toAddress: receiver,
27+
fromAddress: sender,
28+
amount: {amount: tokenAmount, denom: tokenDenom},
29+
denom: tokenDenom,
30+
sourcePort,
31+
sourceChannel,
32+
eventId: `${messageId(event)}-${event.idx}`,
33+
messageId: id,
34+
transactionId: msg.tx.hash,
35+
blockId: msg.block.block.id
36+
});
37+
38+
await transferEntity.save();
39+
}

0 commit comments

Comments
 (0)