package staticjsonFinnhub import ( "encoding/json" "errors" "fmt" "io" "os" ) type security struct { Symbol string `json:"symbol"` Quantity int `json:"quantity"` } type account struct { YnabAccountID string `json:"ynabAccountId"` Securities []security `json:"securities"` } type inputData struct { Accounts []account `json:"accounts"` } type Provider struct { data *inputData // Data stored on disk and loaded when program starts client *client // HTTP client for interacting with Finnhub API } func (p *Provider) Name() string { return "Static JSON - Finnhub" } // Configures the provider for usage via environment variables and inputData // If an error is returned, the provider will not be used func (p *Provider) Configure() error { var err error // Load input data from disk p.data, err = loadInputData() if err != nil { return err } b, _ := json.Marshal(p.data) fmt.Println(string(b)) apiKey := os.Getenv("staticjson_finnhub_key") if apiKey == "" { return fmt.Errorf("this account provider is not configured: missing staticjson_finnhub_key environment variable") } p.client, err = newClient(apiKey) if err != nil { return fmt.Errorf("failed to create new client: %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) { balances := make([]int, 0) ynabAccountIDs := make([]string, 0) for i := range p.data.Accounts { balance := 0 for j := range p.data.Accounts[i].Securities { price, err := p.client.getQuote(p.data.Accounts[i].Securities[j].Symbol) if err != nil { return balances, ynabAccountIDs, fmt.Errorf("failed to get quote for security with symbol '%s': %v", p.data.Accounts[i].Securities[j].Symbol, err) } balance += price * p.data.Accounts[i].Securities[j].Quantity } balances = append(balances, balance) ynabAccountIDs = append(ynabAccountIDs, p.data.Accounts[i].YnabAccountID) } return balances, ynabAccountIDs, nil } // Load input data from disk func loadInputData() (*inputData, error) { data := &inputData{} f, err := os.Open("data/staticjsonFinnhub-data.json") if errors.Is(err, os.ErrNotExist) { return nil, fmt.Errorf("this account provider is not configured: missing data/staticjsonFinnhub-data.json") } defer f.Close() b, err := io.ReadAll(f) if err != nil { return nil, fmt.Errorf("failed to read file data/staticjsonFinnhub-data.json: %v", err) } err = json.Unmarshal(b, data) if err != nil { return nil, fmt.Errorf("failed to unmarshal data/staticjsonFinnhub-data.json to inputData struct: %v", err) } return data, nil }