Skip to content

Commit 3755616

Browse files
committed
feat: password auth WIP
resolve #698
1 parent 01e7a2d commit 3755616

File tree

3 files changed

+63
-14
lines changed

3 files changed

+63
-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(256, 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(),
@@ -327,7 +332,7 @@ const apiRouter = router({
327332

328333
bitcoin: router({
329334
// note?: create all variants (e.g. segwit, nested segwit, legacy, taproot) for each added account by default
330-
add: t.procedure
335+
add: publicProcedure
331336
.input(
332337
z.object({
333338
walletId: z.string(),
@@ -385,7 +390,7 @@ const apiRouter = router({
385390
}),
386391

387392
// note: our first tx https://mempool.space/testnet4/tx/4d1797f4a6e92ab5164cfa8030e5954670f162e2aae792c8d6d6a81aae32fbd4
388-
send: t.procedure
393+
send: publicProcedure
389394
.input(
390395
z.object({
391396
walletId: z.string(),
@@ -429,7 +434,7 @@ const apiRouter = router({
429434
}),
430435

431436
solana: router({
432-
add: t.procedure
437+
add: publicProcedure
433438
.input(
434439
z.object({
435440
walletId: z.string(),
@@ -453,7 +458,7 @@ const apiRouter = router({
453458
}),
454459

455460
// note: our first tx https://solscan.io/tx/LNgKUb6bewbcgVXi9NBF4qYNJC5kjMPpH5GDVZBsVXFC7MDhYtdygkuP1avq7c31bHDkr9pkKYvMSdT16mt294g?cluster=devnet
456-
send: t.procedure
461+
send: publicProcedure
457462
.input(
458463
z.object({
459464
walletId: z.string(),
@@ -497,7 +502,7 @@ const apiRouter = router({
497502
}),
498503

499504
cardano: router({
500-
add: t.procedure
505+
add: publicProcedure
501506
.input(
502507
z.object({
503508
walletId: z.string(),
@@ -551,7 +556,7 @@ const apiRouter = router({
551556
}),
552557

553558
privateKey: router({
554-
import: t.procedure
559+
import: publicProcedure
555560
.input(
556561
z.object({
557562
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+
}

apps/wallet/src/routes/onboarding/new.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ function RouteComponent() {
2929
{onboardingState.type === 'recovery-phrase' && (
3030
<RecoveryPhrase mnemonic={onboardingState.mnemonic} />
3131
)}
32+
<Button variant="danger" onClick={async () => {}}>
33+
Show password input
34+
</Button>
3235
</div>
3336
)
3437
}

0 commit comments

Comments
 (0)