Skip to content

Commit c59c6c4

Browse files
Add BigNumber transformation utility for typed data signing
Co-authored-by: joaquim.verges <joaquim.verges@gmail.com>
1 parent 067d5da commit c59c6c4

2 files changed

Lines changed: 71 additions & 1 deletion

File tree

src/server/routes/backend-wallet/sign-typed-data.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { arbitrumSepolia } from "thirdweb/chains";
66
import { isSmartBackendWallet } from "../../../shared/db/wallets/get-wallet-details";
77
import { getWalletDetails } from "../../../shared/db/wallets/get-wallet-details";
88
import { walletDetailsToAccount } from "../../../shared/utils/account";
9+
import { transformBigNumbers } from "../../../shared/utils/bignumber";
910
import { getChain } from "../../../shared/utils/chain";
1011
import { createCustomError } from "../../middleware/error";
1112
import { standardResponseSchema } from "../../schemas/shared-api-schemas";
@@ -47,6 +48,9 @@ export async function signTypedData(fastify: FastifyInstance) {
4748
const { "x-backend-wallet-address": walletAddress } =
4849
request.headers as Static<typeof walletHeaderSchema>;
4950

51+
// Transform any BigNumber objects in the value to stringified bigints
52+
const transformedValue = transformBigNumbers(value);
53+
5054
const walletDetails = await getWalletDetails({
5155
address: walletAddress,
5256
});
@@ -79,7 +83,7 @@ export async function signTypedData(fastify: FastifyInstance) {
7983
domain,
8084
types,
8185
primaryType: parsedPrimaryType,
82-
message: value,
86+
message: transformedValue,
8387
} as never);
8488

8589
reply.status(StatusCodes.OK).send({

src/shared/utils/bignumber.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/**
2+
* Utility functions for handling BigNumber objects in payloads
3+
*/
4+
5+
/**
6+
* Interface representing a BigNumber object as it comes from the frontend
7+
*/
8+
interface BigNumberObject {
9+
type: "BigNumber";
10+
hex: string;
11+
}
12+
13+
/**
14+
* Type guard to check if an object is a BigNumber object
15+
*/
16+
function isBigNumberObject(obj: unknown): obj is BigNumberObject {
17+
return (
18+
typeof obj === "object" &&
19+
obj !== null &&
20+
"type" in obj &&
21+
"hex" in obj &&
22+
obj.type === "BigNumber" &&
23+
typeof obj.hex === "string"
24+
);
25+
}
26+
27+
/**
28+
* Converts a BigNumber object to a stringified bigint
29+
*/
30+
function bigNumberToStringifiedBigInt(bigNumberObj: BigNumberObject): string {
31+
// Convert hex string to bigint, then to string
32+
return BigInt(bigNumberObj.hex).toString();
33+
}
34+
35+
/**
36+
* Recursively transforms all BigNumber objects in an arbitrary object/array
37+
* into stringified bigints
38+
*/
39+
export function transformBigNumbers(obj: unknown): unknown {
40+
// Handle null/undefined
41+
if (obj === null || obj === undefined) {
42+
return obj;
43+
}
44+
45+
// Handle BigNumber objects
46+
if (isBigNumberObject(obj)) {
47+
return bigNumberToStringifiedBigInt(obj);
48+
}
49+
50+
// Handle arrays
51+
if (Array.isArray(obj)) {
52+
return obj.map(transformBigNumbers);
53+
}
54+
55+
// Handle objects
56+
if (typeof obj === "object") {
57+
const result: Record<string, unknown> = {};
58+
for (const [key, value] of Object.entries(obj)) {
59+
result[key] = transformBigNumbers(value);
60+
}
61+
return result;
62+
}
63+
64+
// Handle primitives (string, number, boolean, etc.)
65+
return obj;
66+
}

0 commit comments

Comments
 (0)