pass errors up rather than logging directly
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -3,7 +3,7 @@ package bitcoinElectrum
|
|||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"log"
|
"fmt"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcutil"
|
"github.com/btcsuite/btcd/btcutil"
|
||||||
@@ -43,13 +43,10 @@ func addressToScriptHash(address btcutil.Address) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Scans a derivation branch (m/0 or m/1) for balances until the gap limit is reached.
|
// Scans a derivation branch (m/0 or m/1) for balances until the gap limit is reached.
|
||||||
func scanBranch(masterKey *hdkeychain.ExtendedKey, branch uint32, gapLimit int, spvServer string) int64 {
|
func scanBranch(masterKey *hdkeychain.ExtendedKey, branch uint32, gapLimit int, spvServer string) (int64, error) {
|
||||||
log.Printf("Scanning branch m/%d/k...", branch)
|
|
||||||
|
|
||||||
branchKey, err := masterKey.Derive(branch)
|
branchKey, err := masterKey.Derive(branch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error deriving branch %d: %v", branch, err)
|
return 0, fmt.Errorf("error deriving branch %d: %v", branch, err)
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var branchTotalBalance int64
|
var branchTotalBalance int64
|
||||||
@@ -57,35 +54,28 @@ func scanBranch(masterKey *hdkeychain.ExtendedKey, branch uint32, gapLimit int,
|
|||||||
|
|
||||||
for i := uint32(0); ; i++ {
|
for i := uint32(0); ; i++ {
|
||||||
if unusedAddressCount >= gapLimit {
|
if unusedAddressCount >= gapLimit {
|
||||||
log.Printf("Gap limit of %d reached on branch m/%d. Stopping scan.", gapLimit, branch)
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Derive child address
|
// 3. Derive child address
|
||||||
address, err := deriveAddress(branchKey, i)
|
address, err := deriveAddress(branchKey, i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Could not derive address at index %d on branch %d: %v", i, branch, err)
|
return 0, fmt.Errorf("could not derive address at index %d on branch %d: %v", i, branch, err)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Get balance from Electrum server
|
// 4. Get balance from Electrum server
|
||||||
balance, err := getAddressBalance(spvServer, address)
|
balance, err := getAddressBalance(spvServer, address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error getting balance for %s: %v", address.EncodeAddress(), err)
|
return 0, fmt.Errorf("error getting balance for %s: %v", address.EncodeAddress(), err)
|
||||||
// On error, we can't know if it's used, so we continue scanning.
|
|
||||||
unusedAddressCount = 0
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
total := balance.Result.Confirmed + balance.Result.Unconfirmed
|
total := balance.Result.Confirmed + balance.Result.Unconfirmed
|
||||||
if total > 0 {
|
if total > 0 {
|
||||||
log.Printf("Found balance for m/%d/%d (%s): %.8f BTC", branch, i, address.EncodeAddress(), btcutil.Amount(total).ToBTC())
|
|
||||||
atomic.AddInt64(&branchTotalBalance, total)
|
atomic.AddInt64(&branchTotalBalance, total)
|
||||||
unusedAddressCount = 0 // Reset gap counter on finding a used address
|
unusedAddressCount = 0 // Reset gap counter on finding a used address
|
||||||
} else {
|
} else {
|
||||||
log.Printf("No balance for m/%d/%d (%s)", branch, i, address.EncodeAddress())
|
|
||||||
unusedAddressCount++
|
unusedAddressCount++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return branchTotalBalance
|
return branchTotalBalance, nil
|
||||||
}
|
}
|
||||||
|
@@ -3,8 +3,6 @@ package bitcoinElectrum
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
|
||||||
"sync/atomic"
|
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcutil/hdkeychain"
|
"github.com/btcsuite/btcd/btcutil/hdkeychain"
|
||||||
)
|
)
|
||||||
@@ -27,7 +25,7 @@ func (p *Provider) Configure() error {
|
|||||||
p.ynabAccountID = os.Getenv("bitcoin_ynab_account")
|
p.ynabAccountID = os.Getenv("bitcoin_ynab_account")
|
||||||
p.spvServer = os.Getenv("bitcoin_spv_server")
|
p.spvServer = os.Getenv("bitcoin_spv_server")
|
||||||
p.coinGeckoApiKey = os.Getenv("bitcoin_coingecko_api_key")
|
p.coinGeckoApiKey = os.Getenv("bitcoin_coingecko_api_key")
|
||||||
p.gapLimit = 20
|
p.gapLimit = 10
|
||||||
if zpub == "" || p.ynabAccountID == "" || p.spvServer == "" || p.coinGeckoApiKey == "" {
|
if zpub == "" || p.ynabAccountID == "" || p.spvServer == "" || p.coinGeckoApiKey == "" {
|
||||||
return fmt.Errorf("this account provider is not configured")
|
return fmt.Errorf("this account provider is not configured")
|
||||||
}
|
}
|
||||||
@@ -43,20 +41,16 @@ func (p *Provider) Configure() error {
|
|||||||
// Returns slices of account balances and mapped YNAB account IDs, along with an error
|
// Returns slices of account balances and mapped YNAB account IDs, along with an error
|
||||||
func (p *Provider) GetBalances() ([]int, []string, error) {
|
func (p *Provider) GetBalances() ([]int, []string, error) {
|
||||||
var totalSats int64
|
var totalSats int64
|
||||||
var wg sync.WaitGroup
|
|
||||||
|
|
||||||
// branch 0 = regular
|
// branch 0 = regular
|
||||||
// branch 1 = change addresses
|
// branch 1 = change addresses
|
||||||
for _, branch := range []uint32{0, 1} {
|
for _, branch := range []uint32{0, 1} {
|
||||||
wg.Add(1)
|
branchSats, err := scanBranch(p.masterKey, branch, p.gapLimit, p.spvServer)
|
||||||
go func(branch uint32) {
|
if err != nil {
|
||||||
defer wg.Done()
|
return nil, nil, fmt.Errorf("failed to scan branch '%v': %v", branch, err)
|
||||||
branchSats := scanBranch(p.masterKey, branch, p.gapLimit, p.spvServer)
|
}
|
||||||
atomic.AddInt64(&branchSats, totalSats)
|
totalSats += branchSats
|
||||||
}(branch)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Wait()
|
|
||||||
|
|
||||||
cad, err := convertBTCToCAD(totalSats, p.coinGeckoApiKey)
|
cad, err := convertBTCToCAD(totalSats, p.coinGeckoApiKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Reference in New Issue
Block a user