From a957028dd6b6d34c4980f66d8acc97d8a3043a38 Mon Sep 17 00:00:00 2001 From: Jiri Malek Date: Thu, 16 Apr 2020 18:31:29 +0200 Subject: [PATCH] Add current gas price resolver to API server. --- Makefile | 26 ++++++++++++ internal/graphql/resolvers/root.go | 3 ++ .../graphql/resolvers/{util.go => utils.go} | 6 +++ internal/graphql/schema/bundle.go | 5 ++- .../graphql/schema/definition/schema.graphql | 3 ++ internal/repository/repository.go | 3 ++ internal/repository/rpc/utils.go | 40 +++++++++++++++++++ internal/repository/utils.go | 5 +++ 8 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 Makefile rename internal/graphql/resolvers/{util.go => utils.go} (80%) create mode 100644 internal/repository/rpc/utils.go diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..a2ed8b28 --- /dev/null +++ b/Makefile @@ -0,0 +1,26 @@ +# -------------------------------------------------------------------------- +# Makefile for the Fantom API GaphQL Server +# +# v0.1 (2020/03/09) - Initial version, base API server build. +# (c) Fantom Foundation, 2020 +# -------------------------------------------------------------------------- + +# project related vars +PROJECT := $(shell basename "$(PWD)") + +# go related vars +GOBASE := $(shell pwd) +GOBIN=$(CURDIR)/build + +## server: Make the API server as bin/frd +server: + go build -o $(GOBIN)/apiserver ./cmd/apiserver + +.PHONY: help +all: help +help: Makefile + @echo + @echo "Choose a make command in "$(PROJECT)":" + @echo + @sed -n 's/^##//p' $< | column -t -s ':' | sed -e 's/^/ /' + @echo diff --git a/internal/graphql/resolvers/root.go b/internal/graphql/resolvers/root.go index 52ca1d8f..820e12f7 100644 --- a/internal/graphql/resolvers/root.go +++ b/internal/graphql/resolvers/root.go @@ -81,6 +81,9 @@ type ApiResolver interface { // Price resolves price details of the Opera blockchain token for the given target symbols. Price(*struct{ To string }) (types.Price, error) + // GasPrice resolves the current amount of WEI for single Gas. + GasPrice() (hexutil.Uint64, error) + // Close terminates resolver broadcast management. Close() } diff --git a/internal/graphql/resolvers/util.go b/internal/graphql/resolvers/utils.go similarity index 80% rename from internal/graphql/resolvers/util.go rename to internal/graphql/resolvers/utils.go index 9b49be1f..11fc89a5 100644 --- a/internal/graphql/resolvers/util.go +++ b/internal/graphql/resolvers/utils.go @@ -5,6 +5,7 @@ import ( "crypto/rand" "fantom-api-graphql/internal/types" "fmt" + "github.com/ethereum/go-ethereum/common/hexutil" "io" ) @@ -13,6 +14,11 @@ func (rs *rootResolver) Price(args *struct{ To string }) (types.Price, error) { return rs.repo.Price(args.To) } +// GasPrice resolves the current amount of WEI for single Gas. +func (rs *rootResolver) GasPrice() (hexutil.Uint64, error) { + return rs.repo.GasPrice() +} + // uuid generates new random subscription UUID func uuid() (string, error) { // prep container diff --git a/internal/graphql/schema/bundle.go b/internal/graphql/schema/bundle.go index 89b1fdb4..d05228fa 100644 --- a/internal/graphql/schema/bundle.go +++ b/internal/graphql/schema/bundle.go @@ -1,6 +1,6 @@ package gqlschema -// Auto generated GraphQL schema bundle; created 2020-03-20 23:21 +// Auto generated GraphQL schema bundle; created 2020-04-16 18:29 const schema = ` # StakerInfo represents extended staker information from smart contract. type StakerInfo { @@ -474,6 +474,9 @@ type Query { "Get the details of a delegator by it's address." delegation(address:Address!): Delegator + "Returns the current price per gas in WEI units." + gasPrice: Long! + "Get price details of the Opera blockchain token for the given target symbols." price(to:String!):Price! } diff --git a/internal/graphql/schema/definition/schema.graphql b/internal/graphql/schema/definition/schema.graphql index eef5e6a4..796092b8 100644 --- a/internal/graphql/schema/definition/schema.graphql +++ b/internal/graphql/schema/definition/schema.graphql @@ -60,6 +60,9 @@ type Query { "Get the details of a delegator by it's address." delegation(address:Address!): Delegator + "Returns the current price per gas in WEI units." + gasPrice: Long! + "Get price details of the Opera blockchain token for the given target symbols." price(to:String!):Price! } diff --git a/internal/repository/repository.go b/internal/repository/repository.go index 923ab529..32f45f10 100644 --- a/internal/repository/repository.go +++ b/internal/repository/repository.go @@ -116,6 +116,9 @@ type Repository interface { // Price returns a price information for the given target symbol. Price(sym string) (types.Price, error) + // GasPrice resolves the current amount of WEI for single Gas. + GasPrice() (hexutil.Uint64, error) + // FtmConnection returns open connection to Opera/Lachesis full node. FtmConnection() *ftm.Client diff --git a/internal/repository/rpc/utils.go b/internal/repository/rpc/utils.go new file mode 100644 index 00000000..01983861 --- /dev/null +++ b/internal/repository/rpc/utils.go @@ -0,0 +1,40 @@ +/* +Package rpc implements bridge to Lachesis full node API interface. + +We recommend using local IPC for fast and the most efficient inter-process communication between the API server +and an Opera/Lachesis node. Any remote RPC connection will work, but the performance may be significantly degraded +by extra networking overhead of remote RPC calls. + +You should also consider security implications of opening Lachesis RPC interface for a remote access. +If you considering it as your deployment strategy, you should establish encrypted channel between the API server +and Lachesis RPC interface with connection limited to specified endpoints. + +We strongly discourage opening Lachesis RPC interface for unrestricted Internet access. +*/ +package rpc + +import "github.com/ethereum/go-ethereum/common/hexutil" + +// GasPrice resolves the current amount of WEI for single Gas. +func (ftm *FtmBridge) GasPrice() (hexutil.Uint64, error) { + // keep track of the operation + ftm.log.Debugf("checking current gas price") + + // call for data + var price hexutil.Big + err := ftm.rpc.Call(&price, "ftm_gasPrice") + if err != nil { + ftm.log.Error("current gas price could not be obtained") + return hexutil.Uint64(0), err + } + + // if the price safely within the range + if !price.ToInt().IsUint64() { + ftm.log.Error("current gas price is too high and can not be extracted") + return hexutil.Uint64(0), err + } + + // inform and return + ftm.log.Debugf("current gas price is %d", uint64(price.ToInt().Uint64())) + return hexutil.Uint64(price.ToInt().Uint64()), nil +} diff --git a/internal/repository/utils.go b/internal/repository/utils.go index 5794e27a..62a69bb0 100644 --- a/internal/repository/utils.go +++ b/internal/repository/utils.go @@ -25,6 +25,11 @@ const ( priceApiTargetSymbolVar = "tsyms=" ) +// GasPrice resolves the current amount of WEI for single Gas. +func (p *proxy) GasPrice() (hexutil.Uint64, error) { + return p.rpc.GasPrice() +} + // Price returns a price information for the given target symbol. func (p *proxy) Price(sym string) (types.Price, error) { // inform what we do