adshao / go-binance Goto Github PK
View Code? Open in Web Editor NEWA Go SDK for Binance API
License: MIT License
A Go SDK for Binance API
License: MIT License
How to get the listenKey for binance.WsUserDataServe(listenKey, wsHandler, errHandler)
I write test.go(appendix) completely copy from your library and execute it, then error: websocket :bad handshake
but if i directly use your library source.go(appendix) and excute it. it is ok and work well
why test.go can't get data?
test.go
package main
import (
"encoding/json"
"fmt"
"strings"
"time"
"github.com/gorilla/websocket"
)
var baseURL = "wss://stream.binance.com:9443"
var symbol = "BTCUSDT"
var WebsocketTimeout = time.Second * 60
var WebsocketKeepalive = false
// WsHandler handle raw websocket message
type WsHandler func(message []byte)
// ErrHandler handles errors
type ErrHandler func(err error)
type wsConfig struct {
endpoint string
}
func newWsConfig(endpoint string) *wsConfig {
return &wsConfig{
endpoint: endpoint,
}
}
var wsServe = func(cfg *wsConfig, handler WsHandler, errHandler ErrHandler) (doneC, stopC chan struct{}, err error) {
c, _, err := websocket.DefaultDialer.Dial(cfg.endpoint, nil)
if err != nil {
return nil, nil, err
}
doneC = make(chan struct{})
stopC = make(chan struct{})
go func() {
defer func() {
cerr := c.Close()
if cerr != nil {
errHandler(cerr)
}
}()
defer close(doneC)
if WebsocketKeepalive {
keepAlive(c, WebsocketTimeout)
}
for {
select {
case <-stopC:
return
default:
_, message, err := c.ReadMessage()
if err != nil {
errHandler(err)
return
}
handler(message)
}
}
}()
return
}
func keepAlive(c *websocket.Conn, timeout time.Duration) {
ticker := time.NewTicker(timeout)
lastResponse := time.Now()
c.SetPongHandler(func(msg string) error {
lastResponse = time.Now()
return nil
})
go func() {
defer ticker.Stop()
for {
deadline := time.Now().Add(10 * time.Second)
err := c.WriteControl(websocket.PingMessage, []byte{}, deadline)
if err != nil {
return
}
<-ticker.C
if time.Now().Sub(lastResponse) > timeout {
c.Close()
return
}
}
}()
}
type WsTradeHandler func(event *WsTradeEvent)
// WsTradeServe serve websocket handler with a symbol
func WsTradeServe(symbol string, handler WsTradeHandler, errHandler ErrHandler) (doneC, stopC chan struct{}, err error) {
endpoint := fmt.Sprintf("%s/%s@trade", baseURL, strings.ToLower(symbol))
cfg := newWsConfig(endpoint)
wsHandler := func(message []byte) {
event := new(WsTradeEvent)
err := json.Unmarshal(message, event)
if err != nil {
errHandler(err)
return
}
handler(event)
}
return wsServe(cfg, wsHandler, errHandler)
}
// WsTradeEvent define websocket trade event
type WsTradeEvent struct {
Event string `json:"e"`
Time int64 `json:"E"`
Symbol string `json:"s"`
TradeID int64 `json:"t"`
Price string `json:"p"`
Quantity string `json:"q"`
BuyerOrderID int64 `json:"b"`
SellerOrderID int64 `json:"a"`
TradeTime int64 `json:"T"`
IsBuyerMaker bool `json:"m"`
Placeholder bool `json:"M"` // add this field to avoid case insensitive unmarshaling
}
func main() {
wsTradeHandle := func(event *WsTradeEvent) {
fmt.Println(event)
}
errHandler := func(err error) {
fmt.Println(err)
}
doneC, _, err := WsTradeServe(symbol, wsTradeHandle, errHandler)
if err != nil {
fmt.Println(err)
return
}
<-doneC
}
source.go
package main
import (
"fmt"
"github.com/adshao/go-binance"
)
var wstradeHandler = func (event *binance.WsTradeEvent) {
fmt.Printf("%+v\n",event)
}
var errHandler = func(err error) {
fmt.Println(err)
}
func main() {
donC,_,_ := binance.WsTradeServe("BTCUSDT",wstradeHandler,errHandler)
<- donC
}
Hi adshao, first of all thanks for your work. Really appreaciated. I just wanted to ask you if there's a connection timeout or ping/pong mechanism to ensure connection stability?
Can we set proxy for the whole package?
It may be useful for dev.
Hi, v1.1.1 seems to be out of date with master from seeing the diff
I'm using this commit ID as revision in Gopkg.toml because v1.1.1 doesn't support binance.NewOrderRespTypeFULL
for example.
Could we tag another release?
Given this is going to be the new de facto standard golang dependency tool thought you might be interested to know it doesn't work.
scott@saruman:~/go/src/gitlab.com/apisw/myproject$ dep ensure -add github.com/adshao/go-binance
Fetching sources...
ensure Solve(): No versions of github.com/adshao/go-binance met constraints:
master: unexpected error while defensively updating submodules: : command failed: [git submodule update --init --recursive]: exit status 128
The issue seems to be some issue with a git submodule in the vendor directory - one time while doing "go get" I also got the error which is slightly more verbose giving some insight:
scott@saruman:~/go/src/gitlab.com/apisw/myproject$ go get github.com/adshao/go-binance
# cd /home/scott/go/src/github.com/adshao/go-binance; git submodule update --init --recursive
fatal: no submodule mapping found in .gitmodules for path 'vendor/github.com/bitly/go-simplejson'
package github.com/adshao/go-binance: exit status 128
Strangely, simply issuing the "go get" again and it worked. However, "dep ensure" never works. Thoughts?
I'm getting this error on NewExchangeInfoService.Do
I guess binance is returning an integer defined as string.
go-binance/exchange_info_service.go
Line 25 in e9a4ac0
I guess this endpoint is missing
https://github.com/binance-exchange/binance-official-api-docs/blob/master/wapi-api.md#deposit-address-user_data
Could you please also include this one
@jeremyhahn @sazor
Hello,
I was trying to use your client for writing a price ticker for Binance... i noticed that i can't list exchanges and therefore, i cannot fetch the symbols available to get tickers for.
the API: https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md#exchange-information is an official one by Binance so i was wondering why it's not available in your wrapper?
Update: Since i would like to get price data using websockets eventually, i have to fetch tickers through the API provided:
prices, err := client.NewListPricesService().Do(context.Background())
if err != nil {
fmt.Println(err)
return
}
for _, p := range prices {
fmt.Println(p)
}
and then get the symbol from this as a workaround.
Thanks,
Rakan
I am rewriting a project in go from javascript and the other library I used for websockets and candle updates provided me with the last 500 candles for a coin and then would provide updates to that candle. Does this service also do that? If not can you point me in the right direction?
update readme tutorial to use
It may be helpful for people who has unstable network .
Hello there. Nice library.
I am trying to cancel order with
resp, err := client.NewCancelOrderService().Symbol(pair).OrderID(orderId).Do(context.Background())
with pair and orderId as received from open orders API call.
Always results in:
Error: code=-2011, msg=UNKNOWN_ORDER - additional sleep
With debug mode enabled:
Binance-golang 2018/02/07 23:43:59 full url: https://www.binance.com/api/v3/order?timestamp=1518047039534&signature=xxxxxxxmodifiedxxxx, body: orderId=35911&symbol=BNBETH
Binance-golang 2018/02/07 23:44:00 response body: {"code":-2011,"msg":"UNKNOWN_ORDER"}
Everything appears correct. Any suggestions would be appreciated.
Hi all,
Is there any documentation that describe how to subscribe to the Diff. Depth Stream to locally keep an order book?
Thanks in advance
Binance has released the futures API documentation here:
https://binanceapitest.github.io/Binance-Future-API-test-doc/general_info/
It looks like we can place finally (useful) margin orders through the API when setting sideEffectType
to MARGIN_BUY
according to the Change Log from Nov 30th: https://binance-docs.github.io/apidocs/spot/en/#change-log.
It would be nice if it was added to the code of this package.
Binance has released margin api: https://github.com/binance-exchange/binance-official-api-docs/blob/master/margin-api.md
Please add this to the SDK, thank you @adshao!
Can this be updated to include the Stop Limit order type?
Options trading is going to be a thing when it comes to Desktop (only available on Mobile atm). @adshao do you have plans to implement it, or anyone else in the near future?
for reference https://binance-docs.github.io/apidocs/delivery/en/#change-log
Hi, could you help me with Binance timestamp conversion to Time in Golang? Cheers.
tm := time.Unix(order.Time, 0)
doesn't work and returns some time in the far far future.
Suddenly started getting the message: code=-1100, msg=Illegal characters found in parameter 'interval'; legal range is '5, 10, 20, 50, 100, 500, 1000'.
snapshot, err := client.NewDepthService().Symbol(sym.Symbol).Limit(100).Do(context.Background())
Occurs for different all different legal ranges. However does not occur for every single time, and is not dependent on a specific pair.
Basically, anybody who doesn't need the entire depth book and is only looking for the orders currently surrounding the market price would benefit from this.
The exchange info endpoint might return optional MAX_NUM_ALGO_ORDERS filter what leads to unmarshalling error. E.g.
{
"symbol": "ARDRBNB",
"status": "TRADING",
"baseAsset": "ARDR",
"baseAssetPrecision": 8,
"quoteAsset": "BNB",
"quotePrecision": 8,
"orderTypes": [
"LIMIT",
"LIMIT_MAKER",
"MARKET",
"STOP_LOSS_LIMIT",
"TAKE_PROFIT_LIMIT"
],
"icebergAllowed": false,
"filters": [
{
"filterType": "PRICE_FILTER",
"minPrice": "0.00178000",
"maxPrice": "0.17750000",
"tickSize": "0.00001000"
},
{
"filterType": "LOT_SIZE",
"minQty": "0.01000000",
"maxQty": "90000000.00000000",
"stepSize": "0.01000000"
},
{
"filterType": "MIN_NOTIONAL",
"minNotional": "1.00000000"
},
{
"filterType": "MAX_NUM_ALGO_ORDERS",
"maxNumAlgoOrders": 5
}
]
}
results to json: cannot unmarshal number into Go value of type string
It makes sense to alter Symbol from
// Symbol market symbol
type Symbol struct {
Symbol string `json:"symbol"`
Status string `json:"status"`
BaseAsset string `json:"baseAsset"`
BaseAssetPrecision int `json:"baseAssetPrecision"`
QuoteAsset string `json:"quoteAsset"`
QuotePrecision int `json:"quotePrecision"`
OrderTypes []string `json:"orderTypes"`
IcebergAllowed bool `json:"icebergAllowed"`
Filters []map[string]string `json:"filters"`
}
to
type Symbol struct {
Symbol string `json:"symbol"`
Status string `json:"status"`
BaseAsset string `json:"baseAsset"`
BaseAssetPrecision int `json:"baseAssetPrecision"`
QuoteAsset string `json:"quoteAsset"`
QuotePrecision int `json:"quotePrecision"`
OrderTypes []string `json:"orderTypes"`
IcebergAllowed bool `json:"icebergAllowed"`
Filters []map[string]interface{} `json:"filters"` //switched to interface{}
}
or create a new typed Filter entity
I'm not sure whether it's a problem regarding this SDK or if it's a problem with Binance (because I'm creating orders quickly one after the other - around 20ms between two orders).
Sometimes (like 50% of the time) the following error occurs when my bot tries to place an order:
code=-1106, msg=Parameter 'quantity' sent when not required.
I cannot see why the error occurs, it just seems to be random. I'm using the client to create market orders as quoted below. :
func order(market, side, amount string){ if side == "buy"{ _, err := client.NewCreateOrderService().Symbol(market). Side(binance.SideTypeBuy).Type(binance.OrderTypeMarket). Quantity(amount). Do(context.Background()) if err != nil{ fmt.Println(err) } } if side == "sell" { _, err := client.NewCreateOrderService().Symbol(market). Side(binance.SideTypeSell).Type(binance.OrderTypeMarket). Quantity(amount). Do(context.Background()) if err != nil{ fmt.Println(err) } } }
module github.com/adshao/go-binance
to
module github.com/adshao/go-binance/v2
I used the same way as mentioned on README.md
to close the websocket. It does close WsDepthServe
, but doesn't close WsUserServe
until I have placed an order to trigger the wsHandler
.
wsHandler := func(message []byte) {
fmt.Println(string(message))
}
errHandler := func(err error) {
fmt.Println(err)
}
doneC, stopC, err := binance.WsUserDataServe(listenKey, wsHandler, errHandler)
if err != nil {
fmt.Println(err)
return
}
// use stopC to exit
go func() {
time.Sleep(5 * time.Second)
stopC <- struct{}{}
}()
<-doneC
Is there a way to stop/pause the websocket stream from within the handler? I see the use of a timer and stopC in the WsDepthServe example in the readme, but that is not what I'm looking for. What would be the elegant way to stop the stream while its running without the use of a timer? Thanks!
code:
client := binance.NewClient("w1***gU", "PW***AW") client.Debug = true xhttp.SetProxy(client.HTTPClient, "socks5://127.0.0.1:1086") res, err := client.NewGetAccountService().Do(context.Background()) if err != nil { fmt.Println(err) return } fmt.Println(res)
logs:
Binance-golang 2018/12/23 11:22:24 full url: https://www.binance.com/api/v3/account?timestamp=1545535344786&signature=bd***c1, body:
Binance-golang 2018/12/23 11:22:24 request: &http.Request{Method:"GET", URL:(url.URL)(0xc000130200), Proto:"HTTP/1.1", ProtoMajor:1, ProtoMinor:1, Header:http.Header{"X-Mbx-Apikey":[]string{"w1**gU"}}, Body:http.noBody{}, GetBody:(func() (io.ReadCloser, error))(0x42df0f0), ContentLength:0, TransferEncoding:[]string(nil), Close:false, Host:"www.binance.com", Form:url.Values(nil), PostForm:url.Values(nil), MultipartForm:(*multipart.Form)(nil), Trailer:http.Header(nil), RemoteAddr:"", RequestURI:"", TLS:(*tls.ConnectionState)(nil), Cancel:(<-chan struct {})(nil), Response:(*http.Response)(nil), ctx:(*context.emptyCtx)(0xc0000240c8)}
Binance-golang 2018/12/23 11:22:25 response: &http.Response{Status:"401 Unauthorized", StatusCode:401, Proto:"HTTP/1.1", ProtoMajor:1, ProtoMinor:1, Header:http.Header{"Connection":[]string{"keep-alive"}, "Strict-Transport-Security":[]string{"max-age=31536000; includeSubdomains"}, "X-Frame-Options":[]string{"SAMEORIGIN"}, "Cache-Control":[]string{"no-cache, no-store, must-revalidate"}, "Content-Type":[]string{"application/json;charset=utf-8"}, "Server":[]string{"nginx"}, "Content-Security-Policy":[]string{"default-src 'self'"}, "X-Content-Security-Policy":[]string{"default-src 'self'"}, "Expires":[]string{"0"}, "X-Amz-Cf-Id":[]string{"Oa***QA=="}, "X-Xss-Protection":[]string{"1; mode=block"}, "X-Content-Type-Options":[]string{"nosniff"}, "X-Webkit-Csp":[]string{"default-src 'self'"}, "Pragma":[]string{"no-cache"}, "Via":[]string{"1.1 7ec9f593de3f3ecf42bf707a48dbe9c3.cloudfront.net (CloudFront)"}, "Date":[]string{"Sun, 23 Dec 2018 03:22:25 GMT"}, "X-Cache":[]string{"Error from cloudfront"}}, Body:(*http.bodyEOFSignal)(0xc00070a340), ContentLength:-1, TransferEncoding:[]string{"chunked"}, Close:false, Uncompressed:false, Trailer:http.Header(nil), Request:(*http.Request)(0xc00046a500), TLS:(*tls.ConnectionState)(0xc0000b18c0)}
Binance-golang 2018/12/23 11:22:25 response body: {"code":-2014,"msg":"API-key format invalid."}
Heya!
I've been using this package for a while now and really like it. There was one problem I encountered when creating orders and that was with the lot sizes. I wrote my own function to convert an amount to a lot sized amount.
Is this something you are interested in to include in the library?
Greetings
Hi,
I think this topic is what you might know, but as fyi, all go package release should be prefixed with "v" (e.g. v1.0.0, v1.1.0, v2.0.0...) so that go mod can find the version (Check this).
Also, I like your binance package better than official api code 😄
请问有没有计划开发包含主流交易所的整合性SDK,看了github上的项目,貌似只有一个,支持的还不是很完善。
Any chance for trade streams being added to this awesome project?
合并更方便使用,谢谢
Using go 1.8 on ubuntu 16.04 (WSL)
when trying to install:
go get github.com/adshao/go-binance
package context: unrecognized import path "context" (import path does not begin with hostname)
Error occurs in NewAggTradesService.
OS: mac os 10.11
Go: 1.9
Hi, I found two useful websocket endpoints which aren't implemented in this client.
Here is a link to documentation: https://github.com/binance-exchange/binance-official-api-docs/blob/master/web-socket-streams.md#individual-symbol-ticker-streams .
I've implemented it by myself and made pr #4 . Could you please review it?
diff --git a/margin_service.go b/margin_service.go
index e7e71f3..0078088 100644
--- a/margin_service.go
+++ b/margin_service.go
@@ -199,6 +199,7 @@ func (s *ListMarginLoansService) Do(ctx context.Context, opts ...RequestOption)
r := &request{
method: "GET",
endpoint: "/sapi/v1/margin/loan",
secType: secTypeSigned,
}
r.setParam("asset", s.asset)
if s.txID != nil {
follow-up on #125
It's sometimes hard (require external sync application), or not possible, and at best requires lots of tooling to be able to change the time machine, especially in cross environment (Windows, Linux, Darwin)... And in case one needs the require permissions to run such tools and do such modifications.
I see for example that the most popular Binance JS library is having such feature https://github.com/jaggedsoft/node-binance-api#troubleshooting. By making a call to that method, it sets an internal flag timeOffset https://github.com/jaggedsoft/node-binance-api/blob/d011f5845a91c06a0f4ef32ff08bed31d53cb29e/node-binance-api.js#L1207 used in subsequent signed requests here https://github.com/jaggedsoft/node-binance-api/blob/d011f5845a91c06a0f4ef32ff08bed31d53cb29e/node-binance-api.js#L192
I would have preferred myself go-binance to analyse the error code -1021 somewhere in the central callAPI method (https://github.com/adshao/go-binance/blob/master/client.go#L244) and in such case get the Binance time, set an internal offset and re-do the request. After all this library does not give a way to centralise errors from all different methods and so we don't have a good way to do that as of now.
Either way, I think that what is done in node-binance is at least a very acceptable trade-off which one could use in a hourly or daily cron job to ensure that the time is always quite accurate
Could you add this feature?
Thank you.
I tried to fetch new Klines in a loop, and the way I tried to achieve this was to update the KlineService's startTime
parameter with the CloseTime
value from the last Kline in a set of 1000 Klines in each iteration. I also tried to create a completely new KlineService with updated startTime
value but in both cases the KlineService only fetched the same 1000 Klines over and over again. Why is this?
This is a question, not an issue. I sometimes get an error: Error: error:<APIError> code=0, when using msg=``client.NewDepthService().Symbol("BNBUSDT").Do(context.Background())
. Do you what it means?
This error is not documented in binance error codes: https://github.com/binance-exchange/binance-official-api-docs/blob/master/errors.md
Please remove v1 endpoints in the package and update it with new v3 ones
It would be great if it could detect when the API rate limit is hit (code -1003) and subsequently wait for one minute, or until the ban is lifted: https://github.com/binance-exchange/binance-official-api-docs/blob/master/errors.md#-1003-too_many_requests
It's not just enough to count the weight placed, since the IP might be used by different apps, including also just accessing Binance in the browser. Also, or as an alternative, the app could save an internal counter of the requests saved and read the answer of the current limits as described here: https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md#limits
futuresClient.NewCreateOrderService().Symbol("BTCUSDT").Side(futures.SideTypeBuy).Type(futures.OrderTypeLimit).Quantity("0.2").Price("6550.44").Do(context.Background())
Hi,
I can't place the orde, my api works, account service works but orderservice not work.
I tried to use get withdraw fee using GetWithdrawFeeService but is is not working. It returns binance.APIError{Code: 0, Msg:""}.
I checked with official documentation, and it seems the does not have /wapi/v3/withdrawFee.html anymore. Instead, they have /wapi/v3/assetDetail.html, which they include withdrawFee there.
It would be great if you can implement assetDetail method to get assetDetail from Binance api.
Best regards,
Excuse me ,
what is Depth in api Show Depth ?
What would be the correct / elegant way to stop the WsKlineServe
client (or any other of the websocket clients)?
I see it's easy to get it up and running, but I'm not sure on how I can turn it on and off programatically.
Thanks!
There are a series of WebSocket APIs that are available for future market independently from the spot market and have different data. One of which would be binance.WsDepthEvent
:
currently the implementation is using baseURL
to access this websocket which is for the spot market. so I could not find a way to use this library to listen to Futures Diff. Book Depth Streams
.
This would mean for example I can not use this library to run the binance instructions for running a local copy of the order book
, since I am able to take the snap shot correctly for the future market using futures.DepthService
, but have not way to listen to Futures Diff ticks:
Hello,
I am trying to implement the WsAllMarketsStatServe function, but using your example code as a basis, I am constantly running into an error. Could you please help me? The error message is the following:
cannot use wsAllMarketsStatHandler (type func(*binance.WsAllMarketsStatEvent)) as type binance.WsAllMarketsStatHandler in argument to binance.WsAllMarketsStatServe
And below is my code:
wsAllMarketsStatHandler := func(event *binance.WsAllMarketsStatEvent) {
fmt.Println(event)
}
errHandler := func(err error) {
fmt.Println(err)
}
doneC, _, err := binance.WsAllMarketsStatServe(wsAllMarketsStatHandler, errHandler)
if err != nil {
fmt.Println(err)
return
}
<-doneC
Thank you!
go get github.com/adshao/go-binance
..is giving me this error:
git submodule update --init --recursive
fatal: No url found for submodule path 'vendor/github.com/bitly/go-simplejson' in .gitmodules
package github.com/adshao/go-binance: exit status 128
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.