Skip to content

Commit

Permalink
Refactor (#28)
Browse files Browse the repository at this point in the history
* Refactor

* Handle connection drops and reconnect

* Increase verbosity

* Fix config file path

* Fix readme

* Add interval

* Write and read feeds by ticker

* Rename daemon to client

* Add comment to explain kraken feeder code
  • Loading branch information
altafan authored Sep 6, 2021
1 parent 259c07d commit 6a5f8af
Show file tree
Hide file tree
Showing 37 changed files with 1,472 additions and 1,474 deletions.
16 changes: 7 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.PHONY: build run clean cov fmt help vet test shorttest integrationtest

## build-arm: build binary for ARM
## build: builds binary for all platforms
build:
chmod u+x ./scripts/build
./scripts/build
Expand All @@ -15,7 +15,7 @@ cov:
@echo "Coverage..."
go test -cover ./...

## fmt: Go Format
## fmt: checks if code is well formatted
fmt:
@echo "Gofmt..."
@if [ -n "$(gofmt -l .)" ]; then echo "Go code is not formatted"; exit 1; fi
Expand All @@ -26,24 +26,22 @@ help:
@echo "Usage: \n"
@sed -n 's/^##//p' ${MAKEFILE_LIST} | column -t -s ':' | sed -e 's/^/ /'

## run-linux: Run locally with default configuration
# run: runs locally without building binary
run: clean
export FEEDER_CONFIG_PATH=./config.example.json; \
export FEEDER_LOG_LEVEL=5; \
go run cmd/feederd/main.go

## vet: code analysis
vet:
@echo "Vet..."
@echo "Vetting..."
@go vet ./...

## test: runs go unit test with default values
test: fmt shorttest

shorttest:
## test: runs unit tests
test: fmt
@echo "Testing..."
go test -v -count=1 -race -short ./...

## integrationtest: run integration tests
integrationtest:
export FEEDER_CONFIG_PATH="./config.test.json"; \
export FEEDER_LOG_LEVEL=5; \
Expand Down
45 changes: 24 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ Feeder allows to connect several price feeds to TDex Daemon(s) in order to autom

## Overview

tdex-feeder connects to exchanges and retrieves market prices in order to consume the gRPC
interface exposed from tdex-deamon `UpdateMarketPrice`.

tdex-feeder connects to exchanges and forwards market(s) price feeds to some tdex-daemon(s) by consuming its `UpdateMarketPrice` RPC.
![tdex-schema](./tdexfeeder.png)

## ⬇️ Run Standalone
Expand Down Expand Up @@ -58,31 +56,36 @@ the `$HOME/config.json` is the path to the feederd configuration file.
### Build it yourself

Builds feeder as static binary and runs the project with default configuration.

#### Linux

`make build-linux`

#### Mac
Build feeder as static binary and run the project with default configuration.

`make build-mac`
```sh
# build feeder as a static binary
$ make build

#### Run Linux
# run the binary on Linux
$ ./build/feederd-linux-amd64

`make run-linux`
# run the binary on MacOS
$ ./build/feederd-darwin-amd64
```

##### Config file

Rename the file `./config.example.json` into `./config.json`
and adapt if for your specific purpose. The default example
connects to kraken socket and to a local instance of tdex-deamon.
uses kraken as price feeder and forwards the feeds related to the BTC/USDT market to a local daemon (with mac auth disabled).

NOTE: All entries of the JSON configuration file are mandatory if not otherwise expressed. Below you can find a brief explanation of the JSON object.

```
daemon_endpoint: String with the address and port of gRPC host. Required.
market: Json List with necessary markets informations. Required.
base_asset: String of the Hash of the base asset for gRPC request. Required.
quote_asset: String of the Hash of the quote asset for gRPC request. Required.
kraken_ticker: String with the ticker we want kraken to provide informations on. Required.
interval: the minimum time in milliseconds between two updateMarketPrice requests. Required.
```
price_feeder: service where to source prices (only "kraken" available for now).
interval: the period in millisecond with which the feeder updates its target(s).
markets: list with necessary markets info.
base_asset: hex string of the hash of the market base asset.
quote_asset: hex string of the hash of the market quote asset.
ticker: string of the corresponding feeder's market ticker.
targets: list of daemons to update for every feed received on this market.
rpc_address: string with hostname and port of the target daemon.
tls_cert_path: string path of the TLS cert file to use to connect with the target daemon. Optional.
macaroons_path: string path of the macaroon file to use to connect with the target daemon. Optional.
```
1 change: 0 additions & 1 deletion cmd/feederd/config.test.json

This file was deleted.

105 changes: 60 additions & 45 deletions cmd/feederd/main.go
Original file line number Diff line number Diff line change
@@ -1,70 +1,85 @@
// Copyright (c) 2020 The VulpemVentures developers

// Feeder allows to connect an external price feed to the TDex Daemon to determine the current market price.
package main

import (
"encoding/json"
"io/ioutil"
"os"
"os/signal"
"syscall"

log "github.com/sirupsen/logrus"
"github.com/tdex-network/tdex-feeder/config"
"github.com/tdex-network/tdex-feeder/internal/adapters"
"github.com/tdex-network/tdex-feeder/internal/application"
)

func main() {
// Interrupt Notification.
interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, syscall.SIGTERM, syscall.SIGINT)

// retrieve feeder service from config file
feeder := configFileToFeederService(config.GetConfigPath())
"github.com/tdex-network/tdex-feeder/internal/config"
"github.com/tdex-network/tdex-feeder/internal/core/application"
grpcclient "github.com/tdex-network/tdex-feeder/internal/core/infrastructure/client/grpc"
krakenfeeder "github.com/tdex-network/tdex-feeder/internal/core/infrastructure/feeder/kraken"
"github.com/tdex-network/tdex-feeder/internal/core/ports"
)

log.Info("Start the feeder...")
go func() {
err := feeder.Start()
if err != nil {
log.Fatal(err)
}
}()
type indexedPriceFeeders map[string]func(args ...interface{}) (ports.PriceFeeder, error)

// check for interupt
<-interrupt
log.Info("Shutting down the feeder...")
err := feeder.Stop()
log.Info("Feeder service stopped")
if err != nil {
log.Fatal(err)
func (i indexedPriceFeeders) supported() []string {
keys := make([]string, 0, len(i))
for k := range i {
keys = append(keys, k)
}
os.Exit(0)
return keys
}

func configFileToFeederService(configFilePath string) application.FeederService {
jsonFile, err := os.Open(configFilePath)
if err != nil {
log.Fatal(err)
var (
priceFeeders = indexedPriceFeeders{
"kraken": krakenfeeder.NewKrakenPriceFeeder,
}
defer jsonFile.Close()
)

configBytes, err := ioutil.ReadAll(jsonFile)
func main() {
cfg, err := config.NewConfigFromFile()
if err != nil {
log.Fatal(err)
log.WithError(err).Fatalf(
"error while reading config from file %s", config.GetConfigPath(),
)
}

config := &adapters.Config{}
err = json.Unmarshal(configBytes, config)
if err != nil {
log.Fatal(err)
priceFeederFactory, ok := priceFeeders[cfg.PriceFeeder]
if !ok {
log.Fatalf(
"price feeder must be one of: '%s'", priceFeeders.supported(),
)
}

feeder, err := config.ToFeederService()
priceFeeder, err := priceFeederFactory(cfg.Interval, cfg.PortableMarkets())
if err != nil {
log.Fatal(err)
log.WithError(err).Fatal("error while initializing price feeder")
}

indexedTargets := make(application.IndexedTargetsByMarket)
for _, mkt := range cfg.Markets {
targets := make(map[string]ports.TdexClient)
for _, t := range mkt.CTargets {
target, err := grpcclient.NewGRPCClient(t.RPCAddress, t.MacaroonsPath, t.TLSCertPath)
if err != nil {
log.WithError(err).Fatalf(
"error while connecting with target %s", t.RPCAddress,
)
}
targets[target.RPCAddress()] = target
}
mktKey := ports.MarketKey(mkt)
indexedTargets[mktKey] = targets
}

return feeder
app := application.NewService(priceFeeder, indexedTargets)

defer app.Stop()

log.Info("starting service")
go func() {
if err := app.Start(); err != nil {
log.WithError(err).Fatal("service exited with error")
}
}()

sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGINT)
<-sigChan

log.Info("shutting down")
}
Loading

0 comments on commit 6a5f8af

Please sign in to comment.