Skip to content

Commit e16ff75

Browse files
committed
feat: ensure wallet.mnemonic is only available internally to the database
1 parent f8dd18a commit e16ff75

11 files changed

+47
-23
lines changed

packages/db/src/database.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { BookmarkAccount } from './bookmark-account/bookmark-account.ts'
44
import type { Network } from './network/network.ts'
55
import { populate } from './populate.ts'
66
import type { Setting } from './setting/setting.ts'
7-
import type { Wallet } from './wallet/wallet.ts'
7+
import type { WalletInternal } from './wallet/wallet-internal.ts'
88

99
export interface DatabaseConfig {
1010
name: string
@@ -15,7 +15,7 @@ export class Database extends Dexie {
1515
bookmarkAccounts!: Table<BookmarkAccount>
1616
networks!: Table<Network>
1717
settings!: Table<Setting>
18-
wallets!: Table<Wallet>
18+
wallets!: Table<WalletInternal>
1919

2020
constructor(config: DatabaseConfig) {
2121
super(config.name)

packages/db/src/wallet/wallet-create-schema.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { walletSchema } from './wallet-schema.ts'
1+
import { walletInternalSchema } from './wallet-internal-schema.ts'
22

3-
export const walletCreateSchema = walletSchema.omit({
3+
export const walletCreateSchema = walletInternalSchema.omit({
44
accounts: true,
55
createdAt: true,
66
id: true,

packages/db/src/wallet/wallet-find-many.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type { Wallet } from './wallet.ts'
55
import type { WalletFindManyInput } from './wallet-find-many-input.ts'
66

77
import { walletFindManySchema } from './wallet-find-many-schema.ts'
8+
import { walletSanitizer } from './wallet-sanitizer.ts'
89

910
export async function walletFindMany(db: Database, input: WalletFindManyInput = {}): Promise<Wallet[]> {
1011
const parsedInput = walletFindManySchema.parse(input)
@@ -36,7 +37,7 @@ export async function walletFindMany(db: Database, input: WalletFindManyInput =
3637
return [
3738
...dataWallets.map((wallet) => {
3839
return {
39-
...wallet,
40+
...walletSanitizer(wallet),
4041
accounts: [...dataAccounts.filter((account) => account.walletId === wallet.id)],
4142
}
4243
}),

packages/db/src/wallet/wallet-find-unique.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ import { tryCatch } from '@workspace/core/try-catch'
22

33
import type { Database } from '../database.ts'
44
import type { Wallet } from './wallet.ts'
5+
import { walletSanitizer } from './wallet-sanitizer.ts'
56

67
export async function walletFindUnique(db: Database, id: string): Promise<Wallet | null> {
78
const { data, error } = await tryCatch(db.wallets.get(id))
89
if (error) {
910
console.log(error)
1011
throw new Error(`Error finding wallet with id ${id}`)
1112
}
12-
return data ? data : null
13+
return data ? walletSanitizer(data) : null
1314
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { z } from 'zod'
2+
3+
import { accountSchema } from '../account/account-schema.ts'
4+
5+
export const walletInternalSchema = z.object({
6+
accounts: z.array(accountSchema).optional().default([]),
7+
createdAt: z.date(),
8+
derivationPath: z.string(),
9+
id: z.string(),
10+
mnemonic: z.string(),
11+
name: z.string(),
12+
order: z.number(),
13+
secret: z.string(),
14+
updatedAt: z.date(),
15+
})
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import type { z } from 'zod'
2+
3+
import type { walletInternalSchema } from './wallet-internal-schema.ts'
4+
5+
export type WalletInternal = z.infer<typeof walletInternalSchema>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import type { Wallet } from './wallet.ts'
2+
import type { WalletInternal } from './wallet-internal.ts'
3+
import { walletSchema } from './wallet-schema.ts'
4+
5+
export function walletSanitizer(internal: WalletInternal): Wallet {
6+
return walletSchema.parse(internal)
7+
}
Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,5 @@
1-
import { z } from 'zod'
1+
import { walletInternalSchema } from './wallet-internal-schema.ts'
22

3-
import { accountSchema } from '../account/account-schema.ts'
4-
5-
export const walletSchema = z.object({
6-
accounts: z.array(accountSchema).optional().default([]),
7-
createdAt: z.date(),
8-
derivationPath: z.string(),
9-
id: z.string(),
10-
mnemonic: z.string(),
11-
name: z.string(),
12-
order: z.number(),
13-
secret: z.string(),
14-
updatedAt: z.date(),
3+
export const walletSchema = walletInternalSchema.omit({
4+
mnemonic: true,
155
})

packages/db/test/wallet-create.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ describe('wallet-create', () => {
2626

2727
// ASSERT
2828
const item = await walletFindUnique(db, result)
29-
expect(item?.mnemonic).toBe(input.mnemonic)
29+
// @ts-expect-error mnemonic does not exist on the type. Here we ensure it's sanitized.
30+
expect(item?.mnemonic).toBe(undefined)
3031
expect(item?.name).toBe(input.name)
3132
expect(item?.order).toBe(0)
3233
})

packages/db/test/wallet-find-many.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ describe('wallet-find-many', () => {
7575

7676
it('should find many wallets by id', async () => {
7777
// ARRANGE
78-
expect.assertions(2)
78+
expect.assertions(3)
7979
const wallet1 = testWalletCreateInput({ name: 'Test Wallet Alpha' })
8080
const wallet2 = testWalletCreateInput({ name: 'Test Wallet Beta' })
8181
const id1 = await walletCreate(db, wallet1)
@@ -87,6 +87,8 @@ describe('wallet-find-many', () => {
8787
// ASSERT
8888
expect(items).toHaveLength(1)
8989
expect(items[0]?.name).toEqual(wallet1.name)
90+
// @ts-expect-error mnemonic does not exist on the type. Here we ensure it's sanitized.
91+
expect(items[0]?.mnemonic).toEqual(undefined)
9092
})
9193
})
9294

@@ -103,8 +105,8 @@ describe('wallet-find-many', () => {
103105
// ARRANGE
104106
expect.assertions(1)
105107
vi.spyOn(db.wallets, 'orderBy').mockImplementation(() => ({
106-
// @ts-expect-error - Mocking Dexie's chained methods confuses Vitest's type inference.
107108
filter: () => ({
109+
// @ts-expect-error - Mocking Dexie's chained methods confuses Vitest's type inference.
108110
toArray: () => Promise.reject(new Error('Test error')) as PromiseExtended<Wallet[]>,
109111
}),
110112
}))

0 commit comments

Comments
 (0)