@ -322,62 +322,65 @@ func (api *SignerAPI) openTrezor(url accounts.URL) {
// startUSBListener starts a listener for USB events, for hardware wallet interaction
func ( api * SignerAPI ) startUSBListener ( ) {
events := make ( chan accounts . WalletEvent , 16 )
eventCh := make ( chan accounts . WalletEvent , 16 )
am := api . am
am . Subscribe ( events )
go func ( ) {
am . Subscribe ( eventCh )
// Open any wallets already attached
for _ , wallet := range am . Wallets ( ) {
if err := wallet . Open ( "" ) ; err != nil {
log . Warn ( "Failed to open wallet" , "url" , wallet . URL ( ) , "err" , err )
if err == usbwallet . ErrTrezorPINNeeded {
go api . openTrezor ( wallet . URL ( ) )
}
}
}
go api . derivationLoop ( eventCh )
}
// Open any wallets already attached
for _ , wallet := range am . Wallets ( ) {
if err := wallet . Open ( "" ) ; err != nil {
log . Warn ( "Failed to open wallet" , "url" , wallet . URL ( ) , "err" , err )
// derivationLoop listens for wallet events
func ( api * SignerAPI ) derivationLoop ( events chan accounts . WalletEvent ) {
// Listen for wallet event till termination
for event := range events {
switch event . Kind {
case accounts . WalletArrived :
if err := event . Wallet . Open ( "" ) ; err != nil {
log . Warn ( "New wallet appeared, failed to open" , "url" , event . Wallet . URL ( ) , "err" , err )
if err == usbwallet . ErrTrezorPINNeeded {
go api . openTrezor ( wallet . URL ( ) )
go api . openTrezor ( event . W allet. URL ( ) )
}
}
}
// Listen for wallet event till termination
for event := range events {
switch event . Kind {
case accounts . WalletArrived :
if err := event . Wallet . Open ( "" ) ; err != nil {
log . Warn ( "New wallet appeared, failed to open" , "url" , event . Wallet . URL ( ) , "err" , err )
if err == usbwallet . ErrTrezorPINNeeded {
go api . openTrezor ( event . Wallet . URL ( ) )
case accounts . WalletOpened :
status , _ := event . Wallet . Status ( )
log . Info ( "New wallet appeared" , "url" , event . Wallet . URL ( ) , "status" , status )
var derive = func ( limit int , next func ( ) accounts . DerivationPath ) {
// Derive first N accounts, hardcoded for now
for i := 0 ; i < limit ; i ++ {
path := next ( )
if acc , err := event . Wallet . Derive ( path , true ) ; err != nil {
log . Warn ( "Account derivation failed" , "error" , err )
} else {
log . Info ( "Derived account" , "address" , acc . Address , "path" , path )
}
}
case accounts . WalletOpened :
status , _ := event . Wallet . Status ( )
log . Info ( "New wallet appeared" , "url" , event . Wallet . URL ( ) , "status" , status )
var derive = func ( numToDerive int , base accounts . DerivationPath ) {
// Derive first N accounts, hardcoded for now
var nextPath = make ( accounts . DerivationPath , len ( base ) )
copy ( nextPath [ : ] , base [ : ] )
for i := 0 ; i < numToDerive ; i ++ {
acc , err := event . Wallet . Derive ( nextPath , true )
if err != nil {
log . Warn ( "Account derivation failed" , "error" , err )
} else {
log . Info ( "Derived account" , "address" , acc . Address , "path" , nextPath )
}
nextPath [ len ( nextPath ) - 1 ] ++
}
}
if event . Wallet . URL ( ) . Scheme == "ledger" {
log . Info ( "Deriving ledger default paths" )
derive ( numberOfAccountsToDerive / 2 , accounts . DefaultBaseDerivationPath )
log . Info ( "Deriving ledger legacy paths" )
derive ( numberOfAccountsToDerive / 2 , accounts . LegacyLedgerBaseDerivationPath )
} else {
derive ( numberOfAccountsToDerive , accounts . DefaultBaseDerivationPath )
}
case accounts . WalletDropped :
log . Info ( "Old wallet dropped" , "url" , event . Wallet . URL ( ) )
event . Wallet . Close ( )
}
log . Info ( "Deriving default paths" )
derive ( numberOfAccountsToDerive , accounts . DefaultIterator ( accounts . DefaultBaseDerivationPath ) )
if event . Wallet . URL ( ) . Scheme == "ledger" {
log . Info ( "Deriving ledger legacy paths" )
derive ( numberOfAccountsToDerive , accounts . DefaultIterator ( accounts . LegacyLedgerBaseDerivationPath ) )
log . Info ( "Deriving ledger live paths" )
// For ledger live, since it's based off the same (DefaultBaseDerivationPath)
// as one we've already used, we need to step it forward one step to avoid
// hitting the same path again
nextFn := accounts . LedgerLiveIterator ( accounts . DefaultBaseDerivationPath )
nextFn ( )
derive ( numberOfAccountsToDerive , nextFn )
}
case accounts . WalletDropped :
log . Info ( "Old wallet dropped" , "url" , event . Wallet . URL ( ) )
event . Wallet . Close ( )
}
} ( )
}
}
// List returns the set of wallet this signer manages. Each wallet can contain