Skip to content

Commit db18223

Browse files
committed
feat: password auth
resolve #698
1 parent 6db6dc3 commit db18223

File tree

2 files changed

+60
-14
lines changed

2 files changed

+60
-14
lines changed

apps/wallet/src/data/api.ts

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import * as bitcoin from './bitcoin/bitcoin'
1212
import * as ethereum from './ethereum/ethereum'
1313
import { getKeystore } from './keystore'
1414
import * as solana from './solana/solana'
15+
import { createPasswordAuthPlugin } from './trpc/middlewares/password-auth'
1516
import {
1617
getWalletCore,
1718
// type WalletCore
@@ -34,6 +35,8 @@ const createContext = async (webextOpts?: CreateWebExtContextOptions) => {
3435

3536
type Context = Awaited<ReturnType<typeof createContext>>
3637

38+
const passwordAuthPlugin = createPasswordAuthPlugin<Context>()
39+
3740
/**
3841
* @see https://trpc.io/docs/server/routers#runtime-configuration
3942
*/
@@ -43,14 +46,15 @@ const t = initTRPC.context<Context>().create({
4346
allowOutsideOfServer: true,
4447
})
4548

46-
// const publicProcedure = t.procedure
49+
const publicProcedure = t.procedure.concat(passwordAuthPlugin)
50+
4751
const { createCallerFactory, router } = t
4852

4953
// todo: lock with password as trpc auth procedure
5054
// todo?: expose password in context or use other (session) token derived from it for encrypting and storing
5155
const apiRouter = router({
5256
wallet: router({
53-
all: t.procedure.query(async ({ ctx }) => {
57+
all: publicProcedure.query(async ({ ctx }) => {
5458
const { keyStore } = ctx
5559

5660
const wallets = await keyStore.loadAll()
@@ -61,7 +65,7 @@ const apiRouter = router({
6165
// todo: validation (e.g. password, mnemonic, already exists)
6266
// todo: words count option
6367
// todo: handle cancelation
64-
add: t.procedure
68+
add: publicProcedure
6569
.input(
6670
z.object({
6771
password: z.string(),
@@ -70,6 +74,7 @@ const apiRouter = router({
7074
)
7175
.mutation(async ({ input, ctx }) => {
7276
const { walletCore, keyStore } = ctx
77+
console.log('ctx = ', ctx)
7378

7479
const wallet = walletCore.HDWallet.create(128, input.password)
7580
const mnemonic = wallet.mnemonic()
@@ -110,7 +115,7 @@ const apiRouter = router({
110115
}
111116
}),
112117

113-
get: t.procedure
118+
get: publicProcedure
114119
.input(
115120
z.object({
116121
walletId: z.string(),
@@ -129,7 +134,7 @@ const apiRouter = router({
129134
}
130135
}),
131136

132-
import: t.procedure
137+
import: publicProcedure
133138
.input(
134139
z.object({
135140
mnemonic: z.string(),
@@ -182,7 +187,7 @@ const apiRouter = router({
182187
}),
183188

184189
account: router({
185-
all: t.procedure
190+
all: publicProcedure
186191
.input(
187192
z.object({
188193
walletId: z.string(),
@@ -197,7 +202,7 @@ const apiRouter = router({
197202
}),
198203

199204
ethereum: router({
200-
add: t.procedure
205+
add: publicProcedure
201206
.input(
202207
z.object({
203208
walletId: z.string(),
@@ -265,7 +270,7 @@ const apiRouter = router({
265270
}),
266271

267272
// note: our first tx https://holesky.etherscan.io/tx/0xdc2aa244933260c50e665aa816767dce6b76d5d498e6358392d5f79bfc9626d5
268-
send: t.procedure
273+
send: publicProcedure
269274
.input(
270275
z.object({
271276
walletId: z.string(),
@@ -333,7 +338,7 @@ const apiRouter = router({
333338

334339
bitcoin: router({
335340
// note?: create all variants (e.g. segwit, nested segwit, legacy, taproot) for each added account by default
336-
add: t.procedure
341+
add: publicProcedure
337342
.input(
338343
z.object({
339344
walletId: z.string(),
@@ -391,7 +396,7 @@ const apiRouter = router({
391396
}),
392397

393398
// note: our first tx https://mempool.space/testnet4/tx/4d1797f4a6e92ab5164cfa8030e5954670f162e2aae792c8d6d6a81aae32fbd4
394-
send: t.procedure
399+
send: publicProcedure
395400
.input(
396401
z.object({
397402
walletId: z.string(),
@@ -435,7 +440,7 @@ const apiRouter = router({
435440
}),
436441

437442
solana: router({
438-
add: t.procedure
443+
add: publicProcedure
439444
.input(
440445
z.object({
441446
walletId: z.string(),
@@ -459,7 +464,7 @@ const apiRouter = router({
459464
}),
460465

461466
// note: our first tx https://solscan.io/tx/LNgKUb6bewbcgVXi9NBF4qYNJC5kjMPpH5GDVZBsVXFC7MDhYtdygkuP1avq7c31bHDkr9pkKYvMSdT16mt294g?cluster=devnet
462-
send: t.procedure
467+
send: publicProcedure
463468
.input(
464469
z.object({
465470
walletId: z.string(),
@@ -503,7 +508,7 @@ const apiRouter = router({
503508
}),
504509

505510
cardano: router({
506-
add: t.procedure
511+
add: publicProcedure
507512
.input(
508513
z.object({
509514
walletId: z.string(),
@@ -557,7 +562,7 @@ const apiRouter = router({
557562
}),
558563

559564
privateKey: router({
560-
import: t.procedure
565+
import: publicProcedure
561566
.input(
562567
z.object({
563568
privateKey: z.string(),
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { initTRPC } from '@trpc/server'
2+
3+
import type { KeyStore } from '@trustwallet/wallet-core'
4+
5+
export interface PasswordAuthParams {
6+
password?: string
7+
walletId?: string
8+
}
9+
10+
type Context = {
11+
keyStore: KeyStore.Default
12+
}
13+
14+
export function createPasswordAuthPlugin<TContext extends Context>() {
15+
const t = initTRPC.context<TContext>().create({
16+
isServer: false,
17+
allowOutsideOfServer: true,
18+
})
19+
20+
return t.procedure.use(async opts => {
21+
const { ctx } = opts
22+
const { keyStore } = ctx
23+
const params = (await opts.getRawInput()) as PasswordAuthParams
24+
if (
25+
typeof params?.password !== 'string' ||
26+
typeof params?.walletId !== 'string'
27+
)
28+
return opts.next()
29+
30+
let validPassword: undefined | string
31+
32+
await keyStore
33+
.export(params.walletId, params.password)
34+
.then(() => {
35+
validPassword = params.password
36+
})
37+
.catch(() => {})
38+
39+
return opts.next({ ctx: { validPassword } })
40+
})
41+
}

0 commit comments

Comments
 (0)