Skip to content

Commit

Permalink
Merge pull request #48 from cypherhat/master
Browse files Browse the repository at this point in the history
Moved to coinmarketcap API pro/v1
  • Loading branch information
cypherhat committed Oct 30, 2018
2 parents 7e5f468 + d02acff commit 66861e1
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 48 deletions.
4 changes: 2 additions & 2 deletions API.md
Expand Up @@ -1040,7 +1040,7 @@ This endpoint configure the plugin at a mount.
* `rpc_url` (`string: <optional> default:"https://rinkeby.infura.io"`) - Specifies the RPC URL of the Ethereum node.
* `chain_id` (`string: <optional> default:"4"`) - Specifies the Ethereum network. Defaults to Rinkeby.
* `bound_cidr_list` (`string array: <optional>`) - Comma delimited list of allowed CIDR blocks.
* `api_key` (`string: <optional>`) - The Infura API key.
* `api_key` (`string: <optional>`) - The Coinmarketcap API key.

#### Sample Payload

Expand Down Expand Up @@ -1097,7 +1097,7 @@ This endpoint reconfigures the plugin at a mount.
* `rpc_url` (`string: <optional> default:"https://rinkeby.infura.io"`) - Specifies the RPC URL of the Ethereum node.
* `chain_id` (`string: <optional> default:"4"`) - Specifies the Ethereum network. Defaults to Rinkeby.
* `bound_cidr_list` (`string array: <optional>`) - Comma delimited list of allowed CIDR blocks.
* `api_key` (`string: <optional>`) - The Infura API key.
* `api_key` (`string: <optional>`) - The Coinmarketcap API key.

#### Sample Payload

Expand Down
6 changes: 3 additions & 3 deletions path_accounts.go
Expand Up @@ -678,7 +678,7 @@ func (b *EthereumBackend) pathSignTx(ctx context.Context, req *logical.Request,
}
amountInUSD, _ := decimal.NewFromString("0")
if config.ChainID == EthereumMainnet {
amountInUSD, err = ConvertToUSD(amount.String())
amountInUSD, err = ConvertToUSD(amount.String(), config.CoinMarketCapAPIKey)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -791,7 +791,7 @@ func (b *EthereumBackend) pathDebit(ctx context.Context, req *logical.Request, d
}
amountInUSD, _ := decimal.NewFromString("0")
if config.ChainID == EthereumMainnet {
amountInUSD, err = ConvertToUSD(amount.String())
amountInUSD, err = ConvertToUSD(amount.String(), config.CoinMarketCapAPIKey)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -980,7 +980,7 @@ func (b *EthereumBackend) readAccountBalanceByAddress(ctx context.Context, req *
}
// Calculate exchange rate value if on Mainnet
if config.ChainID == EthereumMainnet {
exchangeValue, err := ConvertToUSD(balance.String())
exchangeValue, err := ConvertToUSD(balance.String(), config.CoinMarketCapAPIKey)
if err != nil {
return nil, zero, err
}
Expand Down
29 changes: 11 additions & 18 deletions path_config.go
Expand Up @@ -17,7 +17,6 @@ package main
import (
"context"
"fmt"
"strings"

"github.com/hashicorp/errwrap"
"github.com/hashicorp/vault/helper/cidrutil"
Expand Down Expand Up @@ -63,10 +62,10 @@ const (

// Config contains the configuration for each mount
type Config struct {
BoundCIDRList []string `json:"bound_cidr_list_list" structs:"bound_cidr_list" mapstructure:"bound_cidr_list"`
RPC string `json:"rpc_url"`
InfuraAPIKey string `json:"api_key"`
ChainID string `json:"chain_id"`
BoundCIDRList []string `json:"bound_cidr_list_list" structs:"bound_cidr_list" mapstructure:"bound_cidr_list"`
RPC string `json:"rpc_url"`
CoinMarketCapAPIKey string `json:"api_key"`
ChainID string `json:"chain_id"`
}

func configPaths(b *EthereumBackend) []*framework.Path {
Expand Down Expand Up @@ -105,7 +104,7 @@ func configPaths(b *EthereumBackend) []*framework.Path {
},
"api_key": &framework.FieldSchema{
Type: framework.TypeString,
Description: `The Infura API Key.`,
Description: `The Coinmarketcap API Key.`,
},
"bound_cidr_list": &framework.FieldSchema{
Type: framework.TypeCommaStringSlice,
Expand All @@ -118,12 +117,6 @@ IP addresses which can perform the login operation.`,
}

func (config *Config) getRPCURL() string {
if config.InfuraAPIKey != "" {
url := strings.TrimRight(config.RPC, "/")
if isInfuraNetwork(url) {
return fmt.Sprintf("%s/%s", url, config.InfuraAPIKey)
}
}
return config.RPC
}

Expand Down Expand Up @@ -167,10 +160,10 @@ func (b *EthereumBackend) pathWriteConfig(ctx context.Context, req *logical.Requ
boundCIDRList = boundCIDRListRaw.([]string)
}
configBundle := Config{
BoundCIDRList: boundCIDRList,
RPC: rpcURL,
ChainID: chainID,
InfuraAPIKey: apiKey,
BoundCIDRList: boundCIDRList,
RPC: rpcURL,
ChainID: chainID,
CoinMarketCapAPIKey: apiKey,
}
entry, err := logical.StorageEntryJSON("config", configBundle)

Expand All @@ -186,7 +179,7 @@ func (b *EthereumBackend) pathWriteConfig(ctx context.Context, req *logical.Requ
Data: map[string]interface{}{
"bound_cidr_list": configBundle.BoundCIDRList,
"chain_id": configBundle.ChainID,
"api_key": configBundle.InfuraAPIKey,
"api_key": configBundle.CoinMarketCapAPIKey,
"rpc_url": configBundle.RPC,
},
}, nil
Expand All @@ -207,7 +200,7 @@ func (b *EthereumBackend) pathReadConfig(ctx context.Context, req *logical.Reque
Data: map[string]interface{}{
"bound_cidr_list": configBundle.BoundCIDRList,
"chain_id": configBundle.ChainID,
"api_key": configBundle.InfuraAPIKey,
"api_key": configBundle.CoinMarketCapAPIKey,
"rpc_url": configBundle.RPC,
},
}, nil
Expand Down
2 changes: 1 addition & 1 deletion path_contracts.go
Expand Up @@ -218,7 +218,7 @@ func (b *EthereumBackend) pathCreateContract(ctx context.Context, req *logical.R
}
amountInUSD, _ := decimal.NewFromString("0")
if config.ChainID == EthereumMainnet {
amountInUSD, err = ConvertToUSD(amount.String())
amountInUSD, err = ConvertToUSD(amount.String(), config.CoinMarketCapAPIKey)
if err != nil {
return nil, err
}
Expand Down
53 changes: 41 additions & 12 deletions path_convert.go
Expand Up @@ -17,11 +17,12 @@ package main
import (
"context"
"fmt"
"log"
"strings"

"github.com/hashicorp/vault/logical"
"github.com/hashicorp/vault/logical/framework"
cmc "github.com/miguelmota/go-coinmarketcap"
cmc "github.com/miguelmota/go-coinmarketcap/pro/v1"
"github.com/shopspring/decimal"
)

Expand Down Expand Up @@ -192,24 +193,49 @@ func ConvertFromWei(normalizeUnit string, amount decimal.Decimal) decimal.Decima
}

// ConvertToUSD uses Coinmarketcap to estimate value of ETH in USD
func ConvertToUSD(amountInWei string) (decimal.Decimal, error) {
func ConvertToUSD(amountInWei, apiKey string) (decimal.Decimal, error) {
zero, _ := decimal.NewFromString("0")
balanceInWei, err := decimal.NewFromString(amountInWei)
floatPrice, err := cmc.Price(&cmc.PriceOptions{
Symbol: "ETH",
Convert: "USD",
if apiKey == "" {
return zero, nil
}

client := cmc.NewClient(&cmc.Config{
ProAPIKey: apiKey,
})

listings, err := client.CryptocurrencyListingsLatest(&cmc.CryptocurrencyListingsLatestOptions{
Limit: 10,
})
if err != nil {
log.Fatal(err)
}
var ethListing *cmc.Listing
for _, listing := range listings {
if listing.Symbol == "ETH" {
ethListing = listing
break
}
}
if ethListing == nil {
return zero, nil
}
balanceInWei, err := decimal.NewFromString(amountInWei)
if err != nil {
return zero, err
}
price := decimal.NewFromFloat(floatPrice)
balanceInETH := ConvertFromWei(ETH, balanceInWei)
exchangeValue := price.Mul(balanceInETH)
return exchangeValue, nil
quote, ok := ethListing.Quote["USD"]
if ok {
price := decimal.NewFromFloat(quote.Price)
balanceInETH := ConvertFromWei(ETH, balanceInWei)
exchangeValue := price.Mul(balanceInETH)
return exchangeValue, nil
}
return zero, nil

}

func (b *EthereumBackend) pathConvertWrite(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
_, err := b.configured(ctx, req)
config, err := b.configured(ctx, req)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -238,7 +264,10 @@ func (b *EthereumBackend) pathConvertWrite(ctx context.Context, req *logical.Req
}
if unitFrom == USD || unitTo == USD {
oneETHInWei := ConvertToWei(ETH, oneETH)
exchangeValue, err = ConvertToUSD(oneETHInWei.String())
exchangeValue, err = ConvertToUSD(oneETHInWei.String(), config.CoinMarketCapAPIKey)
if err != nil {
return nil, err
}
}
if unitFrom == USD {
usdFrom = true
Expand Down
8 changes: 4 additions & 4 deletions test/ethereum/config/config.bats
@@ -1,7 +1,7 @@
#!/usr/bin/env bats

@test "test write rinkeby config" {
config="$(vault write -format=json ethereum/dev/config @rinkeby.json | jq .data)"
config="$(vault write -format=json ethereum/dev/config rpc_url="https://rinkeby.infura.io" chain_id="4" | jq .data)"
api_key="$(echo $config | jq -r .api_key)"
bound_cidr_list="$(echo $config | jq -r .bound_cidr_list)"
chain_id="$(echo $config | jq -r .chain_id)"
Expand All @@ -12,18 +12,18 @@
}

@test "test write mainnet config" {
config="$(vault write -format=json ethereum/prod/config @mainnet.json | jq .data)"
config="$(vault write -format=json ethereum/prod/config rpc_url="https://mainnet.infura.io" chain_id="1" api_key="$COINMARKETCAP_API_KEY" | jq .data)"
api_key="$(echo $config | jq -r .api_key)"
bound_cidr_list="$(echo $config | jq -r .bound_cidr_list)"
chain_id="$(echo $config | jq -r .chain_id)"
rpc_url="$(echo $config | jq -r .rpc_url)"
[ "$api_key" = "" ]
[ "$api_key" = "$COINMARKETCAP_API_KEY" ]
[ "$chain_id" = "1" ]
[ "$rpc_url" = "https://mainnet.infura.io" ]
}

@test "test read config" {
config="$(vault write -format=json ethereum/prod/config @mainnet.json | jq .data)"
config="$(vault write -format=json ethereum/prod/config rpc_url="https://mainnet.infura.io" chain_id="1" api_key="$COINMARKETCAP_API_KEY" | jq .data)"
api_key="$(echo $config | jq -r .api_key)"
bound_cidr_list="$(echo $config | jq -r .bound_cidr_list)"
chain_id="$(echo $config | jq -r .chain_id)"
Expand Down
4 changes: 0 additions & 4 deletions test/ethereum/config/mainnet.json

This file was deleted.

4 changes: 0 additions & 4 deletions test/ethereum/config/rinkeby.json

This file was deleted.

0 comments on commit 66861e1

Please sign in to comment.