ynab-portfolio-monitor/providers/bitcoin/providerImpl.go

75 lines
2.3 KiB
Go
Raw Normal View History

package bitcoin
import (
"fmt"
2024-09-01 15:05:21 +00:00
"log"
"os"
2024-09-01 15:05:21 +00:00
"sync"
)
type Provider struct {
bitcoinAddresses []string // Slice of bitcoin addresses this provider monitors
ynabAccountID string // YNAB account ID this provider updates - all bitcoin addresses are summed up and mapped to this YNAB account
client *client // HTTP client for interacting with Questrade API
}
func (p *Provider) Name() string {
return "Bitcoin - Blockstream.info / CoinGecko"
}
// Configures the provider for usage via environment variables and persistentData
// If an error is returned, the provider will not be used
func (p *Provider) Configure() error {
// Load environment variables in continous series with suffix starting at 0
// Multiple addresses can be configured, (eg _1, _2)
// As soon as the series is interrupted, we assume we're done
p.bitcoinAddresses = make([]string, 0)
for i := 0; true; i++ {
bitcoinAddress := os.Getenv(fmt.Sprintf("bitcoin_address_%d", i))
if bitcoinAddress == "" {
if i == 0 {
return fmt.Errorf("this account provider is not configured")
}
break
}
p.bitcoinAddresses = append(p.bitcoinAddresses, bitcoinAddress)
}
p.ynabAccountID = os.Getenv("bitcoin_ynab_account")
// Create new HTTP client
p.client = newClient(os.Getenv("bitcoin_coingecko_api_key"))
return nil
}
// Returns slices of account balances and mapped YNAB account IDs, along with an error
func (p *Provider) GetBalances() ([]int, []string, error) {
balances := make([]int, 0)
ynabAccountIDs := make([]string, 0)
var satoshiBalance int
2024-09-01 15:05:21 +00:00
wg := sync.WaitGroup{}
2024-09-01 15:05:21 +00:00
for _, bitcoinAddress := range p.bitcoinAddresses {
wg.Add(1)
go func() {
defer wg.Done()
addressResponse, err := p.client.getAddress(bitcoinAddress)
if err != nil {
log.Printf("failed to get bitcoin address '%s': %v", bitcoinAddress, err)
}
satoshiBalance += addressResponse.ChainStats.FundedTxoSum - addressResponse.ChainStats.SpentTxoSum
}()
}
2024-09-01 15:05:21 +00:00
wg.Wait()
2024-03-23 20:06:38 +00:00
fiatBalance, err := p.client.convertBTCToCAD(satoshiBalance)
if err != nil {
return balances, ynabAccountIDs, fmt.Errorf("failed to convert satoshi balance to fiat balance: %v", err)
}
balances = append(balances, fiatBalance)
ynabAccountIDs = append(ynabAccountIDs, p.ynabAccountID)
return balances, ynabAccountIDs, nil
}