package bitcoinElectrum import ( "fmt" "os" "sync" "sync/atomic" "github.com/btcsuite/btcd/btcutil/hdkeychain" ) type Provider struct { masterKey *hdkeychain.ExtendedKey ynabAccountID string // YNAB account ID this provider updates - all bitcoin addresses are summed up and mapped to this YNAB account spvServer string gapLimit int coinGeckoApiKey string } func (p *Provider) Name() string { return "Bitcoin - Electrum SPV" } func (p *Provider) Configure() error { var err error zpub := os.Getenv("bitcoin_zpub") p.ynabAccountID = os.Getenv("bitcoin_ynab_account") p.spvServer = os.Getenv("bitcoin_spv_server") p.coinGeckoApiKey = os.Getenv("bitcoin_coingecko_api_key") p.gapLimit = 20 if zpub == "" || p.ynabAccountID == "" || p.spvServer == "" || p.coinGeckoApiKey == "" { return fmt.Errorf("this account provider is not configured") } p.masterKey, err = hdkeychain.NewKeyFromString(zpub) if err != nil { return fmt.Errorf("failed to obtain master key from zpub: %v", err) } return nil } // Returns slices of account balances and mapped YNAB account IDs, along with an error func (p *Provider) GetBalances() ([]int, []string, error) { var totalSats int64 var wg sync.WaitGroup // branch 0 = regular // branch 1 = change addresses for _, branch := range []uint32{0, 1} { wg.Add(1) go func(branch uint32) { defer wg.Done() branchSats := scanBranch(p.masterKey, branch, p.gapLimit, p.spvServer) atomic.AddInt64(&branchSats, totalSats) }(branch) } wg.Wait() return nil, nil, nil }