From d2a989ebc82f6dfad43a0515292bce6e1e39d55a Mon Sep 17 00:00:00 2001 From: Phillip Ho Date: Wed, 10 Jan 2024 13:18:27 +0900 Subject: [PATCH] feat: Reset nonces on server start, add endpoint (#366) * feat: Reset nonces on server start * add route --- src/db/wallets/deleteAllWalletNonces.ts | 18 ++++++++ src/server/index.ts | 8 +++- .../routes/backend-wallet/resetNonces.ts | 46 +++++++++++++++++++ src/server/routes/index.ts | 2 + src/server/schemas/wallet/index.ts | 4 +- 5 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 src/db/wallets/deleteAllWalletNonces.ts create mode 100644 src/server/routes/backend-wallet/resetNonces.ts diff --git a/src/db/wallets/deleteAllWalletNonces.ts b/src/db/wallets/deleteAllWalletNonces.ts new file mode 100644 index 000000000..34aa559fe --- /dev/null +++ b/src/db/wallets/deleteAllWalletNonces.ts @@ -0,0 +1,18 @@ +import { PrismaTransaction } from "../../schema/prisma"; +import { getPrismaWithPostgresTx } from "../client"; + +interface DeleteAllWalletNoncesParams { + pgtx?: PrismaTransaction; +} + +/** + * Delete the cached value of all backend wallet nonces. + * This is useful to require all backend wallets to resync their + * nonce on the next txn. + */ +export const deleteAllWalletNonces = async ({ + pgtx, +}: DeleteAllWalletNoncesParams) => { + const prisma = getPrismaWithPostgresTx(pgtx); + await prisma.walletNonce.deleteMany({}); +}; diff --git a/src/server/index.ts b/src/server/index.ts index dadc90d68..864f20add 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -3,6 +3,7 @@ import fastify, { FastifyInstance } from "fastify"; import * as fs from "fs"; import path from "path"; import { URL } from "url"; +import { deleteAllWalletNonces } from "../db/wallets/deleteAllWalletNonces"; import { env } from "../utils/env"; import { logger } from "../utils/logger"; import { withAuth } from "./middleware/auth"; @@ -25,8 +26,12 @@ interface HttpsObject { } const main = async () => { - let httpsObject: HttpsObject | undefined = undefined; + // Reset any server state that is safe to reset. + // This allows the server to start in a predictable state. + await deleteAllWalletNonces({}); + // Enables the server to run on https://localhost:PORT, if ENABLE_HTTPS is provided. + let httpsObject: HttpsObject | undefined = undefined; if (env.ENABLE_HTTPS) { httpsObject = { https: { @@ -37,6 +42,7 @@ const main = async () => { }; } + // Start the server with middleware. const server: FastifyInstance = fastify({ disableRequestLogging: true, ...(env.ENABLE_HTTPS ? httpsObject : {}), diff --git a/src/server/routes/backend-wallet/resetNonces.ts b/src/server/routes/backend-wallet/resetNonces.ts new file mode 100644 index 000000000..2455dd17e --- /dev/null +++ b/src/server/routes/backend-wallet/resetNonces.ts @@ -0,0 +1,46 @@ +import { Static, Type } from "@sinclair/typebox"; +import { FastifyInstance } from "fastify"; +import { StatusCodes } from "http-status-codes"; +import { deleteAllWalletNonces } from "../../../db/wallets/deleteAllWalletNonces"; +import { standardResponseSchema } from "../../schemas/sharedApiSchemas"; + +const responseSchema = Type.Object({ + result: Type.Object({ + status: Type.String(), + }), +}); + +responseSchema.example = { + result: { + status: "success", + }, +}; + +export const resetBackendWalletNonces = async (fastify: FastifyInstance) => { + fastify.route<{ + Reply: Static; + }>({ + method: "POST", + url: "/backend-wallet/reset-nonces", + schema: { + summary: "Reset all nonces", + description: + "Reset nonces for all backend wallets. This is for debugging purposes and does not impact held tokens.", + tags: ["Backend Wallet"], + operationId: "resetNonces", + response: { + ...standardResponseSchema, + [StatusCodes.OK]: responseSchema, + }, + }, + handler: async (req, reply) => { + await deleteAllWalletNonces({}); + + reply.status(StatusCodes.OK).send({ + result: { + status: "success", + }, + }); + }, + }); +}; diff --git a/src/server/routes/index.ts b/src/server/routes/index.ts index 1c41a5013..48453a5cc 100644 --- a/src/server/routes/index.ts +++ b/src/server/routes/index.ts @@ -94,6 +94,7 @@ import { revokeRelayer } from "./relayer/revoke"; // System import { getAllTransactions } from "./backend-wallet/getTransactions"; +import { resetBackendWalletNonces } from "./backend-wallet/resetNonces"; import { sendTransactionBatch } from "./backend-wallet/sendTransactionBatch"; import { withdraw } from "./backend-wallet/withdraw"; import { home } from "./home"; @@ -118,6 +119,7 @@ export const withRoutes = async (fastify: FastifyInstance) => { await fastify.register(signTransaction); await fastify.register(signMessage); await fastify.register(getAllTransactions); + await fastify.register(resetBackendWalletNonces); // Configuration await fastify.register(getWalletsConfiguration); diff --git a/src/server/schemas/wallet/index.ts b/src/server/schemas/wallet/index.ts index 55fab5db4..ed782559f 100644 --- a/src/server/schemas/wallet/index.ts +++ b/src/server/schemas/wallet/index.ts @@ -14,11 +14,11 @@ export const walletAuthSchema = Type.Object({ export const walletParamSchema = Type.Object({ chain: Type.String({ examples: ["mumbai"], - description: "Chain ID name", + description: "Chain name", }), walletAddress: Type.String({ examples: ["0x..."], - description: "Wallet Address", + description: "Backend wallet address", }), });