diff --git a/src/server/routes/contract/write/write.ts b/src/server/routes/contract/write/write.ts index f58990c30..892458bca 100644 --- a/src/server/routes/contract/write/write.ts +++ b/src/server/routes/contract/write/write.ts @@ -1,8 +1,8 @@ -import { Type, type Static } from "@sinclair/typebox"; +import { type Static, Type } from "@sinclair/typebox"; import type { FastifyInstance } from "fastify"; import { StatusCodes } from "http-status-codes"; import { prepareContractCall, resolveMethod } from "thirdweb"; -import type { AbiFunction } from "thirdweb/utils"; +import { type AbiFunction, parseAbiParams } from "thirdweb/utils"; import { getContractV5 } from "../../../../utils/cache/getContractv5"; import { prettifyError } from "../../../../utils/error"; import { queueTransaction } from "../../../../utils/transaction/queueTransation"; @@ -83,8 +83,13 @@ export async function writeToContract(fastify: FastifyInstance) { // 3. functionName passed as function name + inferred ABI (fetched at encode time) // this is all handled inside the `resolveMethod` function let method: AbiFunction; + let params: Array; try { method = await resolveMethod(functionName)(contract); + params = parseAbiParams( + method.inputs.map((i) => i.type), + args, + ); } catch (e) { throw createCustomError( prettifyError(e), @@ -95,7 +100,7 @@ export async function writeToContract(fastify: FastifyInstance) { const transaction = prepareContractCall({ contract, method, - params: args, + params, ...parseTransactionOverrides(txOverrides), }); diff --git a/test/e2e/tests/write.test.ts b/test/e2e/tests/write.test.ts index bfe72b146..c49e45ac3 100644 --- a/test/e2e/tests/write.test.ts +++ b/test/e2e/tests/write.test.ts @@ -1,6 +1,6 @@ import { beforeAll, describe, expect, test } from "bun:test"; import assert from "node:assert"; -import type { Address } from "thirdweb"; +import { type Address, stringToHex } from "thirdweb"; import { zeroAddress } from "viem"; import type { ApiError } from "../../../sdk/dist/thirdweb-dev-engine.cjs"; import { CONFIG } from "../config"; @@ -69,6 +69,98 @@ describe("Write Tests", () => { expect(writeTransactionStatus.minedAt).toBeDefined(); }); + test.only("Write to a contract with untyped args", async () => { + const res = await engine.deploy.deployNftDrop( + CONFIG.CHAIN.id.toString(), + backendWallet, + { + contractMetadata: { + name: "test token", + platform_fee_basis_points: 0, + platform_fee_recipient: zeroAddress, + symbol: "TT", + trusted_forwarders: [], + seller_fee_basis_points: 0, + fee_recipient: zeroAddress, + }, + }, + ); + + expect(res.result.queueId).toBeDefined(); + assert(res.result.queueId, "queueId must be defined"); + expect(res.result.deployedAddress).toBeDefined(); + const nftDropContractAddress = res.result.deployedAddress; + + if (!nftDropContractAddress) { + throw new Error("nftDropContractAddress must be defined"); + } + + const transactionStatus = await pollTransactionStatus( + engine, + res.result.queueId, + true, + ); + + expect(transactionStatus.minedAt).toBeDefined(); + const writeRes = await engine.contract.write( + CONFIG.CHAIN.id.toString(), + nftDropContractAddress, + backendWallet, + { + functionName: "setApprovalForAll", + args: [ + "0x1234567890123456789012345678901234567890", + "true", // string instead of bool + ], + }, + ); + + expect(writeRes.result.queueId).toBeDefined(); + + const writeTransactionStatus = await pollTransactionStatus( + engine, + writeRes.result.queueId, + true, + ); + + expect(writeTransactionStatus.minedAt).toBeDefined(); + + const writeRes2 = await engine.contract.write( + CONFIG.CHAIN.id.toString(), + nftDropContractAddress, + backendWallet, + { + functionName: "setClaimConditions", + args: [ + // stringified array of structs + JSON.stringify([ + { + startTimestamp: "0", + maxClaimableSupply: "100000", + supplyClaimed: "0", + quantityLimitPerWallet: "10", + merkleRoot: stringToHex("", { size: 32 }), + pricePerToken: "0", + currency: zeroAddress, + metadata: "", + }, + ]), + "false", + ], + }, + ); + + expect(writeRes2.result.queueId).toBeDefined(); + + const writeTransactionStatus2 = await pollTransactionStatus( + engine, + writeRes2.result.queueId, + true, + ); + + expect(writeTransactionStatus2.minedAt).toBeDefined(); + }); + test("Write to a contract with function signature", async () => { const writeRes = await engine.contract.write( CONFIG.CHAIN.id.toString(),