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{ Flags: []cli.Flag{
&cli.StringFlag{ &cli.StringFlag{
Name: flagMinAmount, Name: flagMinAmount,
Aliases: []string{"min"},
Usage: "Minimum amount to be swapped, in XMR", Usage: "Minimum amount to be swapped, in XMR",
Required: true, Required: true,
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: flagMaxAmount, Name: flagMaxAmount,
Aliases: []string{"max"},
Usage: "Maximum amount to be swapped, in XMR", Usage: "Maximum amount to be swapped, in XMR",
Required: true, Required: true,
}, },
@@ -184,15 +186,16 @@ func cliApp() *cli.App {
}, },
&cli.BoolFlag{ &cli.BoolFlag{
Name: flagDetached, 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{ &cli.StringFlag{
Name: flagToken, 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{ &cli.BoolFlag{
Name: flagUseRelayer, Name: flagUseRelayer,
Usage: "Use the relayer even if the receiving account has enough ETH to claim", 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, swapdPortFlag,
}, },
@@ -215,12 +218,13 @@ func cliApp() *cli.App {
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: flagProvidesAmount, Name: flagProvidesAmount,
Aliases: []string{"pa"},
Usage: "Amount of coin to send in the swap", Usage: "Amount of coin to send in the swap",
Required: true, Required: true,
}, },
&cli.BoolFlag{ &cli.BoolFlag{
Name: flagDetached, Name: flagDetached,
Usage: "Exit immediately instead of subscribing to notifications about the swap's status", Usage: "Exit immediately without subscribing to status notifications",
}, },
swapdPortFlag, swapdPortFlag,
}, },
@@ -251,7 +255,7 @@ func cliApp() *cli.App {
}, },
{ {
Name: "cancel", 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, Action: runCancel,
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.StringFlag{ &cli.StringFlag{
@@ -308,8 +312,8 @@ func cliApp() *cli.App {
}, },
}, },
{ {
Name: "suggested-exchange-rate", Name: "price-feed",
Aliases: []string{"price-feed"}, Aliases: []string{"suggested-exchange-rate"},
Usage: "Returns the current mainnet exchange rate based on ETH/USD and XMR/USD price feeds.", Usage: "Returns the current mainnet exchange rate based on ETH/USD and XMR/USD price feeds.",
Action: runSuggestedExchangeRate, Action: runSuggestedExchangeRate,
Flags: []cli.Flag{swapdPortFlag}, Flags: []cli.Flag{swapdPortFlag},

View File

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

View File

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

View File

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