mirror of
https://github.com/AthanorLabs/atomic-swap.git
synced 2026-01-09 22:28:04 -05:00
restore price feed (#494)
This commit is contained in:
@@ -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},
|
||||||
|
|||||||
@@ -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
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user