@@ -220,6 +220,7 @@ func NewHandlers(
220220 getAPIRouterNoError (apiRouter )("/dev-servers" , handlers .getDevServers ).Methods ("GET" )
221221 getAPIRouterNoError (apiRouter )("/account-add" , handlers .postAddAccount ).Methods ("POST" )
222222 getAPIRouterNoError (apiRouter )("/keystores" , handlers .getKeystores ).Methods ("GET" )
223+ getAPIRouterNoError (apiRouter )("/keystore/{rootFingerprint}/features" , handlers .getKeystoreFeatures ).Methods ("GET" )
223224 getAPIRouterNoError (apiRouter )("/accounts" , handlers .getAccounts ).Methods ("GET" )
224225 getAPIRouter (apiRouter )("/accounts/balance-summary" , handlers .getAccountsBalanceSummary ).Methods ("GET" )
225226 getAPIRouterNoError (apiRouter )("/set-account-active" , handlers .postSetAccountActive ).Methods ("POST" )
@@ -401,6 +402,8 @@ type accountJSON struct {
401402 IsToken bool `json:"isToken"`
402403 ActiveTokens []activeToken `json:"activeTokens,omitempty"`
403404 BlockExplorerTxPrefix string `json:"blockExplorerTxPrefix"`
405+ // Number of the account per coin per keystore, starting at 0. Nil if unknown.
406+ AccountNumber * uint16 `json:"accountNumber"`
404407}
405408
406409func newAccountJSON (
@@ -411,6 +414,11 @@ func newAccountJSON(
411414 eth , ok := account .Coin ().(* eth.Coin )
412415 isToken := ok && eth .ERC20Token () != nil
413416 watch := account .Config ().Config .Watch
417+ var accountNumberPtr * uint16
418+ accountNumber , err := account .Config ().Config .SigningConfigurations .AccountNumber ()
419+ if err == nil {
420+ accountNumberPtr = & accountNumber
421+ }
414422 return & accountJSON {
415423 Keystore : keystoreJSON {
416424 Keystore : keystore ,
@@ -427,6 +435,7 @@ func newAccountJSON(
427435 IsToken : isToken ,
428436 ActiveTokens : activeTokens ,
429437 BlockExplorerTxPrefix : account .Coin ().BlockExplorerTransactionURLPrefix (),
438+ AccountNumber : accountNumberPtr ,
430439 }
431440}
432441
@@ -598,6 +607,55 @@ func (handlers *Handlers) getKeystores(*http.Request) interface{} {
598607 return keystores
599608}
600609
610+ func (handlers * Handlers ) getKeystoreFeatures (r * http.Request ) interface {} {
611+ type response struct {
612+ Success bool `json:"success"`
613+ ErrorMessage string `json:"errorMessage,omitempty"`
614+ Features * keystore.Features `json:"features,omitempty"`
615+ }
616+
617+ rootFingerprintHex := mux .Vars (r )["rootFingerprint" ]
618+ rootFingerprint , err := hex .DecodeString (rootFingerprintHex )
619+ if err != nil {
620+ handlers .log .WithError (err ).Error ("invalid root fingerprint for features request" )
621+ return response {
622+ Success : false ,
623+ ErrorMessage : err .Error (),
624+ }
625+ }
626+
627+ connectedKeystore := handlers .backend .Keystore ()
628+ if connectedKeystore == nil {
629+ handlers .log .Warn ("features requested but no keystore connected" )
630+ return response {
631+ Success : false ,
632+ ErrorMessage : "keystore not connected" ,
633+ }
634+ }
635+
636+ connectedRootFingerprint , err := connectedKeystore .RootFingerprint ()
637+ if err != nil {
638+ handlers .log .WithError (err ).Error ("could not determine connected keystore root fingerprint" )
639+ return response {
640+ Success : false ,
641+ ErrorMessage : err .Error (),
642+ }
643+ }
644+
645+ if ! bytes .Equal (rootFingerprint , connectedRootFingerprint ) {
646+ handlers .log .WithField ("requested" , rootFingerprintHex ).Warn ("features requested for non-connected keystore" )
647+ return response {
648+ Success : false ,
649+ ErrorMessage : "wrong keystore connected" ,
650+ }
651+ }
652+
653+ return response {
654+ Success : true ,
655+ Features : connectedKeystore .Features (),
656+ }
657+ }
658+
601659func (handlers * Handlers ) getAccounts (* http.Request ) interface {} {
602660 persistedAccounts := handlers .backend .Config ().AccountsConfig ()
603661
0 commit comments