github.com/wtfutil/wtf@v0.43.0/modules/cryptocurrency/blockfolio/widget.go (about)

     1  package blockfolio
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io"
     7  	"log"
     8  	"net/http"
     9  
    10  	"github.com/rivo/tview"
    11  	"github.com/wtfutil/wtf/view"
    12  )
    13  
    14  type Widget struct {
    15  	view.TextWidget
    16  
    17  	device_token string
    18  	settings     *Settings
    19  }
    20  
    21  func NewWidget(tviewApp *tview.Application, redrawChan chan bool, settings *Settings) *Widget {
    22  	widget := Widget{
    23  		TextWidget: view.NewTextWidget(tviewApp, redrawChan, nil, settings.Common),
    24  
    25  		device_token: settings.deviceToken,
    26  		settings:     settings,
    27  	}
    28  
    29  	return &widget
    30  }
    31  
    32  /* -------------------- Exported Functions -------------------- */
    33  
    34  func (widget *Widget) Refresh() {
    35  
    36  	widget.Redraw(widget.content)
    37  }
    38  
    39  /* -------------------- Unexported Functions -------------------- */
    40  func (widget *Widget) content() (string, string, bool) {
    41  	positions, err := Fetch(widget.device_token)
    42  	title := widget.CommonSettings().Title
    43  	if err != nil {
    44  		return title, err.Error(), true
    45  	}
    46  
    47  	res := ""
    48  	totalFiat := float32(0.0)
    49  
    50  	for i := 0; i < len(positions.PositionList); i++ {
    51  		colorForChange := widget.settings.colors.grows
    52  
    53  		if positions.PositionList[i].TwentyFourHourPercentChangeFiat <= 0 {
    54  			colorForChange = widget.settings.colors.drop
    55  		}
    56  
    57  		totalFiat += positions.PositionList[i].HoldingValueFiat
    58  
    59  		if widget.settings.displayHoldings {
    60  			res += fmt.Sprintf(
    61  				"[%s]%-6s - %5.2f ([%s]%.3fk [%s]%.2f%s)\n",
    62  				widget.settings.colors.name,
    63  				positions.PositionList[i].Coin,
    64  				positions.PositionList[i].Quantity,
    65  				colorForChange,
    66  				positions.PositionList[i].HoldingValueFiat/1000,
    67  				colorForChange,
    68  				positions.PositionList[i].TwentyFourHourPercentChangeFiat,
    69  				"%",
    70  			)
    71  		} else {
    72  			res += fmt.Sprintf(
    73  				"[%s]%-6s - %5.2f ([%s]%.2f%s)\n",
    74  				widget.settings.colors.name,
    75  				positions.PositionList[i].Coin,
    76  				positions.PositionList[i].Quantity,
    77  				colorForChange,
    78  				positions.PositionList[i].TwentyFourHourPercentChangeFiat,
    79  				"%",
    80  			)
    81  		}
    82  	}
    83  
    84  	if widget.settings.displayHoldings {
    85  		res += fmt.Sprintf("\n[%s]Total value: $%.3fk", "green", totalFiat/1000)
    86  	}
    87  
    88  	return title, res, true
    89  }
    90  
    91  // always the same
    92  const magic = "edtopjhgn2345piuty89whqejfiobh89-2q453"
    93  
    94  type Position struct {
    95  	Coin                            string  `json:"coin"`
    96  	LastPriceFiat                   float32 `json:"lastPriceFiat"`
    97  	TwentyFourHourPercentChangeFiat float32 `json:"twentyFourHourPercentChangeFiat"`
    98  	Quantity                        float32 `json:"quantity"`
    99  	HoldingValueFiat                float32 `json:"holdingValueFiat"`
   100  }
   101  
   102  type AllPositionsResponse struct {
   103  	PositionList []Position `json:"positionList"`
   104  }
   105  
   106  func MakeApiRequest(token string, method string) ([]byte, error) {
   107  	client := &http.Client{}
   108  	url := "https://api-v0.blockfolio.com/rest/" + method + "/" + token + "?use_alias=true&fiat_currency=USD"
   109  	req, err := http.NewRequest("GET", url, http.NoBody)
   110  	if err != nil {
   111  		return nil, err
   112  	}
   113  	req.Header.Add("magic", magic)
   114  	resp, err := client.Do(req)
   115  	if err != nil {
   116  		return nil, err
   117  	}
   118  	defer func() { _ = resp.Body.Close() }()
   119  	body, err := io.ReadAll(resp.Body)
   120  	if err != nil {
   121  		return nil, err
   122  	}
   123  	return body, err
   124  }
   125  
   126  func GetAllPositions(token string) (*AllPositionsResponse, error) {
   127  	jsn, _ := MakeApiRequest(token, "get_all_positions")
   128  	var parsed AllPositionsResponse
   129  
   130  	err := json.Unmarshal(jsn, &parsed)
   131  	if err != nil {
   132  		log.Fatalf("Failed to parse json %v", err)
   133  		return nil, err
   134  	}
   135  	return &parsed, err
   136  }
   137  
   138  func Fetch(token string) (*AllPositionsResponse, error) {
   139  	return GetAllPositions(token)
   140  }