diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 6ed0ed9..6030977 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -35,5 +35,5 @@ jobs: if: github.event_name != 'pull_request' run: just docker-ci "${REGISTRY}/${REPO}" - name: Docker build (PR validate) - if: github.event.name == 'pull_request' + if: github.event_name == 'pull_request' run: just docker-build diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..95cc0a7 --- /dev/null +++ b/Makefile @@ -0,0 +1,22 @@ +all: get-just + +get-just: + @echo "❗ make is deprecated in this project ❗" + @echo "Please transition to our new build manager, just (https://just.systems)" + @echo "If you need to install it, check out asdf: https://asdf-vm.com/guide/getting-started.html" + @echo " asdf plugin add just" + @echo " asdf install just" + @echo " just" + @echo + @echo "Happy hacking! See the README for details." + @exit 1 + +build: get-just + +install: get-just + +test-unit: get-just + +lint: get-just + +.PHONY: all get-just build install test-unit lint diff --git a/README.md b/README.md index 59eabaa..8b377cd 100644 --- a/README.md +++ b/README.md @@ -2,39 +2,32 @@ This is a standalone version of [Umee's fantastic work](https://github.com/umee-network/umee/tree/main/price-feeder) migrating [Terra's oracle-feeder](https://github.com/terra-money/oracle-feeder) app to Go, and integrating it more closely with the Cosmos SDK. -## Providers -The list of current supported providers: +## Build and install -- [Astroport](https://astroport.fi/en) -- [Binance](https://www.binance.com/en) -- [BinanceUS](https://www.binance.us) -- [Bitfinex](https://www.bitfinex.com) -- [Bitget](https://www.bitget.com/en/) -- [Bitmart](https://www.bitmart.com/en-US) -- [Bitstamp](https://www.bitstamp.net) -- [Bybit](https://www.bybit.com/en-US/) -- [Camelot DEX](https://excalibur.exchange) -- [Coinbase](https://www.coinbase.com/) -- [Crypto.com](https://crypto.com/eea) -- [Curve](https://curve.fi) -- [FIN](https://fin.kujira.app) -- [Gate.io](https://www.gate.io) -- [HitBTC](https://hitbtc.com) -- [Huobi](https://www.huobi.com/en-us/) -- [Kraken](https://www.kraken.com/en-us/) -- [Kucoin](https://www.kucoin.com) -- [LBank](https://www.lbank.com) -- [MEXC](https://www.mexc.com/) -- [Okx](https://www.okx.com/) -- [Osmosis](https://app.osmosis.zone/) -- [PancakeSwap (Ethereum)](https://pancakeswap.finance) -- [Phemex](https://phemex.com) -- [Poloniex](https://poloniex.com) -- [Pyth](https://pyth.network) -- [UniswapV3](https://app.uniswap.org) -- [WhiteWhale](https://whitewhale.money) -- [XT.COM](https://www.xt.com/en) +An extensive installation guide can be found [here](https://docs.kujira.app/validators/run-a-node/oracle-price-feeder). + +### Using `just` + +This project uses `just` (https://just.systems) for build management. A simpler and +faster alternative to `make` written in Rust, `just` is the easiest way to build and +install this project. + +Many install methods for `just` are documented on its [Github page](https://github.com/casey/just). +The recommended one, which works on most platforms, is via the `asdf` package manager +[available here](https://asdf-vm.com/guide/getting-started.html). Install it and then install `just`: +``` +asdf plugin add just +asdf install just +``` + +Run `just` without any arguments to list available recipes. Code for the recipes can be found in the +`justfile`. + +### Docker + +Docker images with x86_64 and ARM64 support are provided for this repository, generated via GitHub +Actions. See **Packages** in the sidebar for the available tags. ## Usage @@ -49,10 +42,6 @@ Please see the [example configuration](config.example.toml) for more details. price-feeder /path/to/price_feeder_config.toml ``` -## Installation - -An extensive installation guide can be found [here](https://docs.kujira.app/validators/run-a-node/oracle-price-feeder). - ## Configuration ### `server` @@ -187,14 +176,13 @@ provider3 = 0 In this example the resulting price will be following provider1 as long as it is available (100k times more weight than provider2). If provider1 fails, the resulting price will follow provider2, and if that fails it too, the resulting price is the one reported by provider3. All assuming the deviation of the all prices are within the configured range. + ## Keyring Our keyring must be set up to sign transactions before running the price feeder. Additional info on the different keyring modes is available [here](https://docs.cosmos.network/master/run-node/keyring.html). -**Please note that the `test` and `memory` modes are only for testing purposes.** -**Do not use these modes for running the price feeder against mainnet.** -### Setup +### Setting the keyring file password The keyring `dir` and `backend` are defined in the config file. You may use the `PRICE_FEEDER_PASS` environment variable to set up the keyring password. @@ -203,3 +191,56 @@ Ex : `export PRICE_FEEDER_PASS=keyringPassword` If this environment variable is not set, the price feeder will prompt the user for input. + +### Providing a mnemonic + +Use the `PRICE_FEEDER_MNEMONIC` environment variable to automatically generate a keyring entry +from a mnemonic. This respects the standard `keyring` config, so if you use the `file` +backend a password is still needed. As an alternative here you can use `backend = "memory"` +and no keyring data will be persisted to disk; in this case the `dir` config is irrelevant. + +Ideally the mnemonic variable should be provided from CI with secrets management, this way your +key data is never persisted in plaintext and not available to external processes. + +### Backend recommendations + +- The `file` backend is the most well-tested and makes sense in most cases. +- The `memory` backend should be used only if a mnemonic env variable is provided, otherwise +your feeder will not recover from a restart without manual input. +- The `test` backend stores key data on disk in plaintext, never use this unless testing with +dummy accounts. + + +## Providers + +The list of current supported providers: + +- [Astroport](https://astroport.fi/en) +- [Binance](https://www.binance.com/en) +- [BinanceUS](https://www.binance.us) +- [Bitfinex](https://www.bitfinex.com) +- [Bitget](https://www.bitget.com/en/) +- [Bitmart](https://www.bitmart.com/en-US) +- [Bitstamp](https://www.bitstamp.net) +- [Bybit](https://www.bybit.com/en-US/) +- [Camelot DEX](https://excalibur.exchange) +- [Coinbase](https://www.coinbase.com/) +- [Crypto.com](https://crypto.com/eea) +- [Curve](https://curve.fi) +- [FIN](https://fin.kujira.app) +- [Gate.io](https://www.gate.io) +- [HitBTC](https://hitbtc.com) +- [Huobi](https://www.huobi.com/en-us/) +- [Kraken](https://www.kraken.com/en-us/) +- [Kucoin](https://www.kucoin.com) +- [LBank](https://www.lbank.com) +- [MEXC](https://www.mexc.com/) +- [Okx](https://www.okx.com/) +- [Osmosis](https://app.osmosis.zone/) +- [PancakeSwap (Ethereum)](https://pancakeswap.finance) +- [Phemex](https://phemex.com) +- [Poloniex](https://poloniex.com) +- [Pyth](https://pyth.network) +- [UniswapV3](https://app.uniswap.org) +- [WhiteWhale](https://whitewhale.money) +- [XT.COM](https://www.xt.com/en) \ No newline at end of file diff --git a/__docker__/Dockerfile b/__docker__/Dockerfile index 0eeb1b1..3190f65 100644 --- a/__docker__/Dockerfile +++ b/__docker__/Dockerfile @@ -8,22 +8,33 @@ ARG gid=3232 ARG binary="price-feeder" ARG just_install_url="https://github.com/casey/just/releases/download/1.33.0/just-1.33.0-x86_64-unknown-linux-musl.tar.gz" -FROM golang:1.21.8-bookworm AS build +FROM --platform=$BUILDPLATFORM golang:1.21.8-bookworm AS build ARG just_install_url ARG binary +ARG TARGETOS +ARG TARGETARCH ENV DEBIAN_FRONTEND=noninteractive WORKDIR /work -RUN echo "install just from ${just_install_url}" -RUN apt-get update && \ +RUN echo "install just from $just_install_url" +RUN CC_ARCH=$(case "$TARGETARCH" in \ + "amd64") echo "x86_64" ;; \ + "arm64") echo "aarch64" ;; \ + *) echo "unknown" ;; \ + esac) && \ + CC_OS=$(case "$TARGETOS" in \ + "linux") echo "linux-gnu" ;; \ + *) echo "unknown" ;; \ + esac) && \ + apt-get update && \ apt-get upgrade -y && \ - apt-get install -y curl && \ - curl -fsSL ${just_install_url} | tar -xzvC /usr/bin -- just + apt-get install -y curl "gcc-${CC_ARCH}-${CC_OS}" && \ + curl -fsSL "$just_install_url" | tar -xzvC /usr/bin -- just COPY . . -RUN just build +RUN just build-${TARGETOS}-${TARGETARCH} WORKDIR /work/dist RUN mkdir bin lib && \ - mv ../build/${binary} ./bin/ && \ - mv $(ldd ./bin/${binary} | grep libwasmvm | awk '{print $3}') ./lib/ + mv ../build/$binary ./bin/ && \ + mv $(ldd ./bin/$binary | grep libwasmvm | awk '{print $3}') ./lib/ FROM debian:bookworm AS main ARG user @@ -36,8 +47,8 @@ COPY --from=build /work/dist/* /usr/ RUN apt-get update && \ apt-get upgrade -y && \ apt-get install -y ca-certificates && \ - groupadd -g ${gid} -r ${user} && \ - useradd -m -u ${uid} -g ${user} -s /bin/bash -d ${home} ${user} + groupadd -g "$gid" -r "$user" && \ + useradd -m -u "$uid" -g "$user" -s /bin/bash -d "$home" "$user" USER ${user}:${user} -WORKDIR ${home} -ENTRYPOINT ["${binary}"] +WORKDIR $home +ENTRYPOINT ["$binary"] diff --git a/justfile b/justfile index 467e78f..8b59880 100644 --- a/justfile +++ b/justfile @@ -4,6 +4,11 @@ export GIT_TAG := `git describe --exact-match 2>/dev/null || exit 0` export VERSION := if GIT_TAG != "" { GIT_TAG } else { GIT_BRANCH + "-" + GIT_COMMIT } export CGO_ENABLED := if os() == "linux" { "1" } else { "0" } +bin_name := "price-feeder" +build_path := "./build" +dockerfile_path := "./__docker__/Dockerfile" +docker_tag := "price-feeder:" + VERSION +docker_args := "--no-cache --progress plain -t " + docker_tag + " -f " + dockerfile_path ldflags := ''' -X price-feeder/cmd.Version=${VERSION} \ -X price-feeder/cmd.Commit=${GIT_COMMIT} \ @@ -12,10 +17,6 @@ ldflags := ''' -X github.com/cosmos/cosmos-sdk/version.Version=${VERSION} \ -X github.com/cosmos/cosmos-sdk/version.Commit=${GIT_COMMIT} ''' -build_path := "./build" -dockerfile_path := "./__docker__/Dockerfile" -docker_tag := "price-feeder:" + VERSION -docker_args := "--no-cache --progress plain -t " + docker_tag + " -f " + dockerfile_path alias b := build alias i := install @@ -25,35 +26,68 @@ alias docker := docker-build _list: @just --list --no-aliases -build: +# build binary for current platform +build out=bin_name: mkdir -p {{build_path}} - go build -mod=readonly -o {{build_path}} -ldflags "{{ldflags}}" ./... + go build -mod=readonly -o "{{build_path}}/{{out}}" -ldflags "{{ldflags}}" main.go +# build binary and install to GOPATH install: go install -mod=readonly -ldflags "{{ldflags}}" ./... +# remove build artifacts clean: rm -rf {{build_path}} - go clean +# clean then build clobber: clean build +# check code with golangci-lint lint: go run github.com/golangci/golangci-lint/cmd/golangci-lint run --timeout=10m +# run all tests test: unit-test +# build for given platform +[group("build")] +build-platform $GOOS="linux" $GOARCH="amd64" $CC="gcc": + @echo "Building: os=${GOOS}, arch=${GOARCH}, CC=${CC}" + @just build "{{bin_name}}_{{GOOS}}-{{GOARCH}}" + +# build for linux/amd64 +[group("build")] +build-linux-amd64: (build-platform "linux" "amd64" "x86_64-linux-gnu-gcc") + +# build for linux/arm64 +[group("build")] +build-linux-arm64: (build-platform "linux" "arm64" "aarch64-linux-gnu-gcc") + +# build docker image for current platform [group("docker")] docker-build: docker build {{docker_args}} . +# build docker image for given platform +[group("docker")] +docker-build-platform platform="linux/amd64": + docker buildx build --platform "{{platform}}" {{docker_args}} . + +# build docker image for linux/amd64 and linux/arm64 +[group("docker")] +docker-build-multiplatform: + docker buildx build --platform "linux/amd64,linux/arm64" {{ docker_args }} . + +# build, tag, and push docker image (for pipelines) [group("docker")] -docker-ci REPO: docker-build - docker tag {{docker_tag}} {{REPO}}:{{VERSION}} - docker tag {{docker_tag}} {{REPO}}:{{GIT_BRANCH}} - docker push {{REPO}}:{{VERSION}} - docker push {{REPO}}:{{GIT_BRANCH}} +docker-ci repo: docker-build-multiplatform + just docker-build-multiplatform + docker tag {{docker_tag}} {{repo}}:{{VERSION}} + docker tag {{docker_tag}} {{repo}}:{{GIT_BRANCH}} + docker push {{repo}}:{{VERSION}} + docker push {{repo}}:{{GIT_BRANCH}} +# run unit tests [group("tests")] unit-test: go test -mod=readonly -race ./...