diff options
| author | terminaldweller <devi@terminaldweller.com> | 2024-06-06 01:42:03 +0000 | 
|---|---|---|
| committer | terminaldweller <devi@terminaldweller.com> | 2024-06-06 01:42:03 +0000 | 
| commit | 8784899e25b362c570cb65f671f11e3bfa9685fc (patch) | |
| tree | 3f52241c179735a61d5b0eacaebf9bf8c22241ea /arbiter | |
| parent | WIP (diff) | |
| download | hived-arbitrage.tar.gz hived-arbitrage.zip  | |
cleaned up the code, removed extranneous microservices. hived is a monolith again. using pocketbase for AAA.arbitrage
Diffstat (limited to '')
| -rw-r--r-- | arbiter/.golangci.yml | 18 | ||||
| -rw-r--r-- | arbiter/Dockerfile | 18 | ||||
| -rw-r--r-- | arbiter/arbiter.go | 505 | ||||
| -rw-r--r-- | arbiter/go.mod | 17 | ||||
| -rw-r--r-- | arbiter/go.sum | 41 | ||||
| -rwxr-xr-x | arbiter/tests.sh | 4 | 
6 files changed, 0 insertions, 603 deletions
diff --git a/arbiter/.golangci.yml b/arbiter/.golangci.yml deleted file mode 100644 index 878e031..0000000 --- a/arbiter/.golangci.yml +++ /dev/null @@ -1,18 +0,0 @@ -run: -  concurrency: 16 -  timeout: 5m -  modules-download-mode: readonly -  allow-parallel-runners: true -  allow-serial-runners: true -  go: '1.22' -linters-settings: -  depguard: -    rules: -      srcs: -        listMode: "Strict" -        allow: -        - $gostd -        - github.com/go-redis/redis/v8 -        - github.com/gorilla/mux -        - github.com/rs/zerolog -        - github.com/rs/zerolog/log diff --git a/arbiter/Dockerfile b/arbiter/Dockerfile deleted file mode 100644 index a512798..0000000 --- a/arbiter/Dockerfile +++ /dev/null @@ -1,18 +0,0 @@ -FROM golang:1.22-alpine3.19 as builder -RUN apk update && apk upgrade -RUN apk add go git -COPY go.* /arbiter/ -RUN cd /arbiter && go mod download -COPY *.go /arbiter/ -RUN cd /arbiter && go build - -FROM alpine:3.19 as certbuilder -RUN apk add openssl -WORKDIR /certs -RUN openssl req -nodes -new -x509 -subj="/C=US/ST=Denial/L=springfield/O=Dis/CN=localhost" -keyout server.key -out server.cert - -# FROM gcr.io/distroless/static-debian10 -FROM alpine:3.19 -COPY --from=certbuilder /certs /certs -COPY --from=builder /arbiter/arbiter /arbiter/ -ENTRYPOINT ["/arbiter/arbiter"] diff --git a/arbiter/arbiter.go b/arbiter/arbiter.go deleted file mode 100644 index 6145a45..0000000 --- a/arbiter/arbiter.go +++ /dev/null @@ -1,505 +0,0 @@ -package main - -import ( -	"context" -	"crypto/tls" -	"encoding/json" -	"errors" -	"flag" -	"io" -	"net/http" -	"net/url" -	"os" -	"os/signal" -	"strconv" -	"sync" -	"time" - -	"github.com/go-redis/redis/v8" -	"github.com/gorilla/mux" -	"github.com/rs/zerolog" -	"github.com/rs/zerolog/log" -) - -var ( -	errBadLogic          = errors.New("we should not be here") -	errUnexpectedParam   = errors.New("got unexpected parameter") -	errUnknownDeployment = errors.New("unknown deployment kind") -) - -const ( -	serverDeploymentType    = "SERVER_DEPLOYMENT_TYPE" -	coingeckoAPIURLv3       = "https://api.coingecko.com/api/v3" -	coincapAPIURLv2         = "https://api.coincap.io/v2" -	getTimeout              = 5 -	httpClientTimeout       = 5 -	serverTLSReadTimeout    = 15 -	serverTLSWriteTimeout   = 15 -	defaultGracefulShutdown = 15 -) - -// https://docs.coincap.io/ -type CoinCapAssetGetResponseData struct { -	ID                string `json:"id"` -	Rank              string `json:"rank"` -	Symbol            string `json:"symbol"` -	Name              string `json:"name"` -	Supply            string `json:"supply"` -	MaxSupply         string `json:"maxSupply"` -	MarketCapUsd      string `json:"marketCapUsd"` -	VolumeUsd24Hr     string `json:"volumeUsd24Hr"` -	PriceUsd          string `json:"priceUsd"` -	ChangePercent24Hr string `json:"changePercent24Hr"` -	Vwap24Hr          string `json:"vwap24Hr"` -} - -type priceResponseData struct { -	Name         string  `json:"name"` -	Price        float64 `json:"price"` -	Unit         string  `json:"unit"` -	Err          string  `json:"err"` -	IsSuccessful bool    `json:"isSuccessful"` -} - -type CoinCapAssetGetResponse struct { -	Data      CoinCapAssetGetResponseData `json:"data"` -	TimeStamp int64                       `json:"timestamp"` -} - -type HTTPHandlerFunc func(http.ResponseWriter, *http.Request) - -type HTTPHandler struct { -	name     string -	function HTTPHandlerFunc -} - -type priceChanStruct struct { -	name  string -	price float64 -} - -type errorChanStruct struct { -	hasError bool -	err      error -} - -func GetProxiedClient() *http.Client { -	transport := &http.Transport{ -		DisableKeepAlives: true, -		Proxy:             http.ProxyFromEnvironment, -	} -	client := &http.Client{ -		Transport:     transport, -		Timeout:       httpClientTimeout * time.Second, -		CheckRedirect: nil, -		Jar:           nil, -	} - -	return client -} - -// OWASP: https://cheatsheetseries.owasp.org/cheatsheets/REST_Security_Cheat_Sheet.html -func addSecureHeaders(writer *http.ResponseWriter) { -	(*writer).Header().Set("Cache-Control", "no-store") -	(*writer).Header().Set("Content-Security-Policy", "default-src https;") -	(*writer).Header().Set("Strict-Transport-Security", "max-age=63072000;") -	(*writer).Header().Set("X-Content-Type-Options", "nosniff") -	(*writer).Header().Set("X-Frame-Options", "DENY") -	(*writer).Header().Set("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS") -} - -func getPriceFromCoinGecko( -	ctx context.Context, -	name, unit string, -	wg *sync.WaitGroup, -	priceChan chan<- priceChanStruct, -	errChan chan<- errorChanStruct, -) { -	defer wg.Done() - -	priceFloat := 0. - -	params := "/simple/price?ids=" + url.QueryEscape(name) + "&" + -		"vs_currencies=" + url.QueryEscape(unit) -	path := coingeckoAPIURLv3 + params - -	client := GetProxiedClient() - -	req, err := http.NewRequestWithContext(ctx, http.MethodGet, path, nil) -	if err != nil { -		priceChan <- priceChanStruct{name: name, price: priceFloat} -		errChan <- errorChanStruct{hasError: true, err: err} - -		log.Error().Err(err) - -		return -	} - -	resp, err := client.Do(req) -	if err != nil { -		priceChan <- priceChanStruct{name: name, price: priceFloat} -		errChan <- errorChanStruct{hasError: true, err: err} - -		log.Error().Err(err).Send() - -		return -	} -	defer resp.Body.Close() - -	body, err := io.ReadAll(resp.Body) -	if err != nil { -		priceChan <- priceChanStruct{name: name, price: priceFloat} -		errChan <- errorChanStruct{hasError: true, err: err} - -		log.Error().Err(err).Send() -	} - -	jsonBody := make(map[string]interface{}) - -	err = json.Unmarshal(body, &jsonBody) -	if err != nil { -		priceChan <- priceChanStruct{name: name, price: priceFloat} -		errChan <- errorChanStruct{hasError: true, err: err} - -		log.Error().Err(err).Send() -	} - -	price, isOk := jsonBody[name].(map[string]interface{}) -	if !isOk { -		priceChan <- priceChanStruct{name: name, price: priceFloat} -		errChan <- errorChanStruct{hasError: true, err: err} - -		log.Error().Err(err) - -		return -	} - -	log.Info().Msg(string(body)) - -	priceFloat, isOk = price[unit].(float64) -	if !isOk { -		priceChan <- priceChanStruct{name: name, price: priceFloat} -		errChan <- errorChanStruct{hasError: true, err: err} - -		log.Error().Err(err) - -		return -	} - -	priceChan <- priceChanStruct{name: name, price: priceFloat} -	errChan <- errorChanStruct{hasError: false, err: nil} -} - -func getPriceFromCoinCap( -	ctx context.Context, -	name string, -	wg *sync.WaitGroup, -	priceChan chan<- priceChanStruct, -	errChan chan<- errorChanStruct, -) { -	defer wg.Done() - -	priceFloat := 0. - -	params := "/assets/" + url.QueryEscape(name) -	path := coincapAPIURLv2 + params - -	client := GetProxiedClient() - -	req, err := http.NewRequestWithContext(ctx, http.MethodGet, path, nil) -	if err != nil { -		priceChan <- priceChanStruct{name: name, price: priceFloat} -		errChan <- errorChanStruct{hasError: true, err: err} - -		log.Error().Err(err) - -		return -	} - -	resp, err := client.Do(req) -	if err != nil { -		priceChan <- priceChanStruct{name: name, price: priceFloat} -		errChan <- errorChanStruct{hasError: true, err: err} - -		log.Error().Err(err).Send() - -		return -	} -	defer resp.Body.Close() - -	body, err := io.ReadAll(resp.Body) -	if err != nil { -		priceChan <- priceChanStruct{name: name, price: priceFloat} -		errChan <- errorChanStruct{hasError: true, err: err} - -		log.Error().Err(err) -	} - -	var coinCapAssetGetResponse CoinCapAssetGetResponse - -	err = json.Unmarshal(body, &coinCapAssetGetResponse) -	if err != nil { -		priceChan <- priceChanStruct{name: name, price: priceFloat} -		errChan <- errorChanStruct{hasError: true, err: err} - -		log.Error().Err(err).Send() -	} - -	priceFloat, err = strconv.ParseFloat(coinCapAssetGetResponse.Data.PriceUsd, 64) -	if err != nil { -		priceChan <- priceChanStruct{name: name, price: priceFloat} -		errChan <- errorChanStruct{hasError: true, err: err} - -		log.Error().Err(err).Send() -	} - -	log.Info().Msg(string(body)) - -	priceChan <- priceChanStruct{name: name, price: priceFloat} -	errChan <- errorChanStruct{hasError: false, err: nil} -} - -func arbHandler(w http.ResponseWriter, r *http.Request) { -	w.Header().Add("Content-Type", "application/json") - -	if r.Method != http.MethodGet { -		http.Error(w, "Method is not supported.", http.StatusNotFound) -	} - -	addSecureHeaders(&w) - -	var name string - -	var unit string - -	params := r.URL.Query() -	for key, value := range params { -		switch key { -		case "name": -			name = value[0] -		case "unit": -			unit = value[0] -		default: -			log.Error().Err(errUnexpectedParam) -		} -	} - -	priceChan := make(chan priceChanStruct, 1) -	errChan := make(chan errorChanStruct, 1) - -	var waitGroup sync.WaitGroup - -	ctx, cancel := context.WithTimeout(context.Background(), getTimeout*time.Second) -	defer cancel() - -	waitGroup.Add(1) - -	//nolint:contextcheck -	getPriceFromCoinGecko(ctx, name, unit, &waitGroup, priceChan, errChan) -	waitGroup.Wait() - -	select { -	case err := <-errChan: -		if err.hasError { -			log.Error().Err(err.err) -		} -	default: -		log.Error().Err(errBadLogic).Send() -	} - -	var price priceChanStruct -	select { -	case priceCh := <-priceChan: -		price = priceCh -	default: -		log.Error().Err(errBadLogic) -	} - -	responseData := priceResponseData{ -		Name:         price.name, -		Price:        price.price, -		Unit:         "USD", -		Err:          "", -		IsSuccessful: true, -	} - -	jsonResp, err := json.Marshal(responseData) -	if err != nil { -		cancel() -		//nolint:gocritic -		log.Fatal().Err(err) -	} - -	_, err = w.Write(jsonResp) -	if err != nil { -		cancel() -		log.Fatal().Err(err) -	} -} - -func coincapHandler(w http.ResponseWriter, r *http.Request) { -	if r.Method != http.MethodGet { -		http.Error(w, "Method is not supported.", http.StatusNotFound) -	} - -	w.Header().Add("Content-Type", "application/json") - -	addSecureHeaders(&w) - -	var name string - -	params := r.URL.Query() -	for key, value := range params { -		switch key { -		case "name": -			name = value[0] -		default: -			log.Error().Err(errUnexpectedParam).Send() -		} -	} - -	priceChan := make(chan priceChanStruct, 1) -	errChan := make(chan errorChanStruct, 1) - -	var waitGroup sync.WaitGroup - -	waitGroup.Add(1) - -	ctx, cancel := context.WithTimeout(context.Background(), getTimeout*time.Second) -	defer cancel() - -	getPriceFromCoinCap(ctx, name, &waitGroup, priceChan, errChan) -	waitGroup.Wait() - -	select { -	case err := <-errChan: -		if err.hasError { -			log.Error().Err(err.err) -		} -	default: -		log.Error().Err(errBadLogic) -	} - -	var price priceChanStruct -	select { -	case priceCh := <-priceChan: -		price = priceCh -	default: -		log.Error().Err(errBadLogic) -	} - -	responseData := priceResponseData{ -		Name:         price.name, -		Price:        price.price, -		Unit:         "USD", -		Err:          "", -		IsSuccessful: true, -	} - -	jsonResp, err := json.Marshal(responseData) -	if err != nil { -		cancel() - -		log.Fatal().Err(err).Send() -	} - -	_, err = w.Write(jsonResp) -	if err != nil { -		cancel() -		log.Fatal().Err(err) -	} -} - -func setupLogging() { -	zerolog.TimeFieldFormat = zerolog.TimeFormatUnix -} - -func startServer(gracefulWait time.Duration, -	handlers []HTTPHandler, -	serverDeploymentType string, port string, -) { -	route := mux.NewRouter() -	cfg := &tls.Config{ -		MinVersion: tls.VersionTLS13, -	} - -	srv := &http.Server{ -		Addr:         "0.0.0.0:" + port, -		WriteTimeout: time.Second * serverTLSWriteTimeout, -		ReadTimeout:  time.Second * serverTLSReadTimeout, -		Handler:      route, -		TLSConfig:    cfg, -	} - -	for i := range len(handlers) { -		route.HandleFunc(handlers[i].name, handlers[i].function) -	} - -	go func() { -		var certPath, keyPath string - -		switch os.Getenv(serverDeploymentType) { -		case "deployment": -			certPath = "/etc/letsencrypt/live/api.terminaldweller.com/fullchain.pem" -			keyPath = "/etc/letsencrypt/live/api.terminaldweller.com/privkey.pem" -		case "test": -			certPath = "/certs/server.cert" -			keyPath = "/certs/server.key" -		default: -			log.Error().Err(errUnknownDeployment).Send() -		} - -		if err := srv.ListenAndServeTLS(certPath, keyPath); err != nil { -			log.Error().Err(err) -		} -	}() - -	c := make(chan os.Signal, 1) - -	signal.Notify(c, os.Interrupt) -	<-c - -	ctx, cancel := context.WithTimeout(context.Background(), gracefulWait) -	defer cancel() - -	if err := srv.Shutdown(ctx); err != nil { -		log.Error().Err(err) -	} - -	log.Info().Msg("gracefully shut down the server") -} - -func main() { -	var gracefulWait time.Duration - -	var rdb *redis.Client - -	flag.DurationVar( -		&gracefulWait, -		"gracefulwait", -		time.Second*defaultGracefulShutdown, -		"the duration to wait during the graceful shutdown", -	) - -	flagPort := flag.String("port", "8009", "determines the port the server will listen on") -	redisDB := flag.Int64("redisdb", 1, "determines the db number") -	redisAddress := flag.String("redisaddress", "redis:6379", "determines the address of the redis instance") -	redisPassword := flag.String("redispassword", "", "determines the password of the redis db") -	flag.Parse() - -	rdb = redis.NewClient(&redis.Options{ -		Addr:     *redisAddress, -		Password: *redisPassword, -		DB:       int(*redisDB), -	}) -	defer rdb.Close() - -	setupLogging() - -	handlerFuncs := []HTTPHandler{ -		{name: "/crypto/v1/arb/gecko", function: arbHandler}, -		{name: "/crypto/v1/arb/coincap", function: coincapHandler}, -	} - -	startServer(gracefulWait, handlerFuncs, serverDeploymentType, *flagPort) -} diff --git a/arbiter/go.mod b/arbiter/go.mod deleted file mode 100644 index a7a87c6..0000000 --- a/arbiter/go.mod +++ /dev/null @@ -1,17 +0,0 @@ -module arbiter - -go 1.22 - -require ( -	github.com/go-redis/redis/v8 v8.11.5 -	github.com/gorilla/mux v1.8.1 -	github.com/rs/zerolog v1.31.0 -) - -require ( -	github.com/cespare/xxhash/v2 v2.2.0 // indirect -	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect -	github.com/mattn/go-colorable v0.1.13 // indirect -	github.com/mattn/go-isatty v0.0.20 // indirect -	golang.org/x/sys v0.15.0 // indirect -) diff --git a/arbiter/go.sum b/arbiter/go.sum deleted file mode 100644 index 85a6437..0000000 --- a/arbiter/go.sum +++ /dev/null @@ -1,41 +0,0 @@ -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= -github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= -github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= -github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= -github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A= -github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= diff --git a/arbiter/tests.sh b/arbiter/tests.sh deleted file mode 100755 index be923f3..0000000 --- a/arbiter/tests.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env sh - -curl -k -X GET "https://localhost:8009/crypto/v1/arb/gecko?name=ethereum&unit=usd" -curl -k -X GET "https://localhost:8009/crypto/v1/arb/coincap?name=ethereum"  | 
