@@ -19,15 +19,12 @@ package console
1919import (
2020 "encoding/json"
2121 "errors"
22- "fmt"
2322 "io"
2423 "reflect"
2524 "strings"
2625 "time"
2726
2827 "github.com/dop251/goja"
29- "github.com/ethereum/go-ethereum/accounts/scwallet"
30- "github.com/ethereum/go-ethereum/accounts/usbwallet"
3128 "github.com/ethereum/go-ethereum/common/hexutil"
3229 "github.com/ethereum/go-ethereum/console/prompt"
3330 "github.com/ethereum/go-ethereum/internal/jsre"
@@ -51,268 +48,6 @@ func newBridge(client *rpc.Client, prompter prompt.UserPrompter, printer io.Writ
5148 }
5249}
5350
54- func getJeth (vm * goja.Runtime ) * goja.Object {
55- jeth := vm .Get ("jeth" )
56- if jeth == nil {
57- panic (vm .ToValue ("jeth object does not exist" ))
58- }
59- return jeth .ToObject (vm )
60- }
61-
62- // NewAccount is a wrapper around the personal.newAccount RPC method that uses a
63- // non-echoing password prompt to acquire the passphrase and executes the original
64- // RPC method (saved in jeth.newAccount) with it to actually execute the RPC call.
65- func (b * bridge ) NewAccount (call jsre.Call ) (goja.Value , error ) {
66- var (
67- password string
68- confirm string
69- err error
70- )
71- switch {
72- // No password was specified, prompt the user for it
73- case len (call .Arguments ) == 0 :
74- if password , err = b .prompter .PromptPassword ("Passphrase: " ); err != nil {
75- return nil , err
76- }
77- if confirm , err = b .prompter .PromptPassword ("Repeat passphrase: " ); err != nil {
78- return nil , err
79- }
80- if password != confirm {
81- return nil , errors .New ("passwords don't match" )
82- }
83- // A single string password was specified, use that
84- case len (call .Arguments ) == 1 && call .Argument (0 ).ToString () != nil :
85- password = call .Argument (0 ).ToString ().String ()
86- default :
87- return nil , errors .New ("expected 0 or 1 string argument" )
88- }
89- // Password acquired, execute the call and return
90- newAccount , callable := goja .AssertFunction (getJeth (call .VM ).Get ("newAccount" ))
91- if ! callable {
92- return nil , errors .New ("jeth.newAccount is not callable" )
93- }
94- ret , err := newAccount (goja .Null (), call .VM .ToValue (password ))
95- if err != nil {
96- return nil , err
97- }
98- return ret , nil
99- }
100-
101- // OpenWallet is a wrapper around personal.openWallet which can interpret and
102- // react to certain error messages, such as the Trezor PIN matrix request.
103- func (b * bridge ) OpenWallet (call jsre.Call ) (goja.Value , error ) {
104- // Make sure we have a wallet specified to open
105- if call .Argument (0 ).ToObject (call .VM ).ClassName () != "String" {
106- return nil , errors .New ("first argument must be the wallet URL to open" )
107- }
108- wallet := call .Argument (0 )
109-
110- var passwd goja.Value
111- if goja .IsUndefined (call .Argument (1 )) || goja .IsNull (call .Argument (1 )) {
112- passwd = call .VM .ToValue ("" )
113- } else {
114- passwd = call .Argument (1 )
115- }
116- // Open the wallet and return if successful in itself
117- openWallet , callable := goja .AssertFunction (getJeth (call .VM ).Get ("openWallet" ))
118- if ! callable {
119- return nil , errors .New ("jeth.openWallet is not callable" )
120- }
121- val , err := openWallet (goja .Null (), wallet , passwd )
122- if err == nil {
123- return val , nil
124- }
125-
126- // Wallet open failed, report error unless it's a PIN or PUK entry
127- switch {
128- case strings .HasSuffix (err .Error (), usbwallet .ErrTrezorPINNeeded .Error ()):
129- val , err = b .readPinAndReopenWallet (call )
130- if err == nil {
131- return val , nil
132- }
133- val , err = b .readPassphraseAndReopenWallet (call )
134- if err != nil {
135- return nil , err
136- }
137-
138- case strings .HasSuffix (err .Error (), scwallet .ErrPairingPasswordNeeded .Error ()):
139- // PUK input requested, fetch from the user and call open again
140- input , err := b .prompter .PromptPassword ("Please enter the pairing password: " )
141- if err != nil {
142- return nil , err
143- }
144- passwd = call .VM .ToValue (input )
145- if val , err = openWallet (goja .Null (), wallet , passwd ); err != nil {
146- if ! strings .HasSuffix (err .Error (), scwallet .ErrPINNeeded .Error ()) {
147- return nil , err
148- }
149- // PIN input requested, fetch from the user and call open again
150- input , err := b .prompter .PromptPassword ("Please enter current PIN: " )
151- if err != nil {
152- return nil , err
153- }
154- if val , err = openWallet (goja .Null (), wallet , call .VM .ToValue (input )); err != nil {
155- return nil , err
156- }
157- }
158-
159- case strings .HasSuffix (err .Error (), scwallet .ErrPINUnblockNeeded .Error ()):
160- // PIN unblock requested, fetch PUK and new PIN from the user
161- var pukpin string
162- input , err := b .prompter .PromptPassword ("Please enter current PUK: " )
163- if err != nil {
164- return nil , err
165- }
166- pukpin = input
167- input , err = b .prompter .PromptPassword ("Please enter new PIN: " )
168- if err != nil {
169- return nil , err
170- }
171- pukpin += input
172-
173- if val , err = openWallet (goja .Null (), wallet , call .VM .ToValue (pukpin )); err != nil {
174- return nil , err
175- }
176-
177- case strings .HasSuffix (err .Error (), scwallet .ErrPINNeeded .Error ()):
178- // PIN input requested, fetch from the user and call open again
179- input , err := b .prompter .PromptPassword ("Please enter current PIN: " )
180- if err != nil {
181- return nil , err
182- }
183- if val , err = openWallet (goja .Null (), wallet , call .VM .ToValue (input )); err != nil {
184- return nil , err
185- }
186-
187- default :
188- // Unknown error occurred, drop to the user
189- return nil , err
190- }
191- return val , nil
192- }
193-
194- func (b * bridge ) readPassphraseAndReopenWallet (call jsre.Call ) (goja.Value , error ) {
195- wallet := call .Argument (0 )
196- input , err := b .prompter .PromptPassword ("Please enter your passphrase: " )
197- if err != nil {
198- return nil , err
199- }
200- openWallet , callable := goja .AssertFunction (getJeth (call .VM ).Get ("openWallet" ))
201- if ! callable {
202- return nil , errors .New ("jeth.openWallet is not callable" )
203- }
204- return openWallet (goja .Null (), wallet , call .VM .ToValue (input ))
205- }
206-
207- func (b * bridge ) readPinAndReopenWallet (call jsre.Call ) (goja.Value , error ) {
208- wallet := call .Argument (0 )
209- // Trezor PIN matrix input requested, display the matrix to the user and fetch the data
210- fmt .Fprintf (b .printer , "Look at the device for number positions\n \n " )
211- fmt .Fprintf (b .printer , "7 | 8 | 9\n " )
212- fmt .Fprintf (b .printer , "--+---+--\n " )
213- fmt .Fprintf (b .printer , "4 | 5 | 6\n " )
214- fmt .Fprintf (b .printer , "--+---+--\n " )
215- fmt .Fprintf (b .printer , "1 | 2 | 3\n \n " )
216-
217- input , err := b .prompter .PromptPassword ("Please enter current PIN: " )
218- if err != nil {
219- return nil , err
220- }
221- openWallet , callable := goja .AssertFunction (getJeth (call .VM ).Get ("openWallet" ))
222- if ! callable {
223- return nil , errors .New ("jeth.openWallet is not callable" )
224- }
225- return openWallet (goja .Null (), wallet , call .VM .ToValue (input ))
226- }
227-
228- // UnlockAccount is a wrapper around the personal.unlockAccount RPC method that
229- // uses a non-echoing password prompt to acquire the passphrase and executes the
230- // original RPC method (saved in jeth.unlockAccount) with it to actually execute
231- // the RPC call.
232- func (b * bridge ) UnlockAccount (call jsre.Call ) (goja.Value , error ) {
233- if len (call .Arguments ) < 1 {
234- return nil , errors .New ("usage: unlockAccount(account, [ password, duration ])" )
235- }
236-
237- account := call .Argument (0 )
238- // Make sure we have an account specified to unlock.
239- if goja .IsUndefined (account ) || goja .IsNull (account ) || account .ExportType ().Kind () != reflect .String {
240- return nil , errors .New ("first argument must be the account to unlock" )
241- }
242-
243- // If password is not given or is the null value, prompt the user for it.
244- var passwd goja.Value
245- if goja .IsUndefined (call .Argument (1 )) || goja .IsNull (call .Argument (1 )) {
246- fmt .Fprintf (b .printer , "Unlock account %s\n " , account )
247- input , err := b .prompter .PromptPassword ("Passphrase: " )
248- if err != nil {
249- return nil , err
250- }
251- passwd = call .VM .ToValue (input )
252- } else {
253- if call .Argument (1 ).ExportType ().Kind () != reflect .String {
254- return nil , errors .New ("password must be a string" )
255- }
256- passwd = call .Argument (1 )
257- }
258-
259- // Third argument is the duration how long the account should be unlocked.
260- duration := goja .Null ()
261- if ! goja .IsUndefined (call .Argument (2 )) && ! goja .IsNull (call .Argument (2 )) {
262- if ! isNumber (call .Argument (2 )) {
263- return nil , errors .New ("unlock duration must be a number" )
264- }
265- duration = call .Argument (2 )
266- }
267-
268- // Send the request to the backend and return.
269- unlockAccount , callable := goja .AssertFunction (getJeth (call .VM ).Get ("unlockAccount" ))
270- if ! callable {
271- return nil , errors .New ("jeth.unlockAccount is not callable" )
272- }
273- return unlockAccount (goja .Null (), account , passwd , duration )
274- }
275-
276- // Sign is a wrapper around the personal.sign RPC method that uses a non-echoing password
277- // prompt to acquire the passphrase and executes the original RPC method (saved in
278- // jeth.sign) with it to actually execute the RPC call.
279- func (b * bridge ) Sign (call jsre.Call ) (goja.Value , error ) {
280- if nArgs := len (call .Arguments ); nArgs < 2 {
281- return nil , errors .New ("usage: sign(message, account, [ password ])" )
282- }
283- var (
284- message = call .Argument (0 )
285- account = call .Argument (1 )
286- passwd = call .Argument (2 )
287- )
288-
289- if goja .IsUndefined (message ) || message .ExportType ().Kind () != reflect .String {
290- return nil , errors .New ("first argument must be the message to sign" )
291- }
292- if goja .IsUndefined (account ) || account .ExportType ().Kind () != reflect .String {
293- return nil , errors .New ("second argument must be the account to sign with" )
294- }
295-
296- // if the password is not given or null ask the user and ensure password is a string
297- if goja .IsUndefined (passwd ) || goja .IsNull (passwd ) {
298- fmt .Fprintf (b .printer , "Give password for account %s\n " , account )
299- input , err := b .prompter .PromptPassword ("Password: " )
300- if err != nil {
301- return nil , err
302- }
303- passwd = call .VM .ToValue (input )
304- } else if passwd .ExportType ().Kind () != reflect .String {
305- return nil , errors .New ("third argument must be the password to unlock the account" )
306- }
307-
308- // Send the request to the backend and return
309- sign , callable := goja .AssertFunction (getJeth (call .VM ).Get ("sign" ))
310- if ! callable {
311- return nil , errors .New ("jeth.sign is not callable" )
312- }
313- return sign (goja .Null (), message , account , passwd )
314- }
315-
31651// Sleep will block the console for the specified number of seconds.
31752func (b * bridge ) Sleep (call jsre.Call ) (goja.Value , error ) {
31853 if nArgs := len (call .Arguments ); nArgs < 1 {
0 commit comments