Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Binance Chain #17

Open
wants to merge 28 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
9ff8063
types/bnctypes: add BinanceChain tx support
susruth Aug 4, 2019
98dd008
Add BinanceChain and Tendermint dependencies
susruth Aug 4, 2019
1346d93
types: add Binance Chain
susruth Aug 6, 2019
0afe4dc
types/bnctypes: add Address
susruth Aug 6, 2019
04b7864
types/bnctypes: add binance chain networks
susruth Aug 6, 2019
d09cb3c
sdk/client/bncclient: add basic binance client
susruth Aug 6, 2019
33e9bc9
updated dependencies
susruth Aug 6, 2019
43baab7
sdk/client/bncclient: add basic test for bncclient
susruth Aug 7, 2019
a091ed7
Merge branch 'master' into feat/binance-chain
susruth Aug 7, 2019
63f5299
types/bnctypes: updated AddressFromBech32
susruth Aug 29, 2019
54638e6
sdk/client/bncclient: add OpenOrder
susruth Aug 29, 2019
3250974
updated go modules
susruth Aug 29, 2019
90d7f87
sdk/client/bncclient: fixed binance base urls
susruth Sep 6, 2019
47961aa
updated go modules
susruth Sep 10, 2019
6646f65
resolved conflicts with master
susruth Sep 10, 2019
34cbaa8
resolved conflicts with master
susruth Sep 10, 2019
8f47640
resolved merge conflicts with master
susruth Sep 10, 2019
08637f6
types/bnctypes: updated to use binance sdk for address en/decoding
susruth Sep 11, 2019
d23c66e
sdk/client/bncclient: fixed to use the correct ChainID
susruth Sep 11, 2019
7c5bd37
updated to use the latest Ginkgo
susruth Sep 11, 2019
32679e9
types/bnctypes: add NewCoins
susruth Sep 12, 2019
564887e
sdk/client/bncclient: fixed balances function
susruth Sep 12, 2019
76f8cc4
Merge branch 'master' into feat/binance-chain
susruth Sep 12, 2019
2f4add5
testutil/btcaccount: updated to use fixed fee
susruth Sep 12, 2019
ec2ec32
sdk/client/bncclient: add mint and burn requests
susruth Sep 12, 2019
a9fce1b
types: add stringer impl for Binance
susruth Sep 12, 2019
8e1f6ed
types/bnctypes: updated to use local address string conv
susruth Sep 26, 2019
16227a7
go mod tidy
susruth Sep 26, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -16,24 +18,26 @@ 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
github.com/mattn/go-runewidth v0.0.4 // indirect
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
Expand All @@ -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
Expand All @@ -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
74 changes: 74 additions & 0 deletions go.sum

Large diffs are not rendered by default.

139 changes: 139 additions & 0 deletions sdk/client/bncclient/bncclient.go
Original file line number Diff line number Diff line change
@@ -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
}
13 changes: 13 additions & 0 deletions sdk/client/bncclient/bncclient_suite_test.go
Original file line number Diff line number Diff line change
@@ -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")
}
43 changes: 43 additions & 0 deletions sdk/client/bncclient/bncclient_test.go
Original file line number Diff line number Diff line change
@@ -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())
})
})
})
2 changes: 1 addition & 1 deletion testutil/btcaccount/btcaccount.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
71 changes: 71 additions & 0 deletions types/bnctypes/address.go
Original file line number Diff line number Diff line change
@@ -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()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is dangerous to change the global variable of the package. Maybe reimplement the function here along with the type you need.

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()
}
Loading