diff --git a/src/server/routes/backend-wallet/get-balance.ts b/src/server/routes/backend-wallet/get-balance.ts index e569e96d..0bd58866 100644 --- a/src/server/routes/backend-wallet/get-balance.ts +++ b/src/server/routes/backend-wallet/get-balance.ts @@ -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, @@ -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, @@ -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: { diff --git a/src/server/routes/contract/events/get-all-events.ts b/src/server/routes/contract/events/get-all-events.ts index d8777a32..f0df96e8 100644 --- a/src/server/routes/contract/events/get-all-events.ts +++ b/src/server/routes/contract/events/get-all-events.ts @@ -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, @@ -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; @@ -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; + }), }); }, }); diff --git a/src/server/schemas/event.ts b/src/server/schemas/event.ts new file mode 100644 index 00000000..0860726e --- /dev/null +++ b/src/server/schemas/event.ts @@ -0,0 +1,71 @@ +import { BigNumber } from "ethers"; + +export type ContractEventV4 = { + eventName: string; + data: Record; + 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; + 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 = {}; + 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 + }, + }; +} diff --git a/tests/unit/migrationV5.test.ts b/tests/unit/migrationV5.test.ts new file mode 100644 index 00000000..e9d31d5b --- /dev/null +++ b/tests/unit/migrationV5.test.ts @@ -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, + ); + } + }); +});