[Blockchain Watcher] (SOLANA) Mapped new attributes in solana redeem (#997)
* Rename and add new attributes * Remove comment * Resolve comment in PR * Run prettier * Resolve solana test * Remove name in method mapper * Run prettier * Improve mapper method * Remove toString in method mapper * Resolve test error * Resolve comment in PR * Resolve comment in PR * Revert name changes --------- Co-authored-by: julian merlo <julianmerlo@julians-MacBook-Pro.local>
This commit is contained in:
parent
13ec7846c0
commit
59c2de9d0c
|
@ -69,3 +69,11 @@ export type TransactionFound = {
|
|||
emitterChain?: number;
|
||||
emitterAddress?: string;
|
||||
};
|
||||
|
||||
export type InstructionFound = {
|
||||
method: string;
|
||||
status: string;
|
||||
emitterChainId: number;
|
||||
emitterAddress: string;
|
||||
sequence: number;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
import { solana } from "../../../domain/entities";
|
||||
|
||||
export const methodNameByInstructionMapper = (
|
||||
instruction: solana.MessageCompiledInstruction,
|
||||
programIdIndex: number
|
||||
): Status => {
|
||||
const data = instruction.data;
|
||||
|
||||
if (!programIdIndex || instruction.programIdIndex != Number(programIdIndex) || data.length == 0) {
|
||||
return {
|
||||
id: MethodID.unknownInstructionID,
|
||||
method: Method.unknownInstruction,
|
||||
};
|
||||
}
|
||||
|
||||
const methodId = data[0];
|
||||
const selectedMethod = methodsMapping[methodId]?.method || Method.unknownInstruction;
|
||||
|
||||
return {
|
||||
id: methodId,
|
||||
method: selectedMethod,
|
||||
};
|
||||
};
|
||||
|
||||
type Status = {
|
||||
id: number;
|
||||
method: string;
|
||||
};
|
||||
|
||||
enum MethodID {
|
||||
completeWrappedInstructionID = 3,
|
||||
completeNativeInstructionID = 2,
|
||||
unknownInstructionID = 0,
|
||||
}
|
||||
|
||||
enum Method {
|
||||
completeWrappedInstruction = "completeWrappedInstruction",
|
||||
completeNativeInstruction = "completeNativeInstruction",
|
||||
unknownInstruction = "unknownInstruction",
|
||||
}
|
||||
|
||||
const methodsMapping: { [key: number]: { method: string } } = {
|
||||
[MethodID.completeWrappedInstructionID]: {
|
||||
method: Method.completeWrappedInstruction,
|
||||
},
|
||||
[MethodID.completeNativeInstructionID]: {
|
||||
method: Method.completeNativeInstruction,
|
||||
},
|
||||
[MethodID.unknownInstructionID]: {
|
||||
method: Method.unknownInstruction,
|
||||
},
|
||||
};
|
|
@ -1,9 +1,10 @@
|
|||
import { decode } from "bs58";
|
||||
import { Connection, Commitment } from "@solana/web3.js";
|
||||
import { solana, LogFoundEvent, TransferRedeemed } from "../../../domain/entities";
|
||||
import { solana, TransactionFoundEvent, InstructionFound } from "../../../domain/entities";
|
||||
import { CompiledInstruction, MessageCompiledInstruction } from "../../../domain/entities/solana";
|
||||
import { configuration } from "../../config";
|
||||
import { methodNameByInstructionMapper } from "./methodNameByInstructionMapper";
|
||||
import { Connection, Commitment } from "@solana/web3.js";
|
||||
import { getPostedMessage } from "@certusone/wormhole-sdk/lib/cjs/solana/wormhole";
|
||||
import { configuration } from "../../config";
|
||||
import { decode } from "bs58";
|
||||
|
||||
enum Instruction {
|
||||
CompleteNativeTransfer = 0x02,
|
||||
|
@ -12,12 +13,15 @@ enum Instruction {
|
|||
CompleteWrappedWithPayload = 0x0a,
|
||||
}
|
||||
|
||||
const TRANSACTION_STATUS_COMPLETED = "completed";
|
||||
const TRANSACTION_STATUS_FAILED = "failed";
|
||||
|
||||
const connection = new Connection(configuration.chains.solana.rpcs[0]);
|
||||
|
||||
export const solanaTransferRedeemedMapper = async (
|
||||
tx: solana.Transaction,
|
||||
{ programId, commitment }: { programId: string; commitment?: Commitment }
|
||||
): Promise<LogFoundEvent<TransferRedeemed>[]> => {
|
||||
): Promise<TransactionFoundEvent<InstructionFound>[]> => {
|
||||
if (!tx || !tx.blockTime) {
|
||||
throw new Error(
|
||||
`Block time is missing for tx ${tx?.transaction?.signatures} in slot ${tx?.slot}`
|
||||
|
@ -36,7 +40,7 @@ export const solanaTransferRedeemedMapper = async (
|
|||
.concat(instructions)
|
||||
.filter((i) => i.programIdIndex === programIdIndex);
|
||||
|
||||
const results: LogFoundEvent<TransferRedeemed>[] = [];
|
||||
const results: TransactionFoundEvent<InstructionFound>[] = [];
|
||||
for (const instruction of whInstructions) {
|
||||
if (isNotACompleteTransferInstruction(instruction.data)) {
|
||||
continue;
|
||||
|
@ -45,6 +49,7 @@ export const solanaTransferRedeemedMapper = async (
|
|||
const accountAddress = accountKeys[instruction.accountKeyIndexes[2]];
|
||||
const { message } = await getPostedMessage(connection, accountAddress, commitment);
|
||||
const { sequence, emitterAddress, emitterChain } = message || {};
|
||||
const methods = methodNameByInstructionMapper(instruction, programIdIndex);
|
||||
|
||||
results.push({
|
||||
name: "transfer-redeemed",
|
||||
|
@ -54,6 +59,8 @@ export const solanaTransferRedeemedMapper = async (
|
|||
blockHeight: BigInt(tx.slot.toString()),
|
||||
blockTime: tx.blockTime,
|
||||
attributes: {
|
||||
method: methods.method,
|
||||
status: mappedStatus(tx),
|
||||
emitterChainId: emitterChain,
|
||||
emitterAddress: emitterAddress.toString("hex"),
|
||||
sequence: Number(sequence),
|
||||
|
@ -64,6 +71,11 @@ export const solanaTransferRedeemedMapper = async (
|
|||
return results;
|
||||
};
|
||||
|
||||
const mappedStatus = (tx: solana.Transaction): string => {
|
||||
if (!tx.meta || tx.meta.err) TRANSACTION_STATUS_FAILED;
|
||||
return TRANSACTION_STATUS_COMPLETED;
|
||||
};
|
||||
|
||||
const normalizeCompileInstruction = (
|
||||
instruction: CompiledInstruction | MessageCompiledInstruction
|
||||
): MessageCompiledInstruction => {
|
||||
|
|
|
@ -145,6 +145,8 @@ describe("solanaTransferRedeemedMapper", () => {
|
|||
expect(events[0].txHash).toBe(tx.transaction.signatures[0]);
|
||||
expect(events[0].blockHeight).toBe(BigInt(tx.slot));
|
||||
expect(events[0].blockTime).toBe(tx.blockTime);
|
||||
expect(events[0].attributes.method).toBe("completeWrappedInstruction");
|
||||
expect(events[0].attributes.status).toBe("completed");
|
||||
});
|
||||
|
||||
it("should map a tx involving token bridge relayer (aka connect) to a transfer-redeemed event", async () => {
|
||||
|
@ -352,5 +354,7 @@ describe("solanaTransferRedeemedMapper", () => {
|
|||
expect(events[0].txHash).toBe(tx.transaction.signatures[0]);
|
||||
expect(events[0].blockHeight).toBe(BigInt(tx.slot));
|
||||
expect(events[0].blockTime).toBe(tx.blockTime);
|
||||
expect(events[0].attributes.method).toBe("unknownInstruction");
|
||||
expect(events[0].attributes.status).toBe("completed");
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue