github.com/0chain/gosdk@v1.17.11/zcncore/ethwallet_base_test.go (about)

     1  package zcncore
     2  
     3  import (
     4  	"context"
     5  	"math/big"
     6  	"sync"
     7  	"testing"
     8  
     9  	"github.com/ethereum/go-ethereum/common"
    10  	"github.com/ethereum/go-ethereum/consensus/ethash"
    11  	"github.com/ethereum/go-ethereum/core"
    12  	"github.com/ethereum/go-ethereum/core/rawdb"
    13  	"github.com/ethereum/go-ethereum/core/types"
    14  	"github.com/ethereum/go-ethereum/crypto"
    15  	"github.com/ethereum/go-ethereum/eth"
    16  	"github.com/ethereum/go-ethereum/eth/ethconfig"
    17  	"github.com/ethereum/go-ethereum/ethclient"
    18  	"github.com/ethereum/go-ethereum/node"
    19  	"github.com/ethereum/go-ethereum/params"
    20  	"github.com/stretchr/testify/require"
    21  )
    22  
    23  var (
    24  	testKey, _  = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
    25  	testAddr    = crypto.PubkeyToAddress(testKey.PublicKey)
    26  	testBalance = big.NewInt(2e15)
    27  )
    28  
    29  func TestTokensConversion(t *testing.T) {
    30  	t.Run("Tokens to Eth", func(t *testing.T) {
    31  		ethTokens := TokensToEth(4337488392000000000)
    32  		require.Equal(t, 4.337488392, ethTokens)
    33  	})
    34  
    35  	t.Run("Eth to tokens", func(t *testing.T) {
    36  		ethTokens := EthToTokens(4.337488392)
    37  		require.Equal(t, int64(4337488392000000000), ethTokens)
    38  	})
    39  
    40  	t.Run("GTokens to Eth", func(t *testing.T) {
    41  		ethTokens := GTokensToEth(10000000)
    42  		require.Equal(t, 0.01, ethTokens)
    43  	})
    44  
    45  	t.Run("Eth to GTokens", func(t *testing.T) {
    46  		ethTokens := GEthToTokens(4.337488392)
    47  		require.Equal(t, int64(4337488392), ethTokens)
    48  	})
    49  }
    50  
    51  func TestValidEthAddress(t *testing.T) {
    52  	t.Run("Valid Eth wallet, but no balance", func(t *testing.T) {
    53  		_config.chain.EthNode = "test"
    54  		backend, _ := newTestBackend(t)
    55  		client, _ := backend.Attach()
    56  		defer backend.Close()
    57  		defer client.Close()
    58  
    59  		realClient := ethclient.NewClient(client)
    60  		getEthClient = func() (*ethclient.Client, error) {
    61  			return realClient, nil
    62  		}
    63  
    64  		res, err := IsValidEthAddress("0x531f9349ed2Fe5c526B47fa7841D35c90482e6cF")
    65  		require.Nil(t, err, "")
    66  		require.False(t, res, "")
    67  	})
    68  
    69  	t.Run("Valid Eth wallet", func(t *testing.T) {
    70  		_config.chain.EthNode = "test"
    71  		backend, _ := newTestBackend(t)
    72  		client, _ := backend.Attach()
    73  		defer backend.Close()
    74  		defer client.Close()
    75  
    76  		realClient := ethclient.NewClient(client)
    77  		err := sendTransaction(realClient)
    78  		require.Nil(t, err)
    79  
    80  		getEthClient = func() (*ethclient.Client, error) {
    81  			return realClient, nil
    82  		}
    83  
    84  		res, err := IsValidEthAddress(testAddr.String())
    85  		require.Nil(t, err, "")
    86  		require.True(t, res, "")
    87  	})
    88  
    89  	t.Run("Invalid Eth wallet", func(t *testing.T) {
    90  		_config.chain.EthNode = "test"
    91  		backend, _ := newTestBackend(t)
    92  		client, _ := backend.Attach()
    93  		defer backend.Close()
    94  		defer client.Close()
    95  
    96  		realClient := ethclient.NewClient(client)
    97  		getEthClient = func() (*ethclient.Client, error) {
    98  			return realClient, nil
    99  		}
   100  
   101  		res, err := IsValidEthAddress("testAddr.String()")
   102  		require.NotNil(t, err, "")
   103  		require.False(t, res, "")
   104  	})
   105  }
   106  
   107  func TestGetWalletAddrFromEthMnemonic(t *testing.T) {
   108  	t.Run("Success", func(t *testing.T) {
   109  		_config.chain.EthNode = "test"
   110  		mnemonic := "expect domain water near beauty bag pond clap chronic chronic length leisure"
   111  		res, err := GetWalletAddrFromEthMnemonic(mnemonic)
   112  		require.Nil(t, err, "")
   113  		require.Equal(t, res, "{\"ID\":\"0x531f9349ed2Fe5c526B47fa7841D35c90482e6cF\",\"PrivateKey\":\"b68bbd97a2b46b3fb2e38db771ec38935231f0b95733a4021d61601c658bc541\"}")
   114  	})
   115  
   116  	t.Run("Wrong", func(t *testing.T) {
   117  		_config.chain.EthNode = "test"
   118  		mnemonic := "this is wrong mnemonic"
   119  		_, err := GetWalletAddrFromEthMnemonic(mnemonic)
   120  		require.NotNil(t, err, "")
   121  	})
   122  }
   123  
   124  func TestGetEthBalance(t *testing.T) {
   125  	t.Run("Success", func(t *testing.T) {
   126  		_config.chain.EthNode = "test"
   127  		backend, _ := newTestBackend(t)
   128  		client, _ := backend.Attach()
   129  		defer backend.Close()
   130  		defer client.Close()
   131  
   132  		realClient := ethclient.NewClient(client)
   133  		err := sendTransaction(realClient)
   134  		require.Nil(t, err)
   135  
   136  		getEthClient = func() (*ethclient.Client, error) {
   137  			return realClient, nil
   138  		}
   139  
   140  		tcb := &MockBalanceCallback{}
   141  		tcb.wg = &sync.WaitGroup{}
   142  		tcb.wg.Add(1)
   143  		err = GetEthBalance(testAddr.String(), tcb)
   144  		if err != nil {
   145  			tcb.wg.Done()
   146  		}
   147  		tcb.wg.Wait()
   148  
   149  		require.Nil(t, err, "")
   150  		require.True(t, tcb.value > 0, "")
   151  		require.True(t, tcb.status == StatusSuccess, "")
   152  		require.True(t, tcb.info == "")
   153  	})
   154  }
   155  
   156  func TestCheckEthHashStatus(t *testing.T) {
   157  	t.Run("Pending transaction", func(t *testing.T) {
   158  		_config.chain.EthNode = "test"
   159  		backend, _ := newTestBackend(t)
   160  		client, _ := backend.Attach()
   161  		defer backend.Close()
   162  		defer client.Close()
   163  
   164  		realClient := ethclient.NewClient(client)
   165  		err := sendTransaction(realClient)
   166  		require.Nil(t, err)
   167  
   168  		getEthClient = func() (*ethclient.Client, error) {
   169  			return realClient, nil
   170  		}
   171  		result := CheckEthHashStatus("0x05aa8890d4778e292f837dd36b59a50931c175f4648c3d8157525f5454475cf7")
   172  		require.True(t, result < 0, "")
   173  	})
   174  }
   175  
   176  func TestSuggestEthGasPrice(t *testing.T) {
   177  	t.Run("suggest gas price success", func(t *testing.T) {
   178  		_config.chain.EthNode = "test"
   179  		backend, _ := newTestBackend(t)
   180  		client, _ := backend.Attach()
   181  		defer backend.Close()
   182  		defer client.Close()
   183  
   184  		realClient := ethclient.NewClient(client)
   185  		getEthClient = func() (*ethclient.Client, error) {
   186  			return realClient, nil
   187  		}
   188  		gas, err := SuggestEthGasPrice()
   189  		require.Nil(t, err)
   190  		require.True(t, gas > 0)
   191  	})
   192  }
   193  
   194  func TestTransferEthTokens(t *testing.T) {
   195  	t.Run("success transfer", func(t *testing.T) {
   196  		_config.chain.EthNode = "test"
   197  		backend, _ := newTestBackend(t)
   198  		client, _ := backend.Attach()
   199  		defer backend.Close()
   200  		defer client.Close()
   201  
   202  		realClient := ethclient.NewClient(client)
   203  		getEthClient = func() (*ethclient.Client, error) {
   204  			return realClient, nil
   205  		}
   206  
   207  		hash, err := TransferEthTokens("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291", 1000000000000, 10000)
   208  		require.Nil(t, err)
   209  		require.EqualValues(t, hash, "0x43eba8525933e34908e766de93176d810e8582e886052708d44d9db157803aec")
   210  	})
   211  }
   212  
   213  type MockBalanceCallback struct {
   214  	wg     *sync.WaitGroup
   215  	status int
   216  	value  int64
   217  	info   string
   218  }
   219  
   220  func (balCall *MockBalanceCallback) OnBalanceAvailable(status int, value int64, info string) {
   221  	defer balCall.wg.Done()
   222  
   223  	balCall.status = status
   224  	balCall.value = value
   225  	balCall.info = info
   226  }
   227  
   228  func newTestBackend(t *testing.T) (*node.Node, []*types.Block) {
   229  	// Generate test chain.
   230  	genesis, blocks := generateTestChain()
   231  	// Create node
   232  	n, err := node.New(&node.Config{})
   233  	if err != nil {
   234  		t.Fatalf("can't create new node: %v", err)
   235  	}
   236  	// Create Ethereum Service
   237  	config := &ethconfig.Config{Genesis: genesis}
   238  	config.Ethash.PowMode = ethash.ModeFake
   239  	ethservice, err := eth.New(n, config)
   240  	if err != nil {
   241  		t.Fatalf("can't create new ethereum service: %v", err)
   242  	}
   243  	// Import the test chain.
   244  	if err := n.Start(); err != nil {
   245  		t.Fatalf("can't start test node: %v", err)
   246  	}
   247  	if _, err := ethservice.BlockChain().InsertChain(blocks[1:]); err != nil {
   248  		t.Fatalf("can't import test blocks: %v", err)
   249  	}
   250  	return n, blocks
   251  }
   252  
   253  func generateTestChain() (*core.Genesis, []*types.Block) {
   254  	db := rawdb.NewMemoryDatabase()
   255  	config := params.AllEthashProtocolChanges
   256  	genesis := &core.Genesis{
   257  		Config:    config,
   258  		Alloc:     core.GenesisAlloc{testAddr: {Balance: testBalance}},
   259  		ExtraData: []byte("test genesis"),
   260  		Timestamp: 9000,
   261  	}
   262  	// BaseFee:   big.NewInt(params.InitialBaseFee),
   263  	generate := func(i int, g *core.BlockGen) {
   264  		g.OffsetTime(5)
   265  		g.SetExtra([]byte("test"))
   266  	}
   267  	gblock := genesis.ToBlock()
   268  	genesis.Commit(db) //nolint: errcheck
   269  	engine := ethash.NewFaker()
   270  	blocks, _ := core.GenerateChain(config, gblock, engine, db, 1, generate)
   271  	blocks = append([]*types.Block{gblock}, blocks...)
   272  	return genesis, blocks
   273  }
   274  
   275  func sendTransaction(ec *ethclient.Client) error {
   276  	// Retrieve chainID
   277  	chainID, err := ec.ChainID(context.Background())
   278  	if err != nil {
   279  		return err
   280  	}
   281  	// Create transaction
   282  	tx := types.NewTransaction(0, common.Address{1}, big.NewInt(1), 22000, big.NewInt(1), nil)
   283  	signer := types.LatestSignerForChainID(chainID)
   284  	signature, err := crypto.Sign(signer.Hash(tx).Bytes(), testKey)
   285  	if err != nil {
   286  		return err
   287  	}
   288  	signedTx, err := tx.WithSignature(signer, signature)
   289  	if err != nil {
   290  		return err
   291  	}
   292  	// Send transaction
   293  	return ec.SendTransaction(context.Background(), signedTx)
   294  }