4
4
import {
5
5
ACCOUNT_SCHEMA_VERSION ,
6
6
AccountImport ,
7
+ Assert ,
7
8
createRootLogger ,
8
9
CurrencyUtils ,
9
10
Logger ,
@@ -45,9 +46,12 @@ export class LedgerDkg {
45
46
this . logger = logger ? logger : createRootLogger ( )
46
47
}
47
48
48
- tryInstruction = async < T > ( promise : Promise < T > ) => {
49
+ tryInstruction = async < T > ( instruction : ( app : IronfishDkgApp ) => Promise < T > ) => {
50
+ await this . refreshConnection ( )
51
+ Assert . isNotUndefined ( this . app , 'Unable to establish connection with Ledger device' )
52
+
49
53
try {
50
- return await promise
54
+ return await instruction ( this . app )
51
55
} catch ( error : unknown ) {
52
56
if ( isResponseError ( error ) ) {
53
57
this . logger . debug ( `Ledger ResponseError returnCode: ${ error . returnCode . toString ( 16 ) } ` )
@@ -69,6 +73,11 @@ export class LedgerDkg {
69
73
connect = async ( ) => {
70
74
const transport = await TransportNodeHid . create ( 3000 )
71
75
76
+ transport . on ( 'disconnect' , async ( ) => {
77
+ await transport . close ( )
78
+ this . app = undefined
79
+ } )
80
+
72
81
if ( transport . deviceModel ) {
73
82
this . logger . debug ( `${ transport . deviceModel . productName } found.` )
74
83
}
@@ -83,15 +92,17 @@ export class LedgerDkg {
83
92
return { app, PATH : this . PATH }
84
93
}
85
94
86
- dkgGetIdentity = async ( index : number ) : Promise < Buffer > => {
95
+ private refreshConnection = async ( ) => {
87
96
if ( ! this . app ) {
88
- throw new Error ( 'Connect to Ledger first' )
97
+ await this . connect ( )
89
98
}
99
+ }
90
100
101
+ dkgGetIdentity = async ( index : number ) : Promise < Buffer > => {
91
102
this . logger . log ( 'Retrieving identity from ledger device.' )
92
103
93
- const response : ResponseIdentity = await this . tryInstruction (
94
- this . app . dkgGetIdentity ( index , false ) ,
104
+ const response : ResponseIdentity = await this . tryInstruction ( ( app ) =>
105
+ app . dkgGetIdentity ( index , false ) ,
95
106
)
96
107
97
108
return response . identity
@@ -102,28 +113,20 @@ export class LedgerDkg {
102
113
identities : string [ ] ,
103
114
minSigners : number ,
104
115
) : Promise < ResponseDkgRound1 > => {
105
- if ( ! this . app ) {
106
- throw new Error ( 'Connect to Ledger first' )
107
- }
108
-
109
116
this . logger . log ( 'Please approve the request on your ledger device.' )
110
117
111
- return this . tryInstruction ( this . app . dkgRound1 ( index , identities , minSigners ) )
118
+ return this . tryInstruction ( ( app ) => app . dkgRound1 ( index , identities , minSigners ) )
112
119
}
113
120
114
121
dkgRound2 = async (
115
122
index : number ,
116
123
round1PublicPackages : string [ ] ,
117
124
round1SecretPackage : string ,
118
125
) : Promise < ResponseDkgRound2 > => {
119
- if ( ! this . app ) {
120
- throw new Error ( 'Connect to Ledger first' )
121
- }
122
-
123
126
this . logger . log ( 'Please approve the request on your ledger device.' )
124
127
125
- return this . tryInstruction (
126
- this . app . dkgRound2 ( index , round1PublicPackages , round1SecretPackage ) ,
128
+ return this . tryInstruction ( ( app ) =>
129
+ app . dkgRound2 ( index , round1PublicPackages , round1SecretPackage ) ,
127
130
)
128
131
}
129
132
@@ -135,14 +138,10 @@ export class LedgerDkg {
135
138
round2SecretPackage : string ,
136
139
gskBytes : string [ ] ,
137
140
) : Promise < void > => {
138
- if ( ! this . app ) {
139
- throw new Error ( 'Connect to Ledger first' )
140
- }
141
-
142
141
this . logger . log ( 'Please approve the request on your ledger device.' )
143
142
144
- return this . tryInstruction (
145
- this . app . dkgRound3Min (
143
+ return this . tryInstruction ( ( app ) =>
144
+ app . dkgRound3Min (
146
145
index ,
147
146
participants ,
148
147
round1PublicPackages ,
@@ -160,28 +159,24 @@ export class LedgerDkg {
160
159
outgoingViewKey : string
161
160
proofAuthorizingKey : string
162
161
} > => {
163
- if ( ! this . app ) {
164
- throw new Error ( 'Connect to Ledger first' )
165
- }
166
-
167
- const responseAddress : KeyResponse = await this . tryInstruction (
168
- this . app . dkgRetrieveKeys ( IronfishKeys . PublicAddress ) ,
162
+ const responseAddress : KeyResponse = await this . tryInstruction ( ( app ) =>
163
+ app . dkgRetrieveKeys ( IronfishKeys . PublicAddress ) ,
169
164
)
170
165
171
166
if ( ! isResponseAddress ( responseAddress ) ) {
172
167
throw new Error ( `No public address returned.` )
173
168
}
174
169
175
- const responseViewKey = await this . tryInstruction (
176
- this . app . dkgRetrieveKeys ( IronfishKeys . ViewKey ) ,
170
+ const responseViewKey = await this . tryInstruction ( ( app ) =>
171
+ app . dkgRetrieveKeys ( IronfishKeys . ViewKey ) ,
177
172
)
178
173
179
174
if ( ! isResponseViewKey ( responseViewKey ) ) {
180
175
throw new Error ( `No view key returned.` )
181
176
}
182
177
183
- const responsePGK : KeyResponse = await this . tryInstruction (
184
- this . app . dkgRetrieveKeys ( IronfishKeys . ProofGenerationKey ) ,
178
+ const responsePGK : KeyResponse = await this . tryInstruction ( ( app ) =>
179
+ app . dkgRetrieveKeys ( IronfishKeys . ProofGenerationKey ) ,
185
180
)
186
181
187
182
if ( ! isResponseProofGenKey ( responsePGK ) ) {
@@ -202,7 +197,7 @@ export class LedgerDkg {
202
197
throw new Error ( 'Connect to Ledger first' )
203
198
}
204
199
205
- const response = await this . tryInstruction ( this . app . dkgGetPublicPackage ( ) )
200
+ const response = await this . tryInstruction ( ( app ) => app . dkgGetPublicPackage ( ) )
206
201
207
202
return response . publicPackage
208
203
}
@@ -216,7 +211,7 @@ export class LedgerDkg {
216
211
'Please review and approve the outputs of this transaction on your ledger device.' ,
217
212
)
218
213
219
- const { hash } = await this . tryInstruction ( this . app . reviewTransaction ( transaction ) )
214
+ const { hash } = await this . tryInstruction ( ( app ) => app . reviewTransaction ( transaction ) )
220
215
221
216
return hash
222
217
}
@@ -226,8 +221,8 @@ export class LedgerDkg {
226
221
throw new Error ( 'Connect to Ledger first' )
227
222
}
228
223
229
- const { commitments } = await this . tryInstruction (
230
- this . app . dkgGetCommitments ( transactionHash ) ,
224
+ const { commitments } = await this . tryInstruction ( ( app ) =>
225
+ app . dkgGetCommitments ( transactionHash ) ,
231
226
)
232
227
233
228
return commitments
@@ -242,8 +237,8 @@ export class LedgerDkg {
242
237
throw new Error ( 'Connect to Ledger first' )
243
238
}
244
239
245
- const { signature } = await this . tryInstruction (
246
- this . app . dkgSign ( randomness , frostSigningPackage , transactionHash ) ,
240
+ const { signature } = await this . tryInstruction ( ( app ) =>
241
+ app . dkgSign ( randomness , frostSigningPackage , transactionHash ) ,
247
242
)
248
243
249
244
return signature
@@ -256,7 +251,7 @@ export class LedgerDkg {
256
251
257
252
this . logger . log ( 'Please approve the request on your ledger device.' )
258
253
259
- const { encryptedKeys } = await this . tryInstruction ( this . app . dkgBackupKeys ( ) )
254
+ const { encryptedKeys } = await this . tryInstruction ( ( app ) => app . dkgBackupKeys ( ) )
260
255
261
256
return encryptedKeys
262
257
}
@@ -268,7 +263,7 @@ export class LedgerDkg {
268
263
269
264
this . logger . log ( 'Please approve the request on your ledger device.' )
270
265
271
- await this . tryInstruction ( this . app . dkgRestoreKeys ( encryptedKeys ) )
266
+ await this . tryInstruction ( ( app ) => app . dkgRestoreKeys ( encryptedKeys ) )
272
267
}
273
268
}
274
269
0 commit comments