diff --git a/cmd/mercury/main.go b/cmd/mercury/main.go index f2b761f..22372cd 100644 --- a/cmd/mercury/main.go +++ b/cmd/mercury/main.go @@ -28,6 +28,8 @@ func main() { zecCache := cache.New(zecStore, logger) bchStore := kv.NewJSON(kv.NewMemDB()) bchCache := cache.New(bchStore, logger) + maticStore := kv.NewJSON(kv.NewMemDB()) + maticCache := cache.New(maticStore, logger) // Initialise Bitcoin API. btcTestnetURL := os.Getenv("BITCOIN_TESTNET_RPC_URL") @@ -62,25 +64,29 @@ func main() { "renex-ui": os.Getenv("INFURA_KEY_RENEX_UI"), "dcc": os.Getenv("INFURA_KEY_DCC"), } - infuraMainnetClient := rpc.NewInfuraClient(ethtypes.Mainnet, taggedKeys) + infuraMainnetClient := rpc.NewInfuraClient(ethtypes.EthMainnet, taggedKeys) ethMainnetProxy := proxy.NewProxy(infuraMainnetClient) - ethMainnetAPI := api.NewApi(ethtypes.Mainnet, ethMainnetProxy, ethCache, logger) + ethMainnetAPI := api.NewApi(ethtypes.EthMainnet, ethMainnetProxy, ethCache, logger) - var testnetClient rpc.Client + var ethTestnetClient rpc.Client ethKovanRPCURL := os.Getenv("ETH_KOVAN_RPC_URL") if ethKovanRPCURL == "" { logger.Infof("Using Infura") - testnetClient = rpc.NewInfuraClient(ethtypes.Kovan, taggedKeys) + ethTestnetClient = rpc.NewInfuraClient(ethtypes.EthKovan, taggedKeys) } else { logger.Infof("Using local ETH node at: %s", ethKovanRPCURL) ethKovanUser := os.Getenv("ETH_KOVAN_RPC_USERNAME") ethKovanPassword := os.Getenv("ETH_KOVAN_RPC_PASSWORD") - testnetClient = rpc.NewClient(ethKovanRPCURL, ethKovanUser, ethKovanPassword) + ethTestnetClient = rpc.NewClient(ethKovanRPCURL, ethKovanUser, ethKovanPassword) } - ethTestnetProxy := proxy.NewProxy(testnetClient) - ethTestnetAPI := api.NewApi(ethtypes.Kovan, ethTestnetProxy, ethKovanCache, logger) + ethTestnetProxy := proxy.NewProxy(ethTestnetClient) + ethTestnetAPI := api.NewApi(ethtypes.EthKovan, ethTestnetProxy, ethKovanCache, logger) + + maticTestnetClient := rpc.NewClient(os.Getenv("MATIC_TESTNET_RPC_URL"), "", "") + maticTestnetProxy := proxy.NewProxy(maticTestnetClient) + maticTestnetAPI := api.NewApi(ethtypes.MaticTestnet, maticTestnetProxy, maticCache, logger) // Set-up and start the server. - server := api.NewServer(logger, "5000", btcTestnetAPI, zecTestnetAPI, bchTestnetAPI, ethMainnetAPI, ethTestnetAPI) + server := api.NewServer(logger, "5000", btcTestnetAPI, zecTestnetAPI, bchTestnetAPI, ethMainnetAPI, ethTestnetAPI, maticTestnetAPI) server.Run() } diff --git a/go.mod b/go.mod index f8792d4..37306fc 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,11 @@ module github.com/renproject/mercury go 1.12 require ( + github.com/VividCortex/gohistogram v1.0.0 // indirect github.com/allegro/bigcache v1.2.1 // indirect github.com/apilayer/freegeoip v3.5.0+incompatible // indirect github.com/aristanetworks/goarista v0.0.0-20190712234253-ed1100a1c015 // indirect + github.com/binance-chain/go-sdk v1.0.8 github.com/btcsuite/btcd v0.0.0-20190807005414-4063feeff79a github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d github.com/cespare/cp v1.1.1 // indirect @@ -16,16 +18,18 @@ require ( github.com/elastic/gosigar v0.10.4 // indirect github.com/ethereum/go-ethereum v1.9.2 github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect + github.com/fortytw2/leaktest v1.3.0 // indirect github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect github.com/golang/protobuf v1.3.2 // indirect + github.com/google/gofuzz v1.0.0 // indirect github.com/gorilla/mux v1.7.3 - github.com/gorilla/websocket v1.4.0 // indirect github.com/graph-gophers/graphql-go v0.0.0-20190724201507-010347b5f9e6 // indirect github.com/hashicorp/golang-lru v0.5.3 // indirect github.com/howeyc/fsnotify v0.9.0 // indirect github.com/huin/goupnp v1.0.0 // indirect github.com/influxdata/influxdb v1.7.7 // indirect github.com/jackpal/go-nat-pmp v1.0.1 // indirect + github.com/jmhodges/levigo v1.0.0 // indirect github.com/karalabe/usb v0.0.0-20190819132248-550797b1cad8 // indirect github.com/mattn/go-colorable v0.1.2 // indirect github.com/mattn/go-isatty v0.0.9 // indirect @@ -33,7 +37,7 @@ require ( github.com/miguelmota/go-ethereum-hdwallet v0.0.0-20190720004541-5f6b3168e4a0 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/olekukonko/tablewriter v0.0.1 // indirect - github.com/onsi/ginkgo v1.9.0 + github.com/onsi/ginkgo v1.10.1 github.com/onsi/gomega v1.6.0 github.com/oschwald/maxminddb-golang v1.3.1 // indirect github.com/pborman/uuid v1.2.0 // indirect @@ -48,6 +52,8 @@ require ( github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 // indirect github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 // indirect github.com/syndtr/goleveldb v1.0.1-0.20190318030020-c3a204f8e965 // indirect + github.com/tendermint/btcd v0.0.0-20180816174608-e5840949ff4f + github.com/tendermint/tendermint v0.31.2-rc0 github.com/tyler-smith/go-bip39 v1.0.2 github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 // indirect golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586 @@ -56,3 +62,5 @@ require ( gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190709231704-1e4459ed25ff // indirect ) + +replace github.com/tendermint/go-amino => github.com/binance-chain/bnc-go-amino v0.14.1-binance.1 diff --git a/go.sum b/go.sum index 80982ed..bd63d42 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,10 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9 h1:HD8gA2tkByhMAwYaFAX9w2l7vxvBQ5NMoxDrkhqhtn4= github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -13,11 +16,20 @@ github.com/aristanetworks/goarista v0.0.0-20190712234253-ed1100a1c015 h1:7ABPr1+ github.com/aristanetworks/goarista v0.0.0-20190712234253-ed1100a1c015/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/binance-chain/bnc-go-amino v0.14.1-binance.1 h1:RU33Toj/38sztKjcJTdziUIL0MBoMF7Xt1gQ3bT2zK0= +github.com/binance-chain/bnc-go-amino v0.14.1-binance.1/go.mod h1:yaElUUxWtv/TC/ldGtlKAvS1vKwokxgJ1d97I+6is80= +github.com/binance-chain/go-sdk v1.0.8 h1:mC1Tai9diqIWuKTJmrFLal90OCsgtDvyLEItMvglaHA= +github.com/binance-chain/go-sdk v1.0.8/go.mod h1:ahR+bb8rCbVRuK9ukmNTr/ghj7n4awioQQgLS5xb7wQ= +github.com/binance-chain/ledger-cosmos-go v0.9.9-binance.1 h1:8mAtw1Tp/BhhTrsXmXM60H1fihcvcKLfo2ZSxShaXKw= +github.com/binance-chain/ledger-cosmos-go v0.9.9-binance.1/go.mod h1:FI6WAujuiBpoSavYreux2zTKyrUkngXDlRJczxsDK5M= +github.com/btcsuite/btcd v0.0.0-20181013004428-67e573d211ac/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= github.com/btcsuite/btcd v0.0.0-20190807005414-4063feeff79a h1:We35J+0yvVFrEXbtViYUW8H/wNOhqjIF3PsrW4yYmGw= github.com/btcsuite/btcd v0.0.0-20190807005414-4063feeff79a/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= @@ -28,11 +40,15 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU= github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/codahale/blake2 v0.0.0-20150924215134-8d10d0420cbf h1:5ZeQB3mThuz5C2MSER6T5GdtXTF9CMMk42F9BOyRsEQ= github.com/codahale/blake2 v0.0.0-20150924215134-8d10d0420cbf/go.mod h1:BO2rLUAZMrpgh6GBVKi0Gjdqw2MgCtJrtmUdDeZRKjY= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-iptables v0.4.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d h1:49RLWk1j44Xu4fjHb6JFYmeUnDORVwHNkDxaQ0ctCVU= +github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -54,9 +70,12 @@ github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaB github.com/elastic/gosigar v0.10.4 h1:6jfw75dsoflhBMRdO6QPzQUgLqUYTsQQQRkkcsHsuPo= github.com/elastic/gosigar v0.10.4/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs= github.com/ethereum/go-ethereum v1.9.2 h1:RMIHDO/diqXEgORSVzYx8xW9x2+S32PoAX5lQwya0Lw= +github.com/ethereum/go-ethereum v1.9.2 h1:RMIHDO/diqXEgORSVzYx8xW9x2+S32PoAX5lQwya0Lw= github.com/ethereum/go-ethereum v1.9.2/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= @@ -67,7 +86,11 @@ github.com/go-logfmt/logfmt v0.3.0 h1:8HUsc87TaSWLKwrnumgC8/YconD2fJQsRJAsWaPg2i github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -77,6 +100,8 @@ github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pO github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= @@ -101,6 +126,8 @@ github.com/influxdata/influxdb v1.7.7/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOpr github.com/jackpal/go-nat-pmp v1.0.1 h1:i0LektDkO1QlrTm/cSuP+PyBCDnYvjPLGl4LdWEMiaA= github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= +github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g= @@ -120,6 +147,7 @@ github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miguelmota/go-ethereum-hdwallet v0.0.0-20190720004541-5f6b3168e4a0 h1:DmK33IJe81zJOzLmzzBHWf2/fGB0tnvqLnvGu8S5wYY= github.com/miguelmota/go-ethereum-hdwallet v0.0.0-20190720004541-5f6b3168e4a0/go.mod h1:VVt+rn/itmf+9eZq9CAabVlsfsHveUNUQ0bRv3ChqxY= @@ -138,6 +166,8 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.9.0 h1:SZjF721BByVj8QH636/8S2DnX4n0Re3SteMmw3N+tzc= github.com/onsi/ginkgo v1.9.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.6.0 h1:8XTW0fcJZEq9q+Upcyws4JSGua2MFysCL5xkaSgHc+M= @@ -155,14 +185,23 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= +github.com/prometheus/client_golang v1.0.0 h1:vrDKnkGzuGvhNAL56c7DBz29ZL+KxnoR0x7enabFceM= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.1 h1:K0MGApIoQvMw27RTdJkPbr3JZ7DNbtxQNyi5STVM6Kw= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2 h1:6LJUbpNm42llc4HRCuvApCSWB/WfhuNo9K98Q9sNGfs= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic= github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a h1:9ZKAASQSHhDYGoxY8uLVpewe1GDZ2vu2Tr/vTdVAkFQ= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/renproject/kv v0.1.0 h1:i4XpBL2vkKMpZz7dhYhaPf/I3/3DNfSZkz9GY96UryE= github.com/renproject/kv v0.1.0/go.mod h1:1kC6F4r7jhMeyZtqc7Of047E/DpfHDphRg/bQHt08hA= github.com/renproject/phi v0.1.0 h1:ZOn7QeDribk/uV46OhQWcTLxyuLg7P+xR1Hfl5cOQuI= @@ -170,6 +209,7 @@ github.com/renproject/phi v0.1.0/go.mod h1:Hrxx2ONVpfByficRjyRd1trecalYr0lo7Z0ak github.com/renproject/rzl v0.1.0 h1:/ToITTp5zB04Ghv7FYk9Tnt0vsEo7Gv4pyEtSBVT+Tk= github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM= +github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= @@ -198,26 +238,50 @@ github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFd github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/syndtr/goleveldb v1.0.1-0.20190318030020-c3a204f8e965 h1:1oFLiOyVl+W7bnBzGhf7BbIv9loSFQcieWWYIjLqcAw= github.com/syndtr/goleveldb v1.0.1-0.20190318030020-c3a204f8e965/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA= +github.com/tendermint/btcd v0.0.0-20180816174608-e5840949ff4f h1:R0wLxgASGMoRQTF/dCSk4N+M3j9DLyPDzDff2WtCg/I= +github.com/tendermint/btcd v0.0.0-20180816174608-e5840949ff4f/go.mod h1:DC6/m53jtQzr/NFmMNEu0rxf18/ktVoVtMrnDD5pN+U= +github.com/tendermint/ed25519 v0.0.0-20171027050219-d8387025d2b9/go.mod h1:nt45hbhDkWVdMBkr2TOgOzCrpBccXdN09WOiOYTHVEk= +github.com/tendermint/tendermint v0.31.2-rc0 h1:Iltc7dXcninZMH0p7iMxJZOv4jXTUznwBwfWge5EJlo= +github.com/tendermint/tendermint v0.31.2-rc0/go.mod h1:ymcPyWblXCplCPQjbOYbrF1fWnpslATMVqiGgWbZrlc= github.com/tyler-smith/go-bip39 v1.0.2 h1:+t3w+KwLXO6154GNJY+qUtIxLTmFjfUmpguQT1OlOT8= github.com/tyler-smith/go-bip39 v1.0.2/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 h1:1cngl9mPEoITZG8s8cVcUy5CeIBYhEESkOB7m6Gmkrk= github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/zondax/hid v0.9.0 h1:eiT3P6vNxAEVxXMw66eZUAAnU2zD33JBkfG/EnfAKl8= +github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= +github.com/zondax/ledger-go v0.9.0 h1:oTrtFqPFA4VdCPRvqMaN45mQnJxkPc0JxoVZfCoUpjI= +github.com/zondax/ledger-go v0.9.0/go.mod h1:b2vIcu3u9gJoIx4kTWuXOgzGV7FPWeUktqRqVf6feG0= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44 h1:9lP3x0pW80sDI6t1UMSLA4to18W7R7imwAI/sWS9S8Q= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586 h1:7KByu05hhLed2MO29w7p1XfZvZ13m8mub3shuVftRs0= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7 h1:rTIdg5QFRR7XCaK4LCjBiPbx8j4DQRpdYMnGn/bJUEU= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -225,6 +289,7 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FY golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -240,6 +305,12 @@ golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/grpc v1.19.1 h1:TrBcJ1yqAl1G++wO39nD/qtgpsW9/1+QGrluyMGEYgM= +google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -249,8 +320,11 @@ gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7 gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190709231704-1e4459ed25ff h1:uuol9OUzSvZntY1v963NAbVd7A+PHLMz1FlCe3Lorcs= gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190709231704-1e4459ed25ff/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= +gopkg.in/resty.v1 v1.10.3 h1:w8FjChB7PWrvE5z6JX/gfFzVwTDj38qiAQJKgdWDGvA= +gopkg.in/resty.v1 v1.10.3/go.mod h1:nrgQYbPhkRfn2BfT32NNTLfq3K9NuHRB0MsAcA9weWY= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/rpc/infura_test.go b/rpc/infura_test.go index fcfd05f..41ba283 100644 --- a/rpc/infura_test.go +++ b/rpc/infura_test.go @@ -18,7 +18,7 @@ var _ = Describe("Infura RPC client", func() { Context("when interacting with the infura client", func() { It("should return the correct response", func() { infuraAPIKey := os.Getenv("INFURA_KEY_DEFAULT") - client := NewInfuraClient(ethtypes.Kovan, map[string]string{ + client := NewInfuraClient(ethtypes.EthKovan, map[string]string{ "": infuraAPIKey, }) diff --git a/sdk/account/ethaccount/ethaccount.go b/sdk/account/ethaccount/ethaccount.go index 29d6096..44a6f0d 100644 --- a/sdk/account/ethaccount/ethaccount.go +++ b/sdk/account/ethaccount/ethaccount.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" hdwallet "github.com/miguelmota/go-ethereum-hdwallet" "github.com/renproject/mercury/sdk/client/ethclient" + "github.com/renproject/mercury/types" "github.com/renproject/mercury/types/ethtypes" ) @@ -15,10 +16,9 @@ type Account interface { Client() ethclient.Client Address() ethtypes.Address Balance(ctx context.Context) (ethtypes.Amount, error) - Transfer(ctx context.Context, toAddress ethtypes.Address, value ethtypes.Amount, gasPrice ethtypes.Amount) (ethtypes.TxHash, error) - BuildUnsignedTx(ctx context.Context, toAddress ethtypes.Address, value ethtypes.Amount, gasLimit uint64, gasPrice ethtypes.Amount, data []byte) (ethtypes.Tx, error) + Transfer(ctx context.Context, toAddress ethtypes.Address, value ethtypes.Amount, gasPrice ethtypes.Amount) (types.TxHash, error) + Transact(ctx context.Context, toAddress ethtypes.Address, value ethtypes.Amount, gasPrice ethtypes.Amount, gasLimit uint64, data []byte) (types.TxHash, error) PrivateKey() *ecdsa.PrivateKey - SignUnsignedTx(ctx context.Context, utx *ethtypes.Tx) error } type account struct { @@ -65,18 +65,22 @@ func RandomAccount(client ethclient.Client) (Account, error) { return NewAccountFromPrivateKey(client, privateKey) } -func (acc *account) Transfer(ctx context.Context, toAddress ethtypes.Address, value ethtypes.Amount, gasPrice ethtypes.Amount) (ethtypes.TxHash, error) { +func (acc *account) Transfer(ctx context.Context, toAddress ethtypes.Address, value ethtypes.Amount, gasPrice ethtypes.Amount) (types.TxHash, error) { + return acc.Transact(ctx, toAddress, value, gasPrice, 21000, nil) +} + +func (acc *account) Transact(ctx context.Context, toAddress ethtypes.Address, value ethtypes.Amount, gasPrice ethtypes.Amount, gasLimit uint64, data []byte) (types.TxHash, error) { nonce, err := acc.client.PendingNonceAt(ctx, acc.address) // fmt.Printf("nonce fetched back from infura: %v", nonce) if err != nil { - return ethtypes.TxHash{}, fmt.Errorf("failed to get pending nonce: %v", err) + return types.TxHash(""), fmt.Errorf("failed to get pending nonce: %v", err) } - tx, err := acc.client.BuildUnsignedTx(ctx, nonce, toAddress, value, 21000, gasPrice, nil) + tx, err := acc.client.BuildUnsignedTx(ctx, nonce, toAddress, value, gasLimit, gasPrice, data) if err != nil { - return ethtypes.TxHash{}, err + return types.TxHash(""), err } if err := tx.Sign(acc.key); err != nil { - return ethtypes.TxHash{}, err + return types.TxHash(""), err } return acc.client.PublishSignedTx(ctx, tx) } @@ -85,7 +89,7 @@ func (acc *account) BuildUnsignedTx(ctx context.Context, toAddress ethtypes.Addr nonce, err := acc.client.PendingNonceAt(ctx, acc.address) // fmt.Printf("nonce fetched back from infura: %v", nonce) if err != nil { - return ethtypes.Tx{}, fmt.Errorf("failed to get pending nonce: %v", err) + return nil, fmt.Errorf("failed to get pending nonce: %v", err) } return acc.client.BuildUnsignedTx(ctx, nonce, toAddress, value, gasLimit, gasPrice, data) } @@ -98,7 +102,7 @@ func (acc *account) Client() ethclient.Client { return acc.client } -func (acc *account) SignUnsignedTx(ctx context.Context, utx *ethtypes.Tx) error { +func (acc *account) SignUnsignedTx(ctx context.Context, utx ethtypes.Tx) error { return utx.Sign(acc.key) } diff --git a/sdk/account/ethaccount/ethaccount_test.go b/sdk/account/ethaccount/ethaccount_test.go index 2f407e9..95a7600 100644 --- a/sdk/account/ethaccount/ethaccount_test.go +++ b/sdk/account/ethaccount/ethaccount_test.go @@ -27,32 +27,6 @@ var _ = Describe("eth account", func() { Expect(account.Address()).To(BeEquivalentTo(convertedAddr)) }) - It("can create an unsigned transaction", func() { - ctx := context.Background() - amount := ethtypes.Ether(3) - gasLimit := uint64(1000) - gasPrice := Client.SuggestGasPrice(ctx, types.Standard) - account, err := RandomAccount(Client) - Expect(err).NotTo(HaveOccurred()) - var data []byte - _, err = EthAccount.BuildUnsignedTx(ctx, account.Address(), amount, gasLimit, gasPrice, data) - Expect(err).NotTo(HaveOccurred()) - }) - - It("can sign an unsigned transaction", func() { - ctx := context.Background() - amount := ethtypes.Ether(3) - gasLimit := uint64(1000) - gasPrice := Client.SuggestGasPrice(ctx, types.Standard) - account, err := RandomAccount(Client) - Expect(err).NotTo(HaveOccurred()) - var data []byte - utx, err := EthAccount.BuildUnsignedTx(ctx, account.Address(), amount, gasLimit, gasPrice, data) - Expect(err).NotTo(HaveOccurred()) - err = EthAccount.SignUnsignedTx(ctx, &utx) - Expect(err).NotTo(HaveOccurred()) - }) - XIt("can transfer funds", func() { ctx := context.Background() amount := ethtypes.Ether(3) @@ -69,13 +43,7 @@ var _ = Describe("eth account", func() { Expect(err).NotTo(HaveOccurred()) Expect(bal.Eq(ethtypes.Wei(0))).Should(BeTrue()) var data []byte - tx, err := EthAccount.BuildUnsignedTx(ctx, account.Address(), amount, gasLimit, gasPrice, data) - fmt.Println(tx.Hash()) - Expect(err).NotTo(HaveOccurred()) - err = EthAccount.SignUnsignedTx(ctx, &tx) - fmt.Println(tx.Hash()) - Expect(err).NotTo(HaveOccurred()) - _, err = Client.PublishSignedTx(ctx, tx) + _, err = EthAccount.Transact(ctx, account.Address(), amount, gasPrice, gasLimit, data) Expect(err).NotTo(HaveOccurred()) // check new balance newBal, err := Client.Balance(ctx, account.Address()) diff --git a/sdk/client/bncclient/bncclient.go b/sdk/client/bncclient/bncclient.go new file mode 100644 index 0000000..5cc5a24 --- /dev/null +++ b/sdk/client/bncclient/bncclient.go @@ -0,0 +1,139 @@ +package bncclient + +import ( + "encoding/hex" + "fmt" + + "github.com/binance-chain/go-sdk/client/basic" + "github.com/binance-chain/go-sdk/client/query" + "github.com/binance-chain/go-sdk/client/websocket" + "github.com/binance-chain/go-sdk/types/msg" + "github.com/binance-chain/go-sdk/types/tx" + "github.com/renproject/mercury/types" + "github.com/renproject/mercury/types/bnctypes" +) + +type Client interface { + PrintTime() + Balances(from bnctypes.Address) (bnctypes.Coins, error) + Mint(from bnctypes.Address, coin bnctypes.Coin) (types.Tx, error) + Burn(from bnctypes.Address, coin bnctypes.Coin) (types.Tx, error) + Send(from bnctypes.Address, recipients bnctypes.Recipients) (types.Tx, error) + SubmitTx(tx types.Tx) error +} + +type client struct { + network bnctypes.Network + queryClient query.QueryClient + basicClient basic.BasicClient + wsClient websocket.WSClient +} + +func New(network bnctypes.Network) Client { + var baseURL string + switch network { + case bnctypes.Mainnet: + baseURL = "dex.binance.org" + case bnctypes.Testnet: + baseURL = "testnet-dex.binance.org" + default: + panic(types.ErrUnknownNetwork) + } + + c := basic.NewClient(baseURL) + return &client{ + network: network, + basicClient: c, + queryClient: query.NewClient(c), + wsClient: websocket.NewClient(c), + } +} + +func (client *client) PrintTime() { + t, err := client.queryClient.GetTime() + if err != nil { + fmt.Println(err) + return + } + fmt.Println(t.ApTime, t.BlockTime) +} + +func (client *client) Mint(from bnctypes.Address, coin bnctypes.Coin) (types.Tx, error) { + return client.BuildTx(from, msg.NewMintMsg( + from.AccAddress(), + coin.Denom, + coin.Amount, + )) +} + +func (client *client) Burn(from bnctypes.Address, coin bnctypes.Coin) (types.Tx, error) { + return client.BuildTx(from, msg.NewTokenBurnMsg( + from.AccAddress(), + coin.Denom, + coin.Amount, + )) +} + +func (client *client) Balances(from bnctypes.Address) (bnctypes.Coins, error) { + acc, err := client.queryClient.GetAccount(from.String()) + if err != nil { + return nil, err + } + balances := make([]bnctypes.Coin, len(acc.Balances)) + for i := range balances { + balances[i] = bnctypes.Coin{ + Denom: acc.Balances[i].Symbol, + Amount: acc.Balances[i].Free.ToInt64(), + } + } + return bnctypes.NewCoins(balances...), nil +} + +func (client *client) Send(from bnctypes.Address, recipients bnctypes.Recipients) (types.Tx, error) { + return client.BuildTx(from, recipients.SendTx(from)) +} + +func (client *client) BuildTx(from bnctypes.Address, m msg.Msg) (types.Tx, error) { + acc, err := client.queryClient.GetAccount(from.String()) + if err != nil { + return nil, err + } + + // prepare message to sign + signMsg := tx.StdSignMsg{ + ChainID: client.network.ChainID(), + AccountNumber: acc.Number, + Sequence: acc.Sequence, + Memo: "", + Msgs: []msg.Msg{m}, + Source: tx.Source, + } + + // special logic for createOrder, to save account query + if orderMsg, ok := m.(msg.CreateOrderMsg); ok { + orderMsg.ID = msg.GenerateOrderID(signMsg.Sequence+1, from.AccAddress()) + signMsg.Msgs[0] = orderMsg + } + + // validate messages + for _, m := range signMsg.Msgs { + if err := m.ValidateBasic(); err != nil { + return nil, err + } + } + + return bnctypes.NewTx(signMsg), nil +} + +func (client *client) SubmitTx(tx types.Tx) error { + stx, err := tx.Serialize() + if err != nil { + return err + } + params := map[string]string{} + params["sync"] = "true" + if _, err := client.basicClient.PostTx([]byte(hex.EncodeToString(stx)), params); err != nil { + return err + } + return nil +} diff --git a/sdk/client/bncclient/bncclient_suite_test.go b/sdk/client/bncclient/bncclient_suite_test.go new file mode 100644 index 0000000..06b9cc9 --- /dev/null +++ b/sdk/client/bncclient/bncclient_suite_test.go @@ -0,0 +1,13 @@ +package bncclient_test + +import ( + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +func TestBncclient(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Bncclient Suite") +} diff --git a/sdk/client/bncclient/bncclient_test.go b/sdk/client/bncclient/bncclient_test.go new file mode 100644 index 0000000..368d8fc --- /dev/null +++ b/sdk/client/bncclient/bncclient_test.go @@ -0,0 +1,43 @@ +package bncclient_test + +import ( + "fmt" + "os" + + "github.com/ethereum/go-ethereum/crypto" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + . "github.com/renproject/mercury/sdk/client/bncclient" + "github.com/renproject/mercury/types/bnctypes" +) + +var _ = Describe("bnc client", func() { + Context("when communicating with the testnet", func() { + It("should print the current time", func() { + client := New(bnctypes.Testnet) + client.PrintTime() + }) + + It("should get the correct balance of an address", func() { + privKey, err := crypto.HexToECDSA(os.Getenv("BNB_PRIVATE_KEY")) + Expect(err).Should(BeNil()) + address := bnctypes.AddressFromPubKey(privKey.PublicKey, bnctypes.Testnet) + Expect(err).Should(BeNil()) + fmt.Println(address) + client := New(bnctypes.Testnet) + client.Balances(bnctypes.Address(address)) + }) + + It("should transfer 0.001", func() { + privKey, err := crypto.HexToECDSA(os.Getenv("BNB_PRIVATE_KEY")) + Expect(err).Should(BeNil()) + address := bnctypes.AddressFromPubKey(privKey.PublicKey, bnctypes.Testnet) + Expect(err).Should(BeNil()) + client := New(bnctypes.Testnet) + tx, err := client.Send(address, bnctypes.Recipients{bnctypes.NewRecipent(address, bnctypes.NewBNBCoin(1000000))}) + Expect(err).Should(BeNil()) + tx.Sign(privKey) + Expect(client.SubmitTx(tx)).Should(BeNil()) + }) + }) +}) diff --git a/sdk/client/ethclient/ethclient.go b/sdk/client/ethclient/ethclient.go index d841584..addc4a7 100644 --- a/sdk/client/ethclient/ethclient.go +++ b/sdk/client/ethclient/ethclient.go @@ -7,6 +7,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + cTypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" mclient "github.com/renproject/mercury/sdk/client" "github.com/renproject/mercury/types" @@ -19,12 +20,12 @@ type Client interface { Balance(context.Context, ethtypes.Address) (ethtypes.Amount, error) BlockNumber(context.Context) (*big.Int, error) Contract(address ethtypes.Address, abi []byte) (ethtypes.Contract, error) - Confirmations(ctx context.Context, hash ethtypes.TxHash) (*big.Int, error) + Confirmations(ctx context.Context, hash types.TxHash) (*big.Int, error) EthClient() *ethclient.Client SuggestGasPrice(context.Context, types.TxSpeed) ethtypes.Amount PendingNonceAt(context.Context, ethtypes.Address) (uint64, error) BuildUnsignedTx(context.Context, uint64, ethtypes.Address, ethtypes.Amount, uint64, ethtypes.Amount, []byte) (ethtypes.Tx, error) - PublishSignedTx(context.Context, ethtypes.Tx) (ethtypes.TxHash, error) + PublishSignedTx(context.Context, ethtypes.Tx) (types.TxHash, error) GasLimit(context.Context) (uint64, error) } @@ -37,16 +38,7 @@ type client struct { // New returns a new Client of given ethereum network. func New(logger logrus.FieldLogger, network ethtypes.Network) (Client, error) { - var url string - switch network { - case ethtypes.Mainnet: - url = fmt.Sprintf("%s/eth/mainnet", mclient.MercuryURL) - case ethtypes.Kovan: - url = fmt.Sprintf("%s/eth/kovan", mclient.MercuryURL) - default: - return nil, types.ErrUnknownNetwork - } - return NewCustomClient(logger, url) + return NewCustomClient(logger, fmt.Sprintf("%s/%s/%s", mclient.MercuryURL, network.Chain(), network.String())) } // NewCustomClient returns an Client for a specific RPC url @@ -104,26 +96,34 @@ func (c *client) PendingNonceAt(ctx context.Context, fromAddress ethtypes.Addres func (c *client) BuildUnsignedTx(ctx context.Context, nonce uint64, toAddress ethtypes.Address, value ethtypes.Amount, gasLimit uint64, gasPrice ethtypes.Amount, data []byte) (ethtypes.Tx, error) { chainID, err := c.client.NetworkID(ctx) if err != nil { - return ethtypes.Tx{}, fmt.Errorf("error building unsigned tx. failed to get chain id. err=%v", err) + return nil, fmt.Errorf("error building unsigned tx. failed to get chain id. err=%v", err) } return ethtypes.NewUnsignedTx(chainID, nonce, toAddress, value, gasLimit, gasPrice, data), nil } // PublishSTX publishes a signed transaction -func (c *client) PublishSignedTx(ctx context.Context, tx ethtypes.Tx) (ethtypes.TxHash, error) { +func (c *client) PublishSignedTx(ctx context.Context, tx ethtypes.Tx) (types.TxHash, error) { // Pre-condition checks if !tx.IsSigned() { panic("pre-condition violation: cannot publish unsigned transaction") } - return tx.Hash(), c.client.SendTransaction(ctx, tx.ToTransaction()) + txBytes, err := tx.Serialize() + if err != nil { + return tx.Hash(), err + } + stx := new(cTypes.Transaction) + if err := stx.UnmarshalJSON(txBytes); err != nil { + return tx.Hash(), err + } + return tx.Hash(), c.client.SendTransaction(ctx, stx) } -func (c *client) Confirmations(ctx context.Context, hash ethtypes.TxHash) (*big.Int, error) { +func (c *client) Confirmations(ctx context.Context, hash types.TxHash) (*big.Int, error) { currentBlockNumber, err := c.BlockNumber(ctx) if err != nil { return nil, fmt.Errorf("error fetching current block number: %v", err) } - receipt, err := c.client.TransactionReceipt(ctx, common.Hash(hash)) + receipt, err := c.client.TransactionReceipt(ctx, common.HexToHash(string(hash))) if err != nil { return nil, fmt.Errorf("error fetching tx hash=%v receipt: %v", hash, err) } diff --git a/sdk/client/ethclient/ethclient_test.go b/sdk/client/ethclient/ethclient_test.go index dabd3b0..817dad4 100644 --- a/sdk/client/ethclient/ethclient_test.go +++ b/sdk/client/ethclient/ethclient_test.go @@ -33,7 +33,7 @@ var _ = Describe("eth client", func() { // Remove this once the ethereum node ancient block sync is done. XIt("can fetch the confirmations of a Kovan transaction", func() { Expect(err).NotTo(HaveOccurred()) - hash := ethtypes.NewTxHashFromHex("0x288a0fe0cb305195bac6fefa6b16df576f0180c229fe5b4a453d57b0dcb42673") + hash := types.TxHash("0x288a0fe0cb305195bac6fefa6b16df576f0180c229fe5b4a453d57b0dcb42673") ctx := context.Background() confs, err := client.Confirmations(ctx, hash) Expect(err).NotTo(HaveOccurred()) diff --git a/sdk/contract/erc20/erc20_test.go b/sdk/contract/erc20/erc20_test.go index 676a753..977d050 100644 --- a/sdk/contract/erc20/erc20_test.go +++ b/sdk/contract/erc20/erc20_test.go @@ -20,7 +20,7 @@ var _ = Describe("ERC20 contract", func() { UserAddress ethtypes.Address }{ { - ethtypes.Kovan, + ethtypes.EthKovan, ethtypes.AddressFromHex("0x2cd647668494c1b15743ab283a0f980d90a87394"), ethtypes.AddressFromHex("0xaD34c12F6000B28a7C583EfC19D631735d1313c4"), @@ -32,7 +32,7 @@ var _ = Describe("ERC20 contract", func() { // TODO: Add tests for the other functions on the ERC20 contract Context("when interacting with an ERC20 contract", func() { It("should be able to call decimals on an ERC20 contract", func() { - client, err := ethclient.New(logrus.StandardLogger(), ethtypes.Kovan) + client, err := ethclient.New(logrus.StandardLogger(), testcase.Network) Expect(err).Should(BeNil()) erc20, err := New(client, testcase.ContractAddress) Expect(err).Should(BeNil()) diff --git a/sdk/gateway/btcgateway/btcgateway_test.go b/sdk/gateway/btcgateway/btcgateway_test.go index 786a0e4..d5d3573 100644 --- a/sdk/gateway/btcgateway/btcgateway_test.go +++ b/sdk/gateway/btcgateway/btcgateway_test.go @@ -2,6 +2,7 @@ package btcgateway_test import ( "context" + "crypto/ecdsa" "fmt" "strings" "time" @@ -32,114 +33,55 @@ var _ = Describe("btc gateway", func() { return wallet } - // TODO: finish writing these tests - // testCases := []struct { - // Network btctypes.Network - // UTXOs btctypes.UTXOs - - // GatewayAddress btctypes.Address - // GatewayScript []byte - // GatewayUTXO btctypes.UTXO - - // FundingTx string - // SpendingTx string - // }{ - // { - // btctypes.BtcTestnet, - // btctypes.UTXOs{}, - - // btctypes.Address{}, - // nil, - // btctypes.UTXO{}, - - // "", - // "", - // }, - // { - // btctypes.ZecTestnet, - // btctypes.UTXOs{}, - - // btctypes.Address{}, - // nil, - // btctypes.UTXO{}, - - // "", - // "", - // }, - // } - - // for _, testcase := range testCases { - // Context(fmt.Sprintf("locally validating %s gateways", testcase.Network.Chain()), func() { - // It(fmt.Sprintf("should be able to generate a %v gateway", testcase.Network), func() { - // client, err := btcclient.New(logger, testcase.Network) - // Expect(err).NotTo(HaveOccurred()) - // key, err := loadTestAccounts(client.Network()).EcdsaKey(44, 1, 1, 0, 1) - // gateway := New(client, key.PublicKey, []byte{}) - // Expect(gateway.Address()).Should(Equal(testcase.GatewayAddress)) - - // }) - - // It(fmt.Sprintf("should be able to generate a %v gateway", testcase.Network), func() { - // client, err := btcclient.New(logger, testcase.Network) - // Expect(err).NotTo(HaveOccurred()) - // key, err := loadTestAccounts(client.Network()).EcdsaKey(44, 1, 0, 0, 1) - // gateway := New(client, key.PublicKey, []byte{}) - - // address, err := btctypes.AddressFromPubKey(key.PublicKey, client.Network()) - // Expect(err).NotTo(HaveOccurred()) - - // // send to gateway - // recipients := btctypes.Recipients{ - // { - // Address: gateway.Address(), - // Amount: 20000 * btctypes.SAT, - // }, - // } - - // tx, err := client.BuildUnsignedTx(testcase.UTXOs, recipients, address, 10000) - // Expect(err).NotTo(HaveOccurred()) - // Expect(tx.Sign(key)).NotTo(HaveOccurred()) - - // txData, err := tx.Serialize() - // Expect(err).NotTo(HaveOccurred()) - // Expect(fmt.Sprintf("%x", txData)).Should(Equal(testcase.FundingTx)) - - // txHash := tx.Hash() - // fmt.Printf("funding gateway address=%v with txhash=%v\n", gateway.Address(), txHash) - - // // Fetch the UTXOs for the transaction hash - // gatewayUTXO, err := gateway.UTXO(tx.OutPoint(gateway.Address())) - // Expect(err).NotTo(HaveOccurred()) - // // fmt.Printf("utxo: %v", gatewayUTXO) - // gatewayUTXOs := btctypes.UTXOs{gatewayUTXO} - // Expect(len(gatewayUTXOs)).To(BeNumerically(">", 0)) - // txSize := gateway.EstimateTxSize(0, len(gatewayUTXOs), 1) - // gasAmount := client.SuggestGasPrice(context.Background(), types.Standard, txSize) - // fmt.Printf("gas amount=%v", gasAmount) - // recipients = btctypes.Recipients{{ - // Address: address, - // Amount: gatewayUTXOs.Sum() - gasAmount, - // }} - // tx, err = client.BuildUnsignedTx(gatewayUTXOs, recipients, address, gasAmount) - // Expect(err).NotTo(HaveOccurred()) - - // // Sign the transaction - // subScripts := tx.SignatureHashes() - // sigs := make([]*btcec.Signature, len(subScripts)) - // for i, subScript := range subScripts { - // sigs[i], err = (*btcec.PrivateKey)(key).Sign(subScript) - // Expect(err).NotTo(HaveOccurred()) - // } - // serializedPK := btctypes.SerializePublicKey(key.PublicKey, client.Network()) - // err = tx.InjectSignatures(sigs, serializedPK) - - // Expect(err).NotTo(HaveOccurred()) - // newTxHash, err := client.SubmitSignedTx(tx) - // Expect(err).NotTo(HaveOccurred()) - // fmt.Printf("spending gateway funds with tx hash=%v\n", newTxHash) - // }) - // }) - // } + testCases := []struct { + Network btctypes.Network + GatewayAddress string + SpenderAddress string + }{ + { + btctypes.BtcTestnet, + "2NDzN2erre3RS7UY8ieY1LsiZ7AwNxGEnTU", + "mzPbx28MWBrEZdXbjauVgf8UgnCm5hFdpf", + }, + { + btctypes.ZecTestnet, + + "t2V72Lwadq2hkH1rdcgckLBEitRUtcViUU1", + "tmXymiPTMYvNjVbfG2xa9S3hsUiKvd1SvMS", + }, + { + btctypes.BchTestnet, + + "ppl7dtqf2zx0l0sln2r53mvlyc4see253ujcxsvvq8", + "qqdwdwu3lpcpcusct56l3t5ptvw32tv7ns4ez829fa", + }, + } + + for _, testcase := range testCases { + testcase := testcase + Context(fmt.Sprintf("locally validating %s gateways", testcase.Network.Chain()), func() { + It(fmt.Sprintf("should be able to generate a %v gateway", testcase.Network), func() { + client := btcclient.NewClient(logger, testcase.Network) + key, err := loadTestAccounts(client.Network()).EcdsaKey(44, 1, 1, 0, 1) + Expect(err).Should(BeNil()) + gateway := New(client, key.PublicKey, []byte{}) + Expect(gateway.Address().EncodeAddress()).Should(Equal(testcase.GatewayAddress)) + }) + + It(fmt.Sprintf("should be able to generate a %v gateway", testcase.Network), func() { + client := btcclient.NewClient(logger, testcase.Network) + key, err := loadTestAccounts(client.Network()).EcdsaKey(44, 1, 1, 0, 1) + Expect(err).Should(BeNil()) + gateway := New(client, key.PublicKey, []byte{}) + Expect(gateway.Spender().EncodeAddress()).Should(Equal(testcase.SpenderAddress)) + }) + + It(fmt.Sprintf("should panic when trying to use an invalid pub key to generate %v gateway", testcase.Network), func() { + client := btcclient.NewClient(logger, testcase.Network) + Expect(func() { New(client, ecdsa.PublicKey{}, []byte{}) }).Should(Panic()) + }) + }) + } Context("when generating gateways", func() { networks := []btctypes.Network{btctypes.BtcLocalnet, btctypes.ZecLocalnet, btctypes.BchLocalnet} diff --git a/testutil/btcaccount/btcaccount.go b/testutil/btcaccount/btcaccount.go index 9739b9f..536c0cf 100644 --- a/testutil/btcaccount/btcaccount.go +++ b/testutil/btcaccount/btcaccount.go @@ -100,7 +100,7 @@ func (acc *account) Transfer(ctx context.Context, to btctypes.Address, value btc return "", fmt.Errorf("error fetching utxos: %v", err) } - fee := acc.Client.SuggestGasPrice(context.Background(), speed, acc.Client.EstimateTxSize(len(utxos), 2)) + fee := 10000 * btctypes.SAT if all { value = utxos.Sum() - fee } diff --git a/testutil/keys.go b/testutil/keys.go index 499b9e8..9104371 100644 --- a/testutil/keys.go +++ b/testutil/keys.go @@ -80,3 +80,7 @@ func RandomSegWitAddress(network btctypes.Network) (btctypes.Address, error) { } return btctypes.SegWitAddressFromPubKey(key.PublicKey, network) } + +func RandomKey() (*ecdsa.PrivateKey, error) { + return ecdsa.GenerateKey(secp256k1.S256(), rand.Reader) +} diff --git a/types/bnctypes/address.go b/types/bnctypes/address.go new file mode 100644 index 0000000..df4d568 --- /dev/null +++ b/types/bnctypes/address.go @@ -0,0 +1,71 @@ +package bnctypes + +import ( + "crypto/ecdsa" + "encoding/hex" + + "github.com/binance-chain/go-sdk/common/types" + "github.com/binance-chain/go-sdk/types/msg" + "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcutil" +) + +type Recipient struct { + Address Address + Coins Coins +} + +type Recipients []Recipient + +type Address struct { + Network Network + PubKeyHash []byte +} + +func (recipients Recipients) SendTx(from Address) msg.SendMsg { + types.Network = from.Network.ChainNetwork() + var inputCoins types.Coins + ops := make([]msg.Output, len(recipients)) + for i, recipient := range recipients { + ops[i] = msg.Output{ + Address: recipient.Address.AccAddress(), + Coins: types.Coins(recipient.Coins), + } + ops[i].Coins = ops[i].Coins.Sort() + inputCoins = inputCoins.Plus(ops[i].Coins) + } + ips := []msg.Input{{Address: from.AccAddress(), Coins: inputCoins}} + return msg.SendMsg{Inputs: ips, Outputs: ops} +} + +func AddressFromBech32(address string, network Network) (Address, error) { + types.Network = network.ChainNetwork() + accAddr, err := types.AccAddressFromBech32(address) + if err != nil { + return Address{}, err + } + return Address{PubKeyHash: accAddr, Network: network}, nil +} + +func AddressFromHex(address string, network Network) (Address, error) { + pkh, err := hex.DecodeString(address) + if err != nil { + return Address{}, err + } + return Address{PubKeyHash: pkh, Network: network}, nil +} + +func AddressFromPubKey(pubKey ecdsa.PublicKey, network Network) Address { + pkHash := btcutil.Hash160((*btcec.PublicKey)(&pubKey).SerializeCompressed()) + return Address{network, pkHash} +} + +func (addr Address) AccAddress() types.AccAddress { + types.Network = addr.Network.ChainNetwork() + return types.AccAddress(addr.PubKeyHash) +} + +func (addr Address) String() string { + types.Network = addr.Network.ChainNetwork() + return types.AccAddress(addr.PubKeyHash).String() +} diff --git a/types/bnctypes/bnctypes.go b/types/bnctypes/bnctypes.go new file mode 100644 index 0000000..662bb5e --- /dev/null +++ b/types/bnctypes/bnctypes.go @@ -0,0 +1,72 @@ +package bnctypes + +import ( + "strings" + + btypes "github.com/binance-chain/go-sdk/common/types" + "github.com/renproject/mercury/types" +) + +type Network interface { + types.Network + + ChainID() string + ChainNetwork() btypes.ChainNetwork +} + +type network uint8 + +const ( + Testnet = network(0) + Mainnet = network(1) +) + +// NewNetwork parse the network from a string. +func NewNetwork(network string) Network { + network = strings.ToLower(network) + switch network { + case "testnet": + return Testnet + case "mainnet": + return Mainnet + default: + panic(types.ErrUnknownChain) + } +} + +func (net network) String() string { + switch net { + case Testnet: + return "testnet" + case Mainnet: + return "mainnet" + default: + panic(types.ErrUnknownNetwork) + } +} + +func (net network) ChainID() string { + switch net { + case Testnet: + return "Binance-Chain-Nile" + case Mainnet: + return "Binance-Chain-Tigris" + default: + panic(types.ErrUnknownNetwork) + } +} + +func (net network) Chain() types.Chain { + return types.Binance +} + +func (net network) ChainNetwork() btypes.ChainNetwork { + switch net { + case Testnet: + return btypes.TestNetwork + case Mainnet: + return btypes.ProdNetwork + default: + panic(types.ErrUnknownNetwork) + } +} diff --git a/types/bnctypes/coin.go b/types/bnctypes/coin.go new file mode 100644 index 0000000..ff8d6c6 --- /dev/null +++ b/types/bnctypes/coin.go @@ -0,0 +1,22 @@ +package bnctypes + +import "github.com/binance-chain/go-sdk/common/types" + +type Coin types.Coin +type Coins types.Coins + +func NewBNBCoin(amount int64) Coin { + return Coin{"BNB", amount} +} + +func NewRecipent(address Address, coins ...Coin) Recipient { + return Recipient{address, NewCoins(coins...)} +} + +func NewCoins(coins ...Coin) Coins { + bCoins := make(Coins, len(coins)) + for i := range coins { + bCoins[i] = types.Coin(coins[i]) + } + return bCoins +} diff --git a/types/bnctypes/tx.go b/types/bnctypes/tx.go new file mode 100644 index 0000000..85946c8 --- /dev/null +++ b/types/bnctypes/tx.go @@ -0,0 +1,86 @@ +package bnctypes + +import ( + "crypto/ecdsa" + + "github.com/binance-chain/go-sdk/types/tx" + "github.com/btcsuite/btcd/btcec" + "github.com/renproject/mercury/types" + tmbtcec "github.com/tendermint/btcd/btcec" + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/secp256k1" +) + +type BNCTx interface { + types.Tx +} + +type bncTx struct { + msg tx.StdSignMsg + tx tx.StdTx + signed bool +} + +func NewTx(msg tx.StdSignMsg) BNCTx { + return &bncTx{ + msg: msg, + } +} + +func (bncTx *bncTx) SignatureHashes() []types.SignatureHash { + return []types.SignatureHash{crypto.Sha256(bncTx.msg.Bytes())} +} + +func (bncTx *bncTx) Sign(key *ecdsa.PrivateKey) (err error) { + hashes := bncTx.SignatureHashes() + sigs := make([]*btcec.Signature, len(hashes)) + privKey := (*btcec.PrivateKey)(key) + for i, hash := range hashes { + sigs[i], err = privKey.Sign(hash) + if err != nil { + return err + } + } + return bncTx.InjectSignatures(sigs, key.PublicKey) +} + +func (bncTx *bncTx) IsSigned() bool { + return bncTx.signed +} + +func (bncTx *bncTx) Serialize() ([]byte, error) { + return tx.Cdc.MarshalBinaryLengthPrefixed(&bncTx.tx) +} + +func (bncTx *bncTx) Hash() types.TxHash { + panic("unimplemented") +} + +func (bncTx *bncTx) InjectSignatures(sigs []*btcec.Signature, pubKey ecdsa.PublicKey) error { + publicKey := (btcec.PublicKey)(pubKey) + var pubkeyBytes secp256k1.PubKeySecp256k1 + copy(pubkeyBytes[:], publicKey.SerializeCompressed()) + sig := tmbtcec.Signature{R: sigs[0].R, S: sigs[0].S} + bncTx.tx = tx.NewStdTx(bncTx.msg.Msgs, []tx.StdSignature{tx.StdSignature{ + AccountNumber: bncTx.msg.AccountNumber, + Sequence: bncTx.msg.Sequence, + PubKey: pubkeyBytes, + Signature: sig.Serialize(), + }}, bncTx.msg.Memo, bncTx.msg.Source, bncTx.msg.Data) + bncTx.signed = true + return nil +} + +func (bncTx *bncTx) InjectSigs(sigs [][]byte, pubKey ecdsa.PublicKey) error { + publicKey := (btcec.PublicKey)(pubKey) + var pubkeyBytes secp256k1.PubKeySecp256k1 + copy(pubkeyBytes[:], publicKey.SerializeCompressed()) + bncTx.tx = tx.NewStdTx(bncTx.msg.Msgs, []tx.StdSignature{tx.StdSignature{ + AccountNumber: bncTx.msg.AccountNumber, + Sequence: bncTx.msg.Sequence, + PubKey: pubkeyBytes, + Signature: sigs[0], + }}, bncTx.msg.Memo, bncTx.msg.Source, bncTx.msg.Data) + bncTx.signed = true + return nil +} diff --git a/types/btctypes/tx.go b/types/btctypes/tx.go index a26ddec..62497a8 100644 --- a/types/btctypes/tx.go +++ b/types/btctypes/tx.go @@ -18,6 +18,7 @@ type BtcTx interface { UTXOs() UTXOs Recipients() Recipients OutputUTXO(address Address) UTXO + InjectSignatures(sigs []*btcec.Signature, pubKey ecdsa.PublicKey) error } type tx struct { @@ -124,6 +125,18 @@ func (t *tx) Hash() types.TxHash { return types.TxHash(t.tx.TxHash().String()) } +func (t *tx) InjectSigs(sigs [][]byte, pubKey ecdsa.PublicKey) error { + signatures := make([]*btcec.Signature, len(sigs)) + for i, sig := range sigs { + signature, err := btcec.ParseSignature(sig, btcec.S256()) + if err != nil { + return err + } + signatures[i] = signature + } + return t.InjectSignatures(signatures, pubKey) +} + // InjectSignatures injects the signed signatureHashes into the Tx. You cannot use the USTX anymore. scriptData is // additional data to be appended to the signature script, it can be nil or an empty byte array. func (t *tx) InjectSignatures(sigs []*btcec.Signature, pubKey ecdsa.PublicKey) error { diff --git a/types/ethtypes/address_test.go b/types/ethtypes/address_test.go new file mode 100644 index 0000000..a8270de --- /dev/null +++ b/types/ethtypes/address_test.go @@ -0,0 +1,34 @@ +package ethtypes_test + +import ( + "crypto/rand" + "encoding/hex" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + "github.com/renproject/mercury/testutil" + "github.com/renproject/mercury/types/ethtypes" +) + +var _ = Describe("eth addresses", func() { + + Context("when calculating addresses", func() { + It("should calcualte an address from ecdsa public key correctly", func() { + key, err := testutil.RandomKey() + Expect(err).Should(BeNil()) + Expect(func() { ethtypes.AddressFromPublicKey(&key.PublicKey) }).ShouldNot(Panic()) + }) + + It("should calcualte an address from hex string correctly", func() { + addrBytes := [20]byte{} + rand.Read(addrBytes[:]) + Expect(func() { ethtypes.AddressFromHex(hex.EncodeToString(addrBytes[:])) }).ShouldNot(Panic()) + }) + + It("should panic on nil public key", func() { + Expect(func() { ethtypes.AddressFromPublicKey(nil) }).Should(Panic()) + }) + }) + +}) diff --git a/types/ethtypes/contract.go b/types/ethtypes/contract.go index 618f9c2..e067e60 100644 --- a/types/ethtypes/contract.go +++ b/types/ethtypes/contract.go @@ -41,7 +41,7 @@ func (c *contract) BuildTx(ctx context.Context, from Address, method string, val data, err := c.abi.Pack(method, params...) if err != nil { - return Tx{}, fmt.Errorf("failed to pack data: %v", err) + return nil, fmt.Errorf("failed to pack data: %v", err) } // Ensure a valid value field and resolve the account nonce @@ -51,13 +51,13 @@ func (c *contract) BuildTx(ctx context.Context, from Address, method string, val nonce, err := c.client.PendingNonceAt(ctx, common.Address(from)) if err != nil { - return Tx{}, fmt.Errorf("failed to retrieve account nonce: %v", err) + return nil, fmt.Errorf("failed to retrieve account nonce: %v", err) } // Figure out the gas allowance and gas price values gasPrice, err := c.client.SuggestGasPrice(ctx) if err != nil { - return Tx{}, fmt.Errorf("failed to suggest gas price: %v", err) + return nil, fmt.Errorf("failed to suggest gas price: %v", err) } contractAddr := common.Address(c.address) @@ -65,7 +65,7 @@ func (c *contract) BuildTx(ctx context.Context, from Address, method string, val msg := ethereum.CallMsg{From: common.Address(from), To: &contractAddr, Value: value, Data: data} gasLimit, err := c.client.EstimateGas(ctx, msg) if err != nil { - return Tx{}, fmt.Errorf("failed to estimate gas needed: %v", err) + return nil, fmt.Errorf("failed to estimate gas needed: %v", err) } // Create the transaction, sign it and schedule it for execution @@ -78,10 +78,10 @@ func (c *contract) BuildTx(ctx context.Context, from Address, method string, val chainID, err := c.client.ChainID(ctx) if err != nil { - return Tx{}, fmt.Errorf("failed to get chain id: %v", err) + return nil, fmt.Errorf("failed to get chain id: %v", err) } - return Tx{ + return ðTx{ tx: rawTx, chainID: chainID, }, nil diff --git a/types/ethtypes/ethtypes.go b/types/ethtypes/ethtypes.go index c0f5ee1..e64f03d 100644 --- a/types/ethtypes/ethtypes.go +++ b/types/ethtypes/ethtypes.go @@ -2,32 +2,46 @@ package ethtypes import ( "crypto/ecdsa" - "math/big" "github.com/ethereum/go-ethereum/common" - coretypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/renproject/mercury/types" ) const ( - Mainnet network = 1 - Kovan network = 42 + EthMainnet network = 0 + EthKovan network = 1 + EthLocalnet network = 2 + + MaticMainnet network = 3 + MaticTestnet network = 4 + MaticLocalnet network = 5 ) func (network network) String() string { switch network { - case Mainnet: + case EthMainnet, MaticMainnet: return "mainnet" - case Kovan: + case EthKovan: return "kovan" + case MaticTestnet: + return "testnet" + case EthLocalnet, MaticLocalnet: + return "localnet" default: panic(types.ErrUnknownNetwork) } } func (network network) Chain() types.Chain { - return types.Ethereum + switch network { + case EthMainnet, EthKovan, EthLocalnet: + return types.Ethereum + case MaticMainnet, MaticTestnet, MaticLocalnet: + return types.Matic + default: + panic(types.ErrUnknownChain) + } } type Network interface { @@ -36,61 +50,8 @@ type Network interface { type network uint8 -type Tx struct { - chainID *big.Int - tx *coretypes.Transaction - signed bool -} - -type TxHash common.Hash - -func NewTxHashFromHex(hexString string) TxHash { - return TxHash(common.HexToHash(hexString)) -} - -func (tx *Tx) Hash() TxHash { - return TxHash(tx.tx.Hash()) -} - -func (tx *Tx) IsSigned() bool { - return tx.signed -} - -func (tx *Tx) ToTransaction() *coretypes.Transaction { - return tx.tx -} - -func (tx *Tx) Sign(key *ecdsa.PrivateKey) error { - // Pre-condition checks - if tx.IsSigned() { - panic("pre-condition violation: cannot sign already signed transaction") - } - - signer := coretypes.NewEIP155Signer(tx.chainID) - signedTx, err := coretypes.SignTx((*coretypes.Transaction)(tx.tx), signer, key) - if err != nil { - return err - } - - tx.tx = signedTx - tx.signed = true - return nil -} - -func NewUnsignedTx(chainID *big.Int, nonce uint64, to Address, value Amount, gasLimit uint64, gasPrice Amount, data []byte) Tx { - return Tx{ - chainID: chainID, - tx: coretypes.NewTransaction(nonce, common.Address(to), value.ToBig(), gasLimit, gasPrice.ToBig(), data), - signed: false, - } -} - -func NewSignedTx(chainID *big.Int, tx *coretypes.Transaction) Tx { - return Tx{ - chainID: chainID, - tx: tx, - signed: true, - } +type Tx interface { + types.Tx } type Address common.Address diff --git a/types/ethtypes/tx.go b/types/ethtypes/tx.go new file mode 100644 index 0000000..dad97d1 --- /dev/null +++ b/types/ethtypes/tx.go @@ -0,0 +1,77 @@ +package ethtypes + +import ( + "crypto/ecdsa" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + mTypes "github.com/renproject/mercury/types" +) + +type ethTx struct { + chainID *big.Int + tx *types.Transaction + signed bool +} + +// SignatureHashes() []SignatureHash +// InjectSignatures(sigs []*btcec.Signature, pubKey ecdsa.PublicKey) error + +func (tx *ethTx) Hash() mTypes.TxHash { + return mTypes.TxHash(tx.tx.Hash().String()) +} + +func (tx *ethTx) IsSigned() bool { + return tx.signed +} + +func (tx *ethTx) SignatureHashes() []mTypes.SignatureHash { + signer := types.NewEIP155Signer(tx.chainID) + return []mTypes.SignatureHash{signer.Hash(tx.tx).Bytes()} +} + +func (tx *ethTx) InjectSigs(sigs [][]byte, _ ecdsa.PublicKey) error { + signer := types.NewEIP155Signer(tx.chainID) + stx, err := tx.tx.WithSignature(signer, sigs[0]) + if err != nil { + return err + } + tx.tx = stx + tx.signed = true + return nil +} + +func (tx *ethTx) Serialize() ([]byte, error) { + return tx.tx.MarshalJSON() +} + +func (tx *ethTx) Sign(key *ecdsa.PrivateKey) error { + // Pre-condition checks + if tx.IsSigned() { + panic("pre-condition violation: cannot sign already signed transaction") + } + hashes := tx.SignatureHashes() + sig, err := crypto.Sign(hashes[0], key) + if err != nil { + return err + } + return tx.InjectSigs([][]byte{sig}, key.PublicKey) +} + +func NewUnsignedTx(chainID *big.Int, nonce uint64, to Address, value Amount, gasLimit uint64, gasPrice Amount, data []byte) Tx { + return ðTx{ + chainID: chainID, + tx: types.NewTransaction(nonce, common.Address(to), value.ToBig(), gasLimit, gasPrice.ToBig(), data), + signed: false, + } +} + +func NewSignedTx(chainID *big.Int, tx *types.Transaction) Tx { + return ðTx{ + chainID: chainID, + tx: tx, + signed: true, + } +} diff --git a/types/network.go b/types/network.go index 90c2de7..bde3622 100644 --- a/types/network.go +++ b/types/network.go @@ -12,6 +12,8 @@ const ( Ethereum Chain = 1 ZCash Chain = 2 BitcoinCash Chain = 3 + Binance Chain = 4 + Matic Chain = 5 ) func NewChain(chain string) Chain { @@ -23,6 +25,12 @@ func NewChain(chain string) Chain { return Ethereum case "ZCASH", "ZEC": return ZCash + case "BITCOIN CASH", "BCH", "BITCOINCASH": + return BitcoinCash + case "BINANCE", "BNC", "BNB": + return Binance + case "MATIC": + return Matic default: panic(ErrUnknownChain) } @@ -39,6 +47,10 @@ func (chain Chain) String() string { return "zec" case BitcoinCash: return "bch" + case Matic: + return "matic" + case Binance: + return "bnc" default: panic(ErrUnknownChain) } diff --git a/types/transaction.go b/types/transaction.go index 71eaa0c..4eb21bd 100644 --- a/types/transaction.go +++ b/types/transaction.go @@ -2,8 +2,6 @@ package types import ( "crypto/ecdsa" - - "github.com/btcsuite/btcd/btcec" ) type SignatureHash []byte @@ -16,5 +14,5 @@ type Tx interface { IsSigned() bool Serialize() ([]byte, error) Hash() TxHash - InjectSignatures(sigs []*btcec.Signature, pubKey ecdsa.PublicKey) error + InjectSigs(sigs [][]byte, pubKey ecdsa.PublicKey) error }