Skip to content

Commit

Permalink
get-balance and get-all-events migrated to v5 (#816)
Browse files Browse the repository at this point in the history
Signed-off-by: Phillip Ho <[email protected]>
  • Loading branch information
nischitpra authored and arcoraven committed Dec 31, 2024
1 parent d71ba93 commit 2a01cf1
Show file tree
Hide file tree
Showing 4 changed files with 211 additions and 12 deletions.
12 changes: 9 additions & 3 deletions src/server/routes/backend-wallet/get-balance.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { type Static, Type } from "@sinclair/typebox";
import type { FastifyInstance } from "fastify";
import { StatusCodes } from "http-status-codes";
import { getSdk } from "../../../shared/utils/cache/get-sdk";
import { AddressSchema } from "../../schemas/address";
import {
currencyValueSchema,
Expand All @@ -10,6 +9,10 @@ import {
import { walletWithAddressParamSchema } from "../../schemas/wallet";
import { getChainIdFromChain } from "../../utils/chain";

import { getChain } from "../../../shared/utils/chain";
import { thirdwebClient } from "../../../shared/utils/sdk";
import { getWalletBalance } from "thirdweb/wallets";

const responseSchema = Type.Object({
result: Type.Object({
walletAddress: AddressSchema,
Expand Down Expand Up @@ -49,9 +52,12 @@ export async function getBalance(fastify: FastifyInstance) {
handler: async (request, reply) => {
const { chain, walletAddress } = request.params;
const chainId = await getChainIdFromChain(chain);
const sdk = await getSdk({ chainId });

const balanceData = await sdk.getBalance(walletAddress);
const balanceData = await getWalletBalance({
client: thirdwebClient,
address: walletAddress,
chain: await getChain(chainId),
});

reply.status(StatusCodes.OK).send({
result: {
Expand Down
28 changes: 19 additions & 9 deletions src/server/routes/contract/events/get-all-events.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { type Static, Type } from "@sinclair/typebox";
import type { FastifyInstance } from "fastify";
import { StatusCodes } from "http-status-codes";
import { getContract } from "../../../../shared/utils/cache/get-contract";
import {
contractEventSchema,
eventsQuerystringSchema,
Expand All @@ -10,7 +9,12 @@ import {
contractParamSchema,
standardResponseSchema,
} from "../../../schemas/shared-api-schemas";
import { thirdwebClient } from "../../../../shared/utils/sdk";
import { getChain } from "../../../../shared/utils/chain";
import { getChainIdFromChain } from "../../../utils/chain";
import { getContract, getContractEvents } from "thirdweb";
import { maybeBigInt } from "../../../../shared/utils/primitive-types";
import { toContractEventV4Schema } from "../../../schemas/event";

const requestSchema = contractParamSchema;

Expand Down Expand Up @@ -82,19 +86,25 @@ export async function getAllEvents(fastify: FastifyInstance) {
const { fromBlock, toBlock, order } = request.query;

const chainId = await getChainIdFromChain(chain);
const contract = await getContract({
chainId,
contractAddress,

const contract = getContract({
client: thirdwebClient,
address: contractAddress,
chain: await getChain(chainId),
});

const returnData = await contract.events.getAllEvents({
fromBlock,
toBlock,
order,
const eventsV5 = await getContractEvents({
contract: contract,
fromBlock: maybeBigInt(fromBlock?.toString()),
toBlock: maybeBigInt(toBlock?.toString()),
});

reply.status(StatusCodes.OK).send({
result: returnData,
result: eventsV5.map(toContractEventV4Schema).sort((a, b) => {
return order === "desc"
? b.transaction.blockNumber - a.transaction.blockNumber
: a.transaction.blockNumber - b.transaction.blockNumber;
}),
});
},
});
Expand Down
71 changes: 71 additions & 0 deletions src/server/schemas/event.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { BigNumber } from "ethers";

export type ContractEventV4 = {
eventName: string;
data: Record<string, unknown>;
transaction: {
blockNumber: number;
blockHash: string;
transactionIndex: number;
removed: boolean;
address: string;
data: string;
topic: string[];
transactionHash: string;
logIndex: number;
event: string;
eventSignature?: string;
};
};

export type ContractEventV5 = {
eventName: string;
args: Record<string, unknown>;
address: string;
topic: string[];
data: string;
blockNumber: bigint;
transactionHash: string;
transactionIndex: number;
blockHash: string;
logIndex: number;
removed: boolean;
};

/**
* Mapping of events v5 response to v4 for backward compatiblity.
* Clients may be using this api and dont want to break things.
*/
export function toContractEventV4Schema(
eventV5: ContractEventV5,
): ContractEventV4 {
const eventName = eventV5.eventName;

// backwards compatibility of BigInt(v5) to BigNumber(v4)
const data: Record<string, unknown> = {};
for (const key of Object.keys(eventV5.args)) {
let value = eventV5.args[key];
if (typeof value === "bigint") {
value = BigNumber.from(value.toString());
}
data[key] = value;
}

return {
eventName,
data,
transaction: {
blockNumber: Number(eventV5.blockNumber),
blockHash: eventV5.blockHash,
transactionIndex: eventV5.transactionIndex,
removed: eventV5.removed,
address: eventV5.address,
data: eventV5.data,
topic: eventV5.topic,
transactionHash: eventV5.transactionHash,
logIndex: eventV5.logIndex,
event: eventV5.eventName,
// todo: eventV5.eventSignature is not returned so ignoring for now
},
};
}
112 changes: 112 additions & 0 deletions tests/unit/migrationV5.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { describe, expect, it } from "vitest";

import { getSdk } from "../../src/shared/utils/cache/get-sdk";
import { getChain } from "../../src/shared/utils/chain";
import { thirdwebClient } from "../../src/shared/utils/sdk";
import { getWalletBalance } from "thirdweb/wallets";
import { getBalance } from "thirdweb/extensions/erc20";
import { getContractEvents } from "thirdweb";
import { getContract as getContractV5 } from "thirdweb";
import { getContract as getContractV4 } from "../../src/shared/utils/cache/get-contract";
import { maybeBigInt } from "../../src/shared/utils/primitive-types";
import { toContractEventV4Schema } from "../../src/server/schemas/event";

/**
* todo: remove all dependencies including tests after everything is migrated properly.
*/
describe("migration from v4 to v5", () => {
it("get-contract: check difference in contract interface", async () => {
const chainId = 137;
const contractAddress = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174";
const walletAddress = "0xE52772e599b3fa747Af9595266b527A31611cebd";

// v4
const sdk = await getSdk({ chainId });
const contractV4 = await sdk.getContract(contractAddress);
const balV4 = await contractV4.erc20.balanceOf(walletAddress);

/**
* v5
* Doesnt have nested helper functions and is separated into individual "extensions"
*/
const contractV5 = getContractV5({
client: thirdwebClient,
address: contractAddress,
chain: await getChain(chainId),
});
const balV5 = await getBalance({
contract: contractV5,
address: walletAddress,
});

expect(balV4.name).eq(balV5.name);
expect(balV4.symbol).eq(balV5.symbol);
expect(balV4.decimals).eq(balV5.decimals);
expect(balV4.displayValue).eq(balV5.displayValue);
expect(balV4.value.toString()).eq(balV5.value.toString());
});

it("tests for get-balance(native token)", async () => {
const chainId = 137;
const walletAddress = "0xE52772e599b3fa747Af9595266b527A31611cebd";

// v4
const sdk = await getSdk({ chainId });
const balanceV4 = await sdk.getBalance(walletAddress);

// v5.
const balanceV5 = await getWalletBalance({
client: thirdwebClient,
address: walletAddress,
chain: await getChain(chainId),
});

expect(balanceV4.name).eq(balanceV5.name);
expect(balanceV4.symbol).eq(balanceV5.symbol);
expect(balanceV4.decimals).eq(balanceV5.decimals);
expect(balanceV4.displayValue).eq(balanceV5.displayValue);
expect(balanceV4.value.toString()).eq(balanceV5.value.toString());
});

it("tests for events/get-all", async () => {
const chainId = 137;
const contractAddress = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174";
const fromBlock = 65334800;
const toBlock = 65334801;
const order = Math.random() > 0.5 ? "asc" : "desc";

// v4
const contractV4 = await getContractV4({ chainId, contractAddress });
const eventsV4 = await contractV4.events.getAllEvents({
fromBlock,
toBlock,
order,
});

// v5.
const contractV5 = getContractV5({
client: thirdwebClient,
address: contractAddress,
chain: await getChain(chainId),
});
const eventsV5Raw = await getContractEvents({
contract: contractV5,
fromBlock: maybeBigInt(fromBlock?.toString()),
toBlock: maybeBigInt(toBlock?.toString()),
});

const eventsV5 = eventsV5Raw.map(toContractEventV4Schema).sort((a, b) => {
return order === "desc"
? b.transaction.blockNumber - a.transaction.blockNumber
: a.transaction.blockNumber - b.transaction.blockNumber;
});

// check two array ordering is the same
expect(eventsV4.length).eq(eventsV5.length);
for (let i = 0; i < eventsV4.length; i++) {
expect(eventsV4[i].transaction.transactionHash).eq(
eventsV5[i].transaction.transactionHash,
);
}
});
});

0 comments on commit 2a01cf1

Please sign in to comment.