Files
ynab-portfolio-monitor/providers/bitcoinElectrum/providerImpl.go
Steven Polley 5f11b45dd4
All checks were successful
continuous-integration/drone/push Build is passing
fiat conversion for electrum SPV provider
2025-09-30 22:54:23 -06:00

73 lines
1.8 KiB
Go

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()
cad, err := convertBTCToCAD(totalSats, p.coinGeckoApiKey)
if err != nil {
return nil, nil, fmt.Errorf("failed to convert sats to CAD: %v", err)
}
balances := make([]int, 0)
accounts := make([]string, 0)
balances = append(balances, int(cad))
accounts = append(accounts, p.ynabAccountID)
return balances, accounts, nil
}