From 0de44ad800bf0bf4ec469ac8f12695b05a3e5d70 Mon Sep 17 00:00:00 2001 From: Prithvish Baidya Date: Tue, 28 Jan 2025 01:30:35 +0530 Subject: [PATCH 1/2] authorization list support on send-transaction --- src/server/middleware/error.ts | 7 +++++ .../routes/backend-wallet/send-transaction.ts | 9 +++++- .../schemas/transaction/authorization.ts | 30 +++++++++++++++++++ src/shared/utils/primitive-types.ts | 9 ++++++ src/shared/utils/transaction/types.ts | 9 +++++- 5 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 src/server/schemas/transaction/authorization.ts diff --git a/src/server/middleware/error.ts b/src/server/middleware/error.ts index 92dbf8200..7b61b4ca5 100644 --- a/src/server/middleware/error.ts +++ b/src/server/middleware/error.ts @@ -42,6 +42,13 @@ export const badChainError = (chain: string | number): CustomError => "INVALID_CHAIN", ); +export const badBigIntError = (variableName: string): CustomError => + createCustomError( + `Invalid BigInt: ${variableName}`, + StatusCodes.BAD_REQUEST, + "INVALID_BIGINT", + ); + const flipObject = (data: object) => Object.fromEntries(Object.entries(data).map(([key, value]) => [value, key])); diff --git a/src/server/routes/backend-wallet/send-transaction.ts b/src/server/routes/backend-wallet/send-transaction.ts index 13e2a8f3a..3d7833386 100644 --- a/src/server/routes/backend-wallet/send-transaction.ts +++ b/src/server/routes/backend-wallet/send-transaction.ts @@ -17,6 +17,10 @@ import { } from "../../schemas/wallet"; import { getChainIdFromChain } from "../../utils/chain"; import { parseTransactionOverrides } from "../../utils/transaction-overrides"; +import { + authorizationListSchema, + toParsedAuthorization, +} from "../../schemas/transaction/authorization"; const requestBodySchema = Type.Object({ toAddress: Type.Optional(AddressSchema), @@ -26,6 +30,7 @@ const requestBodySchema = Type.Object({ value: Type.String({ examples: ["10000000"], }), + authorizationList: authorizationListSchema, ...txOverridesSchema.properties, }); @@ -65,7 +70,8 @@ export async function sendTransaction(fastify: FastifyInstance) { }, handler: async (request, reply) => { const { chain } = request.params; - const { toAddress, data, value, txOverrides } = request.body; + const { toAddress, data, value, txOverrides, authorizationList } = + request.body; const { simulateTx } = request.query; const { "x-backend-wallet-address": fromAddress, @@ -110,6 +116,7 @@ export async function sendTransaction(fastify: FastifyInstance) { data: data as Hex, transactionMode: transactionMode, value: BigInt(value), + authorizationList: authorizationList?.map(toParsedAuthorization), ...parseTransactionOverrides(txOverrides), }, shouldSimulate: simulateTx, diff --git a/src/server/schemas/transaction/authorization.ts b/src/server/schemas/transaction/authorization.ts new file mode 100644 index 000000000..3f6e99537 --- /dev/null +++ b/src/server/schemas/transaction/authorization.ts @@ -0,0 +1,30 @@ +import { type Static, Type } from "@sinclair/typebox"; +import { AddressSchema } from "../address"; +import { requiredAddress } from "../wallet"; +import { requiredBigInt } from "../../../shared/utils/primitive-types"; + +export const authorizationSchema = Type.Object({ + address: AddressSchema, + chainId: Type.Integer(), + nonce: Type.String(), + r: Type.String(), + s: Type.String(), + yParity: Type.Number(), +}); + +export const authorizationListSchema = Type.Optional( + Type.Array(authorizationSchema), +); + +export const toParsedAuthorization = ( + authorization: Static, +) => { + return { + address: requiredAddress(authorization.address, "[Authorization List]"), + chainId: authorization.chainId, + nonce: requiredBigInt(authorization.nonce, "[Authorization List] -> nonce"), + r: requiredBigInt(authorization.r, "[Authorization List] -> r"), + s: requiredBigInt(authorization.s, "[Authorization List] -> s"), + yParity: authorization.yParity, + }; +}; diff --git a/src/shared/utils/primitive-types.ts b/src/shared/utils/primitive-types.ts index 759902bc2..5f7f30cc6 100644 --- a/src/shared/utils/primitive-types.ts +++ b/src/shared/utils/primitive-types.ts @@ -1,10 +1,19 @@ import type { Address } from "thirdweb"; import { checksumAddress } from "thirdweb/utils"; +import { badBigIntError } from "../../server/middleware/error"; export const maybeBigInt = (val?: string) => (val ? BigInt(val) : undefined); export const maybeInt = (val?: string) => val ? Number.parseInt(val) : undefined; +export function requiredBigInt(val: string, variableName: string) { + try { + return BigInt(val); + } catch { + throw badBigIntError(variableName); + } +} + // These overloads hint TS at the response type (ex: Address if `val` is Address). export function normalizeAddress(val: Address): Address; export function normalizeAddress(val?: Address): Address | undefined; diff --git a/src/shared/utils/transaction/types.ts b/src/shared/utils/transaction/types.ts index 6b28b88d3..920e23f4d 100644 --- a/src/shared/utils/transaction/types.ts +++ b/src/shared/utils/transaction/types.ts @@ -1,4 +1,10 @@ -import type { Address, Hex, toSerializableTransaction } from "thirdweb"; +import { + signAuthorization, + SignedAuthorization, + type Address, + type Hex, + type toSerializableTransaction, +} from "thirdweb"; import type { TransactionType } from "viem"; // TODO: Replace with thirdweb SDK exported type when available. @@ -30,6 +36,7 @@ export type InsertedTransaction = { value?: bigint; data?: Hex; + authorizationList?: SignedAuthorization[]; functionName?: string; functionArgs?: unknown[]; From 1f3f48136f5843ae6b3ab5109795c3a773097d78 Mon Sep 17 00:00:00 2001 From: Prithvish Baidya Date: Tue, 28 Jan 2025 02:01:05 +0530 Subject: [PATCH 2/2] fix: clean up unused imports in transaction overrides utility and update yarn.lock for dependency management --- src/server/utils/transaction-overrides.ts | 3 +-- yarn.lock | 16 ++-------------- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/src/server/utils/transaction-overrides.ts b/src/server/utils/transaction-overrides.ts index 443758ef0..06575dc49 100644 --- a/src/server/utils/transaction-overrides.ts +++ b/src/server/utils/transaction-overrides.ts @@ -1,6 +1,5 @@ import type { Static } from "@sinclair/typebox"; import { maybeBigInt } from "../../shared/utils/primitive-types"; -import type { InsertedTransaction } from "../../shared/utils/transaction/types"; import type { txOverridesSchema, txOverridesWithValueSchema, @@ -10,7 +9,7 @@ export const parseTransactionOverrides = ( overrides: | Static["txOverrides"] | Static["txOverrides"], -): Partial => { +) => { if (!overrides) { return {}; } diff --git a/yarn.lock b/yarn.lock index 79a69d912..f1dda428b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2372,7 +2372,7 @@ dependencies: "@noble/hashes" "1.4.0" -"@noble/curves@1.4.2": +"@noble/curves@1.4.2", "@noble/curves@~1.4.0": version "1.4.2" resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.2.tgz#40309198c76ed71bc6dbf7ba24e81ceb4d0d1fe9" integrity sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw== @@ -2386,13 +2386,6 @@ dependencies: "@noble/hashes" "1.6.0" -"@noble/curves@~1.6.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.6.0.tgz#be5296ebcd5a1730fccea4786d420f87abfeb40b" - integrity sha512-TlaHRXDehJuRNR9TfZDNQ45mMEd5dwUwmicsafcIX4SsNiqnCHKjE/1alYPd/lDRVhxdhUAlv8uEhMCI5zjIJQ== - dependencies: - "@noble/hashes" "1.5.0" - "@noble/hashes@1.3.2": version "1.3.2" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" @@ -2403,11 +2396,6 @@ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== -"@noble/hashes@1.5.0", "@noble/hashes@~1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.5.0.tgz#abadc5ca20332db2b1b2aa3e496e9af1213570b0" - integrity sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA== - "@noble/hashes@1.6.0": version "1.6.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.6.0.tgz#d4bfb516ad6e7b5111c216a5cc7075f4cf19e6c5" @@ -3274,7 +3262,7 @@ resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.2.1.tgz#dd0b2a533063ca612c17aa9ad26424a2ff5aa865" integrity sha512-DGmGtC8Tt63J5GfHgfl5CuAXh96VF/LD8K9Hr/Gv0J2lAoRGlPOMpqMpMbCTOoOJMZCk2Xt+DskdDyn6dEFdzQ== -"@scure/base@~1.1.0", "@scure/base@~1.1.2", "@scure/base@~1.1.6", "@scure/base@~1.1.7": +"@scure/base@~1.1.0", "@scure/base@~1.1.2", "@scure/base@~1.1.6": version "1.1.9" resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.9.tgz#e5e142fbbfe251091f9c5f1dd4c834ac04c3dbd1" integrity sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==