Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 22 additions & 8 deletions src/db/wallets/getWalletDetails.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import LRUMap from "mnemonist/lru-map";
import { getAddress } from "thirdweb";
import { z } from "zod";
import type { PrismaTransaction } from "../../schema/prisma";
Expand All @@ -8,7 +9,7 @@ import { getPrismaWithPostgresTx } from "../client";

interface GetWalletDetailsParams {
pgtx?: PrismaTransaction;
address: string;
walletAddress: string;
}

export class WalletDetailsError extends Error {
Expand Down Expand Up @@ -130,6 +131,8 @@ export type SmartBackendWalletType = (typeof SmartBackendWalletTypes)[number];
export type BackendWalletType = (typeof BackendWalletTypes)[number];
export type ParsedWalletDetails = z.infer<typeof walletDetailsSchema>;

export const walletDetailsCache = new LRUMap<string, ParsedWalletDetails>(2048);

/**
* Return the wallet details for the given address.
*
Expand All @@ -143,20 +146,28 @@ export type ParsedWalletDetails = z.infer<typeof walletDetailsSchema>;
*/
export const getWalletDetails = async ({
pgtx,
address,
walletAddress: _walletAddress,
}: GetWalletDetailsParams) => {
// Wallet details are stored in lowercase.
const walletAddress = _walletAddress.toLowerCase();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ugh would love for all of us to align on lower vs checksum


const cachedDetails = walletDetailsCache.get(walletAddress);
if (cachedDetails) {
return cachedDetails;
}

const prisma = getPrismaWithPostgresTx(pgtx);
const config = await getConfig();

const walletDetails = await prisma.walletDetails.findUnique({
where: {
address: address.toLowerCase(),
address: walletAddress,
},
});

if (!walletDetails) {
throw new WalletDetailsError(
`No wallet details found for address ${address}`,
`No wallet details found for address ${walletAddress}`,
);
}

Expand All @@ -167,7 +178,7 @@ export const getWalletDetails = async ({
) {
if (!walletDetails.awsKmsArn) {
throw new WalletDetailsError(
`AWS KMS ARN is missing for the wallet with address ${address}`,
`AWS KMS ARN is missing for the wallet with address ${walletAddress}`,
);
}

Expand All @@ -188,7 +199,7 @@ export const getWalletDetails = async ({
) {
if (!walletDetails.gcpKmsResourcePath) {
throw new WalletDetailsError(
`GCP KMS resource path is missing for the wallet with address ${address}`,
`GCP KMS resource path is missing for the wallet with address ${walletAddress}`,
);
}

Expand All @@ -209,14 +220,17 @@ export const getWalletDetails = async ({

// zod schema can validate all necessary fields are populated after decryption
try {
return walletDetailsSchema.parse(walletDetails, {
const result = walletDetailsSchema.parse(walletDetails, {
errorMap: (issue) => {
const fieldName = issue.path.join(".");
return {
message: `${fieldName} is necessary for wallet ${address} of type ${walletDetails.type}, but not found in wallet details or configuration`,
message: `${fieldName} is necessary for wallet ${walletAddress} of type ${walletDetails.type}, but not found in wallet details or configuration`,
};
},
});

walletDetailsCache.set(walletAddress, result);
return result;
} catch (e) {
if (e instanceof z.ZodError) {
throw new WalletDetailsError(
Expand Down
2 changes: 1 addition & 1 deletion src/server/routes/backend-wallet/signMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export async function signMessageRoute(fastify: FastifyInstance) {
}

const walletDetails = await getWalletDetails({
address: walletAddress,
walletAddress,
});

if (isSmartBackendWallet(walletDetails) && !chainId) {
Expand Down
12 changes: 3 additions & 9 deletions src/server/routes/backend-wallet/simulateTransaction.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { Type, type Static } from "@sinclair/typebox";
import type { FastifyInstance } from "fastify";
import { StatusCodes } from "http-status-codes";
import { randomUUID } from "node:crypto";
import type { Address, Hex } from "thirdweb";
import { doSimulateTransaction } from "../../../utils/transaction/simulateQueuedTransaction";
import type { QueuedTransaction } from "../../../utils/transaction/types";
import type { InsertedTransaction } from "../../../utils/transaction/types";
import { createCustomError } from "../../middleware/error";
import { AddressSchema } from "../../schemas/address";
import {
Expand Down Expand Up @@ -86,12 +85,7 @@ export async function simulateTransaction(fastify: FastifyInstance) {

const chainId = await getChainIdFromChain(chain);

let queuedTransaction: QueuedTransaction = {
status: "queued",
queueId: randomUUID(),
queuedAt: new Date(),
resendCount: 0,

const insertedTransaction: InsertedTransaction = {
chainId,
from: walletAddress as Address,
to: toAddress as Address,
Expand All @@ -112,7 +106,7 @@ export async function simulateTransaction(fastify: FastifyInstance) {
}),
};

const simulateError = await doSimulateTransaction(queuedTransaction);
const simulateError = await doSimulateTransaction(insertedTransaction);
if (simulateError) {
throw createCustomError(
simulateError,
Expand Down
8 changes: 6 additions & 2 deletions src/server/utils/wallets/getLocalWallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ export const getLocalWallet = async ({
});

// If that works, save the wallet using the encryption password for the future
const walletDetails = await getWalletDetails({ address: walletAddress });
const walletDetails = await getWalletDetails({
walletAddress,
});

logger({
service: "worker",
Expand All @@ -73,7 +75,9 @@ export const getLocalWallet = async ({
export const getLocalWalletAccount = async (
walletAddress: Address,
): Promise<Account> => {
const walletDetails = await getWalletDetails({ address: walletAddress });
const walletDetails = await getWalletDetails({
walletAddress,
});

if (walletDetails.type !== "local") {
throw new Error(`Local Wallet not found for address ${walletAddress}`);
Expand Down
4 changes: 2 additions & 2 deletions src/utils/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export const getAccount = async (args: {
}

const walletDetails = await getWalletDetails({
address: from,
walletAddress: from,
});

const { account } = await walletDetailsToAccount({ walletDetails, chain });
Expand Down Expand Up @@ -180,7 +180,7 @@ export const getSmartBackendWalletAdminAccount = async ({
}

const walletDetails = await getWalletDetails({
address: accountAddress,
walletAddress: accountAddress,
});

if (!isSmartBackendWallet(walletDetails)) {
Expand Down
4 changes: 4 additions & 0 deletions src/utils/cache/clearCache.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { walletDetailsCache } from "../../db/wallets/getWalletDetails";
import type { env } from "../env";
import { accessTokenCache } from "./accessToken";
import { invalidateConfig } from "./getConfig";
import { sdkCache } from "./getSdk";
import { smartWalletsCache } from "./getSmartWalletV5";
import { walletsCache } from "./getWallet";
import { webhookCache } from "./getWebhook";
import { keypairCache } from "./keypair";
Expand All @@ -15,4 +17,6 @@ export const clearCache = async (
walletsCache.clear();
accessTokenCache.clear();
keypairCache.clear();
smartWalletsCache.clear();
walletDetailsCache.clear();
};
2 changes: 1 addition & 1 deletion src/utils/cache/getWallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export const getWallet = async <TWallet extends EVMWallet>({
try {
walletDetails = await getWalletDetails({
pgtx,
address: walletAddress,
walletAddress,
});
} catch (e) {
if (e instanceof WalletDetailsError) {
Expand Down
Loading
Loading