|
1 | | -import { Static, Type } from "@sinclair/typebox"; |
2 | | -import { FastifyInstance } from "fastify"; |
| 1 | +import { Type, type Static } from "@sinclair/typebox"; |
| 2 | +import type { FastifyInstance } from "fastify"; |
3 | 3 | import { StatusCodes } from "http-status-codes"; |
4 | | -import { getWallet } from "../../../utils/cache/getWallet"; |
| 4 | +import type { Hex } from "thirdweb"; |
| 5 | +import { getAccount } from "../../../utils/account"; |
| 6 | +import { |
| 7 | + getChecksumAddress, |
| 8 | + maybeBigInt, |
| 9 | + maybeInt, |
| 10 | +} from "../../../utils/primitiveTypes"; |
| 11 | +import { toTransactionType } from "../../../utils/sdk"; |
| 12 | +import { createCustomError } from "../../middleware/error"; |
5 | 13 | import { standardResponseSchema } from "../../schemas/sharedApiSchemas"; |
6 | 14 | import { walletHeaderSchema } from "../../schemas/wallet"; |
7 | 15 |
|
8 | 16 | const requestBodySchema = Type.Object({ |
9 | 17 | transaction: Type.Object({ |
10 | 18 | to: Type.Optional(Type.String()), |
11 | | - from: Type.Optional(Type.String()), |
12 | 19 | nonce: Type.Optional(Type.String()), |
13 | 20 | gasLimit: Type.Optional(Type.String()), |
14 | 21 | gasPrice: Type.Optional(Type.String()), |
15 | 22 | data: Type.Optional(Type.String()), |
16 | 23 | value: Type.Optional(Type.String()), |
17 | | - chainId: Type.Optional(Type.Number()), |
18 | | - type: Type.Optional(Type.Number()), |
| 24 | + chainId: Type.Optional(Type.Integer()), |
| 25 | + type: Type.Optional(Type.Integer()), |
19 | 26 | accessList: Type.Optional(Type.Any()), |
20 | 27 | maxFeePerGas: Type.Optional(Type.String()), |
21 | 28 | maxPriorityFeePerGas: Type.Optional(Type.String()), |
22 | | - customData: Type.Optional(Type.Record(Type.String(), Type.Any())), |
23 | 29 | ccipReadEnabled: Type.Optional(Type.Boolean()), |
24 | 30 | }), |
25 | 31 | }); |
@@ -52,16 +58,39 @@ export async function signTransaction(fastify: FastifyInstance) { |
52 | 58 | const { "x-backend-wallet-address": walletAddress } = |
53 | 59 | request.headers as Static<typeof walletHeaderSchema>; |
54 | 60 |
|
55 | | - const wallet = await getWallet({ |
| 61 | + const account = await getAccount({ |
56 | 62 | chainId: 1, |
57 | | - walletAddress, |
| 63 | + from: getChecksumAddress(walletAddress), |
58 | 64 | }); |
| 65 | + if (!account.signTransaction) { |
| 66 | + throw createCustomError( |
| 67 | + 'This backend wallet does not support "signTransaction".', |
| 68 | + StatusCodes.BAD_REQUEST, |
| 69 | + "SIGN_TRANSACTION_UNIMPLEMENTED", |
| 70 | + ); |
| 71 | + } |
59 | 72 |
|
60 | | - const signer = await wallet.getSigner(); |
61 | | - const signedMessage = await signer.signTransaction(transaction); |
| 73 | + // @TODO: Assert type to viem TransactionSerializable. |
| 74 | + const serializableTransaction: any = { |
| 75 | + chainId: transaction.chainId, |
| 76 | + to: getChecksumAddress(transaction.to), |
| 77 | + nonce: maybeInt(transaction.nonce), |
| 78 | + gas: maybeBigInt(transaction.gasLimit), |
| 79 | + gasPrice: maybeBigInt(transaction.gasPrice), |
| 80 | + data: transaction.data as Hex | undefined, |
| 81 | + value: maybeBigInt(transaction.value), |
| 82 | + type: transaction.type |
| 83 | + ? toTransactionType(transaction.type) |
| 84 | + : undefined, |
| 85 | + accessList: transaction.accessList, |
| 86 | + maxFeePerGas: maybeBigInt(transaction.maxFeePerGas), |
| 87 | + maxPriorityFeePerGas: maybeBigInt(transaction.maxPriorityFeePerGas), |
| 88 | + ccipReadEnabled: transaction.ccipReadEnabled, |
| 89 | + }; |
| 90 | + const signature = await account.signTransaction(serializableTransaction); |
62 | 91 |
|
63 | 92 | reply.status(StatusCodes.OK).send({ |
64 | | - result: signedMessage, |
| 93 | + result: signature, |
65 | 94 | }); |
66 | 95 | }, |
67 | 96 | }); |
|
0 commit comments