restore price feed (#494)

This commit is contained in:
Dmitry Holodov
2023-06-29 12:00:54 -05:00
committed by GitHub
parent 485d1332a5
commit 3b4870ed50
4 changed files with 60 additions and 55 deletions

View File

@@ -169,11 +169,13 @@ func cliApp() *cli.App {
Flags: []cli.Flag{
&cli.StringFlag{
Name: flagMinAmount,
Aliases: []string{"min"},
Usage: "Minimum amount to be swapped, in XMR",
Required: true,
},
&cli.StringFlag{
Name: flagMaxAmount,
Aliases: []string{"max"},
Usage: "Maximum amount to be swapped, in XMR",
Required: true,
},
@@ -184,15 +186,16 @@ func cliApp() *cli.App {
},
&cli.BoolFlag{
Name: flagDetached,
Usage: "Exit immediately instead of subscribing to notifications about the swap's status",
Usage: "Exit immediately without subscribing to status notifications",
},
&cli.StringFlag{
Name: flagToken,
Usage: "Use to pass the ethereum ERC20 token address to receive instead of ETH",
Usage: "Ethereum ERC20 token address to receive instead of ETH",
},
&cli.BoolFlag{
Name: flagUseRelayer,
Usage: "Use the relayer even if the receiving account has enough ETH to claim",
Name: flagUseRelayer,
Usage: "Use the relayer even if the receiving account has enough ETH to claim",
Hidden: true, // useful for testing, but no clear end-user use case for the flag
},
swapdPortFlag,
},
@@ -215,12 +218,13 @@ func cliApp() *cli.App {
},
&cli.StringFlag{
Name: flagProvidesAmount,
Aliases: []string{"pa"},
Usage: "Amount of coin to send in the swap",
Required: true,
},
&cli.BoolFlag{
Name: flagDetached,
Usage: "Exit immediately instead of subscribing to notifications about the swap's status",
Usage: "Exit immediately without subscribing to status notifications",
},
swapdPortFlag,
},
@@ -251,7 +255,7 @@ func cliApp() *cli.App {
},
{
Name: "cancel",
Usage: "Cancel a ongoing swap if possible. Depending on the swap stage, this may not be possible.",
Usage: "Cancel ongoing swap, if possible at the current swap stage.",
Action: runCancel,
Flags: []cli.Flag{
&cli.StringFlag{
@@ -308,8 +312,8 @@ func cliApp() *cli.App {
},
},
{
Name: "suggested-exchange-rate",
Aliases: []string{"price-feed"},
Name: "price-feed",
Aliases: []string{"suggested-exchange-rate"},
Usage: "Returns the current mainnet exchange rate based on ETH/USD and XMR/USD price feeds.",
Action: runSuggestedExchangeRate,
Flags: []cli.Flag{swapdPortFlag},

View File

@@ -28,8 +28,9 @@ const (
// Ethereum chain IDs
const (
MainnetChainID = 1
SepoliaChainID = 11155111
GanacheChainID = 1337
HardhatChainID = 31337
MainnetChainID = 1
OpMainnetChainID = 10 // Optimism
SepoliaChainID = 11155111
GanacheChainID = 1337
HardhatChainID = 31337
)

View File

@@ -21,17 +21,16 @@ import (
)
const (
// mainnetEndpoint is a mainnet ethereum endpoint, from
// https://chainlist.org/chain/1, which stagenet users get pointed at for
// price feeds, as Sepolia doesn't have an XMR feed. Mainnet users will use
// the same ethereum endpoint that they use for other swap transactions.
mainnetEndpoint = "https://eth-rpc.gateway.pokt.network"
// optimismEndpoint is an RPC endpoint for optimism mainnet. Note that we
// tried https://mainnet.optimism.io first, but it is severely rate limited
// to around 2 requests/second.
optimismEndpoint = "https://1rpc.io/op"
// https://data.chain.link/ethereum/mainnet/crypto-usd/eth-usd
chainlinkETHToUSDProxy = "0x5f4ec3df9cbd43714fe2740f5e3616155c5b8419"
// https://data.chain.link/optimism/mainnet/crypto-usd/eth-usd
chainlinkETHToUSDProxy = "0x13e3ee699d1909e989722e753853ae30b17e08c5"
// https://data.chain.link/ethereum/mainnet/crypto-usd/xmr-usd
chainlinkXMRToUSDProxy = "0xfa66458cce7dd15d8650015c4fce4d278271618f"
// https://data.chain.link/optimism/mainnet/crypto-usd/xmr-usd
chainlinkXMRToUSDProxy = "0x2a8d91686a048e98e6ccf1a89e82f40d14312672"
)
var (
@@ -47,7 +46,6 @@ type PriceFeed struct {
}
// GetETHUSDPrice returns the current ETH/USD price from the Chainlink oracle.
// It errors if the chain ID is not the Ethereum mainnet.
func GetETHUSDPrice(ctx context.Context, ec *ethclient.Client) (*PriceFeed, error) {
chainID, err := ec.ChainID(ctx)
if err != nil {
@@ -55,11 +53,10 @@ func GetETHUSDPrice(ctx context.Context, ec *ethclient.Client) (*PriceFeed, erro
}
switch chainID.Uint64() {
case common.MainnetChainID:
case common.OpMainnetChainID:
// No extra work to do
case common.SepoliaChainID:
// Push stagenet/sepolia users to a mainnet endpoint
ec, err = ethclient.Dial(mainnetEndpoint)
case common.MainnetChainID, common.SepoliaChainID:
ec, err = ethclient.Dial(optimismEndpoint)
if err != nil {
return nil, err
}
@@ -78,25 +75,18 @@ func GetETHUSDPrice(ctx context.Context, ec *ethclient.Client) (*PriceFeed, erro
}
// GetXMRUSDPrice returns the current XMR/USD price from the Chainlink oracle.
// It errors if the chain ID is not the Ethereum mainnet.
func GetXMRUSDPrice(ctx context.Context, ec *ethclient.Client) (*PriceFeed, error) {
chainID, err := ec.ChainID(ctx)
if err != nil {
return nil, err
}
// Temporary hack to return a better error until the issue is resolved.
switch chainID.Uint64() {
case common.MainnetChainID, common.SepoliaChainID:
return nil, errors.New("https://github.com/AthanorLabs/atomic-swap/issues/492")
}
switch chainID.Uint64() {
case common.MainnetChainID:
case common.OpMainnetChainID:
// No extra work to do
case common.SepoliaChainID:
case common.MainnetChainID, common.SepoliaChainID:
// Push stagenet/sepolia users to a mainnet endpoint
ec, err = ethclient.Dial(mainnetEndpoint)
ec, err = ethclient.Dial(optimismEndpoint)
if err != nil {
return nil, err
}

View File

@@ -7,6 +7,7 @@ import (
"context"
"testing"
"github.com/ethereum/go-ethereum/ethclient"
logging "github.com/ipfs/go-log/v2"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -15,18 +16,28 @@ import (
)
func init() {
logging.SetLogLevel("pricefeed", "debug")
_ = logging.SetLogLevel("pricefeed", "debug")
}
func TestGetETHUSDPrice_mainnet(t *testing.T) {
ec := tests.NewEthMainnetClient(t)
feed, err := GetETHUSDPrice(context.Background(), ec)
func newOptimismClient(t *testing.T) *ethclient.Client {
ec, err := ethclient.Dial(optimismEndpoint)
require.NoError(t, err)
t.Logf("%s is $%s (updated: %s)", feed.Description, feed.Price, feed.UpdatedAt)
assert.Equal(t, "ETH / USD", feed.Description)
assert.False(t, feed.Price.Negative)
assert.False(t, feed.Price.IsZero())
t.Cleanup(func() {
ec.Close()
})
return ec
}
func TestGetETHUSDPrice_nonDev(t *testing.T) {
for _, ec := range []*ethclient.Client{tests.NewEthSepoliaClient(t), newOptimismClient(t)} {
feed, err := GetETHUSDPrice(context.Background(), ec)
require.NoError(t, err)
t.Logf("%s is $%s (updated: %s)", feed.Description, feed.Price, feed.UpdatedAt)
assert.Equal(t, "ETH / USD", feed.Description)
assert.False(t, feed.Price.Negative)
assert.False(t, feed.Price.IsZero())
}
}
func TestGetETHUSDPrice_dev(t *testing.T) {
@@ -37,16 +48,15 @@ func TestGetETHUSDPrice_dev(t *testing.T) {
assert.Equal(t, "1234.12345678", feed.Price.String())
}
func TestGetXMRUSDPrice_mainnet(t *testing.T) {
t.Skip("Chainlink XMR price feed is down: https://github.com/AthanorLabs/atomic-swap/issues/492")
ec := tests.NewEthMainnetClient(t)
feed, err := GetXMRUSDPrice(context.Background(), ec)
require.NoError(t, err)
t.Logf("%s is $%s (updated: %s)", feed.Description, feed.Price, feed.UpdatedAt)
assert.Equal(t, "XMR / USD", feed.Description)
assert.False(t, feed.Price.Negative)
assert.False(t, feed.Price.IsZero())
func TestGetXMRUSDPrice_nonDev(t *testing.T) {
for _, ec := range []*ethclient.Client{tests.NewEthSepoliaClient(t), newOptimismClient(t)} {
feed, err := GetXMRUSDPrice(context.Background(), ec)
require.NoError(t, err)
t.Logf("%s is $%s (updated: %s)", feed.Description, feed.Price, feed.UpdatedAt)
assert.Equal(t, "XMR / USD", feed.Description)
assert.False(t, feed.Price.Negative)
assert.False(t, feed.Price.IsZero())
}
}
func TestGetXMRUSDPrice_dev(t *testing.T) {