Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: geovannyAvelar/brapigo
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v0.0.3
Choose a base ref
...
head repository: geovannyAvelar/brapigo
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: main
Choose a head ref
  • 15 commits
  • 10 files changed
  • 2 contributors

Commits on Nov 19, 2023

  1. Copy the full SHA
    a52485d View commit details
  2. Copy the full SHA
    8d16b68 View commit details
  3. Renaming test-data dir

    geovannyAvelar committed Nov 19, 2023
    Copy the full SHA
    b644253 View commit details
  4. Including makefile

    geovannyAvelar committed Nov 19, 2023
    Copy the full SHA
    bdcb3ad View commit details
  5. Including gitignore

    geovannyAvelar committed Nov 19, 2023
    Copy the full SHA
    de3a5af View commit details
  6. README.md

    geovannyAvelar committed Nov 19, 2023
    Copy the full SHA
    92af119 View commit details

Commits on Nov 25, 2023

  1. Fixing base url

    geovannyAvelar committed Nov 25, 2023
    Copy the full SHA
    4b143c7 View commit details
  2. Copy the full SHA
    81e6a0f View commit details
  3. Copy the full SHA
    6765088 View commit details
  4. .idea on gitignore

    geovannyAvelar committed Nov 25, 2023
    Copy the full SHA
    56be480 View commit details
  5. Copy the full SHA
    6e991db View commit details
  6. Copy the full SHA
    1454a42 View commit details
  7. Copy the full SHA
    5a11906 View commit details
  8. Copy the full SHA
    9754ae0 View commit details

Commits on Mar 31, 2024

  1. Create LICENSE.md

    geovannyAvelar authored Mar 31, 2024
    Copy the full SHA
    822935b View commit details
Showing with 467 additions and 153 deletions.
  1. +30 −0 .gitignore
  2. +9 −0 LICENSE.md
  3. +10 −0 Makefile
  4. +3 −0 README.md
  5. +154 −12 brapi.go
  6. +225 −0 brapi_test.go
  7. +0 −141 brapi_test_helper.go
  8. +36 −0 testdata/cryptocoins.json
  9. 0 {test-data → testdata}/list.json
  10. 0 {test-data → testdata}/quote_data.json
30 changes: 30 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Dependency directories (remove the comment below to include it)
# vendor/

# Go workspace file
go.work

# VSCode
.vscode

# Debug files
__debug_bin

# Goland files
.idea
9 changes: 9 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
MIT License

Copyright (c) 2022 Geovanny de Avelar Carneiro

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 changes: 10 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

test:
go test ./...

test-coverage:
go test ./... -coverprofile=coverage.out >> /dev/null
go tool cover -func coverage.out

lint:
golangci-lint run --enable-all
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# BrAPIGo

A Go client for brapi.dev, an API to collect Brazilian stocks data.
166 changes: 154 additions & 12 deletions brapi.go
Original file line number Diff line number Diff line change
@@ -2,23 +2,31 @@ package brapigo

import (
"encoding/json"
"io/ioutil"
"errors"
"io"
"net/http"
"strings"
"time"
)

const DEFAULT_BASE_URL = "https://brapi.dev"
const DEFAULT_BASE_URL = "https://brapi.dev/api"

func NewBrApi() BrApi {
return BrApi{baseUrl: DEFAULT_BASE_URL}
return BrApi{baseUrl: DEFAULT_BASE_URL, Client: &http.Client{
Timeout: 10 * time.Second,
}}
}

func NewBrApiWithCustomBaseUrl(baseUrl string) BrApi {
return BrApi{baseUrl}
return BrApi{baseUrl: baseUrl, Client: &http.Client{
Timeout: 10 * time.Second,
}}
}

type BrApi struct {
baseUrl string
Token string
Client *http.Client
}

type StockApiResponse struct {
@@ -52,33 +60,70 @@ type Quote struct {
RegularMarketPrice float64 `json:"RegularMarketPrice"`
}

type CoinsApiResponse struct {
Coins []string `json:"coins"`
}

type CryptoCoin struct {
Currency string `json:"currency"`
CurrencyRateFromUSD float64 `json:"currencyRateFromUSD"`
CoinName string `json:"coinName"`
Coin string `json:"coin"`
RegularMarketChange float64 `json:"regularMarketChange"`
RegularMarketPrice float64 `json:"regularMarketPrice"`
RegularMarketChangePercent float64 `json:"regularMarketChangePercent"`
RegularMarketDayLow float64 `json:"regularMarketDayLow"`
RegularMarketDayHigh float64 `json:"regularMarketDayHigh"`
RegularMarketDayRange string `json:"regularMarketDayRange"`
RegularMarketVolume float64 `json:"regularMarketVolume"`
MarketCap float64 `json:"marketCap"`
RegularMarketTime int `json:"regularMarketTime"`
CoinImageUrl string `json:"coinImageUrl"`
}

func (a BrApi) FindAssetByTicker(tickers ...string) ([]Quote, error) {
tickersParam := strings.Join(tickers, ",")
resp, err := http.Get(a.baseUrl + "/api/quote/" + tickersParam)

req, err := http.NewRequest("GET", a.baseUrl+"/quote/"+tickersParam, nil)

q := req.URL.Query()

if a.Token != "" {
q.Add("token", a.Token)
}

req.URL.RawQuery = q.Encode()

resp, err := a.Client.Do(req)

return parseQuoteResponse(resp, err)
}

func (a BrApi) SearchTickets(keyword string) ([]string, error) {
client := &http.Client{}
req, err := http.NewRequest("GET", a.baseUrl+"/available", nil)

req, err := http.NewRequest("GET", a.baseUrl+"/api/available", nil)
q := req.URL.Query()
q.Add("search", keyword)

if a.Token != "" {
q.Add("token", a.Token)
}

req.URL.RawQuery = q.Encode()

if err != nil {
return nil, err
}

resp, err := client.Do(req)
resp, err := a.Client.Do(req)

if err != nil {
return nil, err
}

defer resp.Body.Close()

responseData, err := ioutil.ReadAll(resp.Body)
responseData, err := io.ReadAll(resp.Body)

if err != nil {
return nil, err
@@ -95,16 +140,111 @@ func (a BrApi) SearchTickets(keyword string) ([]string, error) {
}

func (a BrApi) ListStocks() ([]Stock, error) {
resp, err := http.Get(a.baseUrl + "/api/quote/list")
req, err := http.NewRequest("GET", a.baseUrl+"/quote/list", nil)

q := req.URL.Query()

if a.Token != "" {
q.Add("token", a.Token)
}

req.URL.RawQuery = q.Encode()

if err != nil {
return nil, err
}

resp, err := a.Client.Do(req)

return parseStockResponse(resp, err)
}

func (a BrApi) ListCryptoCoins() ([]string, error) {
req, err := http.NewRequest("GET", a.baseUrl+"/v2/crypto/available", nil)

q := req.URL.Query()

if a.Token != "" {
q.Add("token", a.Token)
}

req.URL.RawQuery = q.Encode()

if err != nil {
return nil, err
}

resp, err := a.Client.Do(req)

responseData, err := io.ReadAll(resp.Body)

if err != nil {
return nil, err
}

coinsResponse := CoinsApiResponse{}
err = json.Unmarshal(responseData, &coinsResponse)

if err != nil {
return nil, err
}

return coinsResponse.Coins, nil
}

func (a BrApi) FindCryptoCoin(coins []string, currency string) ([]CryptoCoin, error) {
if len(coins) == 0 {
return nil, errors.New("it is necessary to inform at least one cryptocoin")
}

req, err := http.NewRequest("GET", a.baseUrl+"/v2/crypto", nil)

q := req.URL.Query()

if a.Token != "" {
q.Add("token", a.Token)
}

q.Add("coin", strings.Join(coins, ","))

if currency != "" {
q.Add("currency", currency)
}

req.URL.RawQuery = q.Encode()

if err != nil {
return nil, err
}

resp, err := a.Client.Do(req)

responseData, err := io.ReadAll(resp.Body)

if err != nil {
return nil, err
}

coinsRes := struct {
Coins []CryptoCoin `json:"coins"`
}{}
err = json.Unmarshal(responseData, &coinsRes)

if err != nil {
return nil, err
}

return coinsRes.Coins, nil
}

func parseStockResponse(resp *http.Response, err error) ([]Stock, error) {
if err != nil {
return nil, err
}

responseData, err := ioutil.ReadAll(resp.Body)
defer resp.Body.Close()

responseData, err := io.ReadAll(resp.Body)

if err != nil {
return nil, err
@@ -125,7 +265,9 @@ func parseQuoteResponse(resp *http.Response, err error) ([]Quote, error) {
return nil, err
}

responseData, err := ioutil.ReadAll(resp.Body)
defer resp.Body.Close()

responseData, err := io.ReadAll(resp.Body)

if err != nil {
return nil, err
Loading