From 32a85b289da1a9d131543b190ddee129a06aa595 Mon Sep 17 00:00:00 2001 From: JoeGruff Date: Fri, 7 May 2021 12:53:18 +0900 Subject: [PATCH] client/asset/eth: Use gwei in Balance. The basic unit of eth is so small that only 18 eth worth of wei can be stored in a uint64. Deal with eth as gwei so that we are able to ensure that as much as 18 billion eth can be represented. --- client/asset/eth/eth.go | 35 +++++++++--------- client/asset/eth/eth_test.go | 71 +++++++++++++++++++++++++++++++++++- dex/testing/eth/harness.sh | 7 ++-- server/asset/eth/common.go | 15 ++++++++ server/asset/eth/eth.go | 14 +------ server/asset/eth/eth_test.go | 5 ++- 6 files changed, 111 insertions(+), 36 deletions(-) diff --git a/client/asset/eth/eth.go b/client/asset/eth/eth.go index f54857b8a8..aa70b3292c 100644 --- a/client/asset/eth/eth.go +++ b/client/asset/eth/eth.go @@ -33,8 +33,8 @@ func init() { const ( // BipID is the BIP-0044 asset ID. BipID = 60 - defaultGasFee = 82_000_000_000 - defaultGasFeeLimit = 200_000_000_000 + defaultGasFee = 82 // gwei + defaultGasFeeLimit = 200 // gwei ) var ( @@ -49,7 +49,7 @@ var ( Description: "This is the highest network fee rate you are willing to " + "pay on swap transactions. If gasfeelimit is lower than a market's " + "maxfeerate, you will not be able to trade on that market with this " + - "wallet. Units: wei", + "wallet. Units: gwei / gas", DefaultValue: defaultGasFeeLimit, }, { @@ -62,7 +62,7 @@ var ( // WalletInfo defines some general information about a Ethereum wallet. WalletInfo = &asset.WalletInfo{ Name: "Ethereum", - Units: "wei", + Units: "gwei", DefaultConfigPath: defaultAppDir, // Incorrect if changed by user? ConfigOpts: configOpts, } @@ -219,25 +219,25 @@ func (eth *ExchangeWallet) Connect(ctx context.Context) (*sync.WaitGroup, error) // OwnsAddress indicates if an address belongs to the wallet. // // In Ethereum, an address is an account. -// -// TODO: Consider adding multiple accounts. func (eth *ExchangeWallet) OwnsAddress(address string) (bool, error) { return strings.ToLower(eth.acct.Address.String()) == strings.ToLower(address), nil } -// Balance returns the total available funds in the account. -// -// NOTE: Ethereum balance does not return Immature or Locked values. +// Balance returns the total available funds in the account. The eth node +// returns balances in wei. Those are flored and stored as gwei, or 1e9 wei. // -// TODO: Ethereum balances can easily go over the max value of a uint64. -// asset.Balance must be changed in a way to accommodate this. +// TODO: Return Immature and Locked values. func (eth *ExchangeWallet) Balance() (*asset.Balance, error) { - bigbal, err := eth.node.balance(eth.ctx, eth.acct) + bigBal, err := eth.node.balance(eth.ctx, eth.acct) + if err != nil { + return nil, err + } + gwei, err := dexeth.ToGwei(bigBal) if err != nil { return nil, err } bal := &asset.Balance{ - Available: bigbal.Uint64(), + Available: gwei, // Immature: , How to know? // Locked: , Not lockable? } @@ -403,14 +403,15 @@ func (eth *ExchangeWallet) sendToAddr(addr common.Address, amt, gasFee *big.Int) return eth.node.sendTransaction(eth.ctx, tx) } -// Withdraw withdraws funds to the specified address. Fees are subtracted from -// the value. +// Withdraw withdraws funds to the specified address. Value is gwei. // -// TODO: Value could be larger than a uint64. Deal with it... // TODO: Return the asset.Coin. +// TODO: Subtract fees from the value. func (eth *ExchangeWallet) Withdraw(addr string, value uint64) (asset.Coin, error) { + bigVal := big.NewInt(0).SetUint64(value) + gweiFactorBig := big.NewInt(dexeth.GweiFactor) _, err := eth.sendToAddr(common.HexToAddress(addr), - big.NewInt(0).SetUint64(value), big.NewInt(0).SetUint64(defaultGasFee)) + bigVal.Mul(bigVal, gweiFactorBig), big.NewInt(0).SetUint64(defaultGasFee)) if err != nil { return nil, err } diff --git a/client/asset/eth/eth_test.go b/client/asset/eth/eth_test.go index ecf4ae38f7..982de672aa 100644 --- a/client/asset/eth/eth_test.go +++ b/client/asset/eth/eth_test.go @@ -40,6 +40,8 @@ type testNode struct { syncProgErr error peerInfo []*p2p.PeerInfo peersErr error + bal *big.Int + balErr error } func (n *testNode) connect(ctx context.Context, node *node.Node, addr common.Address) error { @@ -59,7 +61,7 @@ func (n *testNode) accounts() []*accounts.Account { return nil } func (n *testNode) balance(ctx context.Context, acct *accounts.Account) (*big.Int, error) { - return nil, nil + return n.bal, n.balErr } func (n *testNode) sendTransaction(ctx context.Context, tx map[string]string) (common.Hash, error) { return common.Hash{}, nil @@ -264,3 +266,70 @@ func TestSyncStatus(t *testing.T) { } } } + +func TestBalance(t *testing.T) { + maxInt := ^uint64(0) + maxWei := new(big.Int).SetUint64(maxInt) + gweiFactorBig := big.NewInt(dexeth.GweiFactor) + maxWei.Mul(maxWei, gweiFactorBig) + overMaxWei := new(big.Int).Set(maxWei) + overMaxWei.Add(overMaxWei, gweiFactorBig) + tests := []struct { + name string + bal *big.Int + balErr error + wantBal uint64 + wantErr bool + }{{ + name: "ok zero", + bal: big.NewInt(0), + wantBal: 0, + }, { + name: "ok rounded down", + bal: big.NewInt(dexeth.GweiFactor - 1), + wantBal: 0, + }, { + name: "ok one", + bal: big.NewInt(dexeth.GweiFactor), + wantBal: 1, + }, { + name: "ok max int", + bal: maxWei, + wantBal: maxInt, + }, { + name: "over max int", + bal: overMaxWei, + wantErr: true, + }, { + name: "node balance error", + bal: big.NewInt(0), + balErr: errors.New(""), + wantErr: true, + }} + + for _, test := range tests { + ctx, cancel := context.WithCancel(context.Background()) + node := &testNode{} + node.bal = test.bal + node.balErr = test.balErr + eth := &ExchangeWallet{ + node: node, + ctx: ctx, + log: tLogger, + } + bal, err := eth.Balance() + cancel() + if test.wantErr { + if err == nil { + t.Fatalf("expected error for test %q", test.name) + } + continue + } + if err != nil { + t.Fatalf("unexpected error for test %q: %v", test.name, err) + } + if bal.Available != test.wantBal { + t.Fatalf("want available balance %v got %v for test %q", test.wantBal, bal.Available, test.name) + } + } +} diff --git a/dex/testing/eth/harness.sh b/dex/testing/eth/harness.sh index d17809a1dc..607bc07348 100755 --- a/dex/testing/eth/harness.sh +++ b/dex/testing/eth/harness.sh @@ -78,6 +78,9 @@ cat > "${NODES_ROOT}/genesis.json" <