preichenberger / go-coinbasepro Goto Github PK
View Code? Open in Web Editor NEWGo (golang) Client for the Coinbase Pro API https://docs.pro.coinbase.com
License: MIT License
Go (golang) Client for the Coinbase Pro API https://docs.pro.coinbase.com
License: MIT License
According to the GDAX documentation at : https://docs.gdax.com/#signing-a-message a message signature needs to be created using a timestamp, method, requestPath, and body. However, the Sign() method in signing.go appears to only use the timestamp, method, and requestPath.
Interestingly enough, the code that doesn't use the websocket actually appears to use all 4 of the components.
Another interesting tidbit about this is the current signing implementation appears to work just fine on the GDAX sandbox. But, on the real GDAX site, it seems to have issues. When I use it to send a subscription message that includes the user channel, I then get a subscription response that claims I am subscribed to the user channel. However, creating an order doesn't result in any order messages coming in, and an order being matched also doesn't result in any messages on the user channel. Since the sandbox generates user messages for these actions, I suspect that GDAX has a bug in how they are handling the subscription messages. They seem to always tell you that you are subscribed to whatever channels you request. However, if the signature is invalid they just don't appear to send messages. I've sent an e-mail to GDAX support about this, but suspect I won't get an answer from them. :-(
I'll be forking the project to attempt to fix the issue, and will submit a pull request if I get anywhere with it. But, I figured I would open a bug report in case someone else gets to the issue first, or in case someone else is fighting with the user channel not working.
This field is useful when subscribing to the web socket for order updates. It is required for correctness.
See https://docs.pro.coinbase.com/#place-a-new-order for details.
CLIENT ORDER ID
The optional client_oid field must be a UUID generated by your trading application. This field value will be broadcast in the public feed for received messages. You can use this field to identify your orders in the public feed.
The client_oid is different than the server-assigned order id. If you are consuming the public feed and see a received message with your client_oid, you should record the server-assigned order_id as it will be used for future order status updates. The client_oid will NOT be used after the received message is sent.
The server-assigned order id is also returned as the id field to this HTTP POST request.
I would like to report an issue wherein the new prime coinbase api endpoints have not been integrated in the repo yet. Will you be integrating them?
Reference: https://docs.prime.coinbase.com/#introduction
Awaiting your reply, thank you!
Hi,
It looks like with "ListTrades" I can only start with the newest trade and then go to older pages. But is there also a way to start the pagination at an arbitrary point? When I try, I only get an exception
Invalid value for "after"
, which seems to come from GDAX directly.
JSON unmarshal of web socket messages fails on 32-bit systems because Sequence is defined as int in the struct.
Returns "Expected string" error. Fails when trying to parse the time in the array
It'd be nice to have orderbook code here....support for L3 would also be nice.
order, err = client.GetOrder(order.Id)
I'm not sure what is causing it but I get the error:
json: cannot unmarshal array into Go value of type gdax.Order
Any idea what's going on there? Some change to the API?
It would be great to unify configuration for both production and sandbox environments.
It's a little bit confusing and requires additional coding to set/read appropriate environment variables.
For example, in previous versions, the Bids field of the Message is defined as following link:
Bids [][]string `json:"bids,omitempty"`
In the latest version, it is defined as link:
Bids [][]SnapshotEntry `json:"bids,omitempty"`
where SnapshotEntry
is a tuple of 3 values. Essentially it makes Bids field match [][][]string
and it will obviously failed to unmarshal the json message. Is this a bug or I misunderstood the intention?
https://github.com/cockroachdb/apd would be a good candidate
How are sctruct members of type Time accessed in go-coinbase-exchange? Is there some way to treat these as standard golang time.Time structs in the existing implementation? Would that require a unique interface or new set of functions within time.go? I'm a bit confused when it comes to the declaration of type Time in this project's time.go.
For example, when modifying the List Account Ledger example from Readme.md (or the main Github page of the project), I wanted to include some useful information about transaction times in a human-readable format using the following line of code:
fmt.Printf(e.CreatedAt.Format("2006-01-02 15:04:05.999999+00"))
This throws the following compiler error:
e.CreatedAt.Format undefined (type coinbase.Time has no field or method Format)
I can see the struct members wall, ext and loc
by printing e.CreatedAt
(where e
is a ledger range) by replacing the print statement above with the following:
fmt.Printf("%#v", e.CreatedAt)
But I'm not quite sure how to parse the resulting string so that the coinbase.Time variables can be treated as standard golang or UNIX times.
This project could use some development with respect to documenting the functions whose combined prototypes and raw code are kind of "self-documenting" rather than verbose. I would be happy to contribute something in that regard should someone point me in the right direction with the underlying fundamentals of go at play here.
Given the limited number of contributors here, I've also posted the question on StackOverflow in a more abstract way (with respect to computer programming terminology) which addresses the more general case of type wrapping/extension:
https://stackoverflow.com/questions/46181419/type-wrapping-of-non-atomic-types-in-golang
There is now a Headers function defined to authenticate websocket sessions. It would be helpful to add an example to the README file as well. Perhaps, a websocket session example to subscribe to user channel would be useful.
I'm new to GoLang, which may be the problem, but I cannot figure out how to pass start, end and granularity to the GetHistoricRates function.
I've even tried passing a struct of type GetHistoricRatesParams with no success.
Note, I *am able to retrieve a default history by simply passing the Product ID.
In my test application, the orderbook is maintained by subscribing to the L2Update channel. When receiving a snapshot message, it creates a orderbook struct and it handles each l2update message after that. Sometimes I see the price crosses, i.e. best bid is higher than the best ask.
It might be a bug in my code, but I also want to check with users of this library and see if you are having the same issue.
Hi Philip,
Do you know that is tradingview? I'm readingview developer and I'm working in integrating coinbase feed to our feed system and I'm trying to use go-coinbase-exchange project. Unfortunately, it looks to be desolated. For instance, it cannot download products because of json mapping is obsolte and mistatches.
Surely I can clone the repository and develop it locally (this is what I've already started with), however I'd like to make my fixes public and alive, so what do you think about adding me as a developer to the project?
Eugene Korobko
[email protected]
TradingView developer
The go-gdax client doesn't check for error before checking status code...res
can be nil
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x10 pc=0x131a2be]
goroutine 54 [running]:
github.com/preichenberger/go-gdax.(*Client).Request(0xc4203920f0, 0x144c038, 0x3, 0xc4204dd520, 0x17, 0x0, 0x0, 0x13a15c0, 0xc4200cbc80, 0xc4202be000, ...)
/Users/christopherchan/code/gocode/src/github.com/preichenberger/go-gdax/client.go:45 +0x13e
github.com/preichenberger/go-gdax.(*Client).GetStats(0xc4203920f0, 0x144cd15, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
/Users/christopherchan/code/gocode/src/github.com/preichenberger/go-gdax/product.go:223 +0x14b
github.com/chrischris292/trading/features/feature_impls.(*HistoricalDataStore).run(0xc420442000)
/Users/christopherchan/code/gocode/src/github.com/chrischris292/trading/features/feature_impls/historical_data_store.go:38 +0x10a
created by github.com/chrischris292/trading/features/feature_impls.NewHistoricalDataStore
/Users/christopherchan/code/gocode/src/github.com/chrischris292/trading/features/feature_impls/historical_data_store.go:32 +0x17f
exit status 2
I generate a brand new API key in GDAX and run go test and it fails with the following:
account_test.go:12: Invalid API Key
--- FAIL: TestGetAccount (0.17s)
account_test.go:27: Invalid API Key
--- FAIL: TestListAccountLedger (0.16s)
account_test.go:47: Invalid API Key
--- FAIL: TestListHolds (0.19s)
account_test.go:72: Invalid API Key
--- FAIL: TestListFills (0.35s)
fill_test.go:15: Invalid API Key
fill_test.go:30: Invalid API Key
--- FAIL: TestCreateLimitOrders (0.20s)
order_test.go:20: Invalid API Key
order_test.go:24: No create id found
order_test.go:30: Price not equal
--- FAIL: TestCreateMarketOrders (0.15s)
order_test.go:47: Invalid API Key
order_test.go:51: No create id found
order_test.go:57: Size not equal
--- FAIL: TestCancelOrder (0.17s)
order_test.go:67: Invalid API Key
--- FAIL: TestGetOrder (0.32s)
order_test.go:92: Invalid API Key
order_test.go:97: Invalid API Key
--- FAIL: TestListOrders (0.31s)
order_test.go:112: Invalid API Key
order_test.go:125: Invalid API Key
Hello!
Many thanks for your library.
I have several questions regarding library:
Waiting for your answer.
Let me start by saying that I know that this is ultimately an issue with the GDAX/Coinbase API, but I figured I would open a bug here as well in case there is a workaround that could be put in place.
When calling GetTicker() with the symbols :
ETH-BTC
LTC-EUR
BCH-BTC
BTC-GBP
ETC-USD
ETC-EUR
ETC-BTC
They all error out an return the message "Cannot unmarshal number into Go struct field of Ticker.volume". I suspect that for those tickers the volume is geting returned as either an int or a float, but have not had time to dig in to see yet. (To be fair, the docs at https://docs.pro.coinbase.com/#get-product-ticker don't actually SAY that volume will be a string, but it sure seems to imply it!)
I will also attempt to locate a way to submit this information to GDAX/Coinbase to attempt to get them to fix the issue.
Following the example at the bottom of the readme, the trades
never gets updated with the results of the query, and it doesn't appear that the Params
is being used to limit the result set. This ends up meaning the call never completes, and the requested data is not populated in the desired object.
Maybe I am doing something wrong, but when I "go get" the repo, assign environment variables, then run the tests this is what i am getting:
--- FAIL: TestGetAccounts (0.00s)
account_test.go:12: illegal base64 data at input byte 4
--- FAIL: TestGetAccount (0.00s)
account_test.go:27: illegal base64 data at input byte 4
--- FAIL: TestListAccountLedger (0.00s)
account_test.go:47: illegal base64 data at input byte 4
--- FAIL: TestListHolds (0.00s)
account_test.go:72: illegal base64 data at input byte 4
--- FAIL: TestGetCurrencies (0.00s)
currency_test.go:12: illegal base64 data at input byte 4
--- FAIL: TestListFills (0.00s)
fill_test.go:15: illegal base64 data at input byte 4
fill_test.go:30: illegal base64 data at input byte 4
--- FAIL: TestCreateLimitOrders (0.00s)
order_test.go:20: illegal base64 data at input byte 4
order_test.go:24: No create id found
order_test.go:30: Price not equal
--- FAIL: TestCreateMarketOrders (0.00s)
order_test.go:47: illegal base64 data at input byte 4
order_test.go:51: No create id found
order_test.go:57: Size not equal
--- FAIL: TestCancelOrder (0.00s)
order_test.go:67: illegal base64 data at input byte 4
--- FAIL: TestGetOrder (0.00s)
order_test.go:92: illegal base64 data at input byte 4
order_test.go:97: illegal base64 data at input byte 4
--- FAIL: TestListOrders (0.00s)
order_test.go:112: illegal base64 data at input byte 4
order_test.go:125: illegal base64 data at input byte 4
--- FAIL: TestGetProducts (0.00s)
product_test.go:13: illegal base64 data at input byte 4
--- FAIL: TestGetBook (0.00s)
product_test.go:27: illegal base64 data at input byte 4
product_test.go:31: illegal base64 data at input byte 4
product_test.go:35: illegal base64 data at input byte 4
--- FAIL: TestGetTicker (0.00s)
product_test.go:43: illegal base64 data at input byte 4
--- FAIL: TestListTrades (0.00s)
product_test.go:58: illegal base64 data at input byte 4
--- FAIL: TestGetHistoricRates (0.00s)
product_test.go:79: illegal base64 data at input byte 4
--- FAIL: TestGetTime (0.00s)
time_test.go:14: illegal base64 data at input byte 4
FAIL
exit status 1
FAIL github.com/preichenberger/go-coinbase-exchange 0.071s
Note: the ticker
channel on the websocket feed does not return the highest bid and lowest ask.
It would be nice to get the highest bid and lowest ask price from the websocket feed and expose this to the user somehow.
I have some working code to keep in sync with the highest bid. It requires listening to certain messages and maintaining an orderbook with only one level - the top bid. The messages to listen to are snapshot
and l2update
.
Does anyone know of an easier way to always get the highest bid and lowest ask without polling the HTTP endpoint?
Currently, use of this library to CreateOrder()s often fails, because the price must be sent as a float64 to the library (as opposed to a string), and is then converted to a string with too much precision. The GDAX API then rejects these orders with an error message, explaining that the "price [is] too precise."
More generally, the use of float64s is probably not ideal.
Consider the following snippet, which closely resembles the websocket example from the readme:
var wsDialer ws.Dialer
wsConn, _, err := wsDialer.Dial("wss://ws-feed.pro.coinbase.com", nil)
if err != nil {
log.Fatal(err.Error())
}
subscribe := coinbasepro.Message{
Type: "subscribe",
Channels: []coinbasepro.MessageChannel{
coinbasepro.MessageChannel{
Name: "heartbeat",
ProductIds: []string{
"BTC-USD",
},
},
coinbasepro.MessageChannel{
Name: "matches",
ProductIds: []string{
"BTC-USD",
},
},
},
}
if err := wsConn.WriteJSON(subscribe); err != nil {
log.Fatal(err.Error())
}
for true {
message := coinbasepro.Message{}
if err := wsConn.ReadJSON(&message); err != nil {
log.Fatal(err.Error())
break
}
log.Printf(
"Type: %s, Product: %s, Amount: %s, Trade ID: %d, Last Trade ID: %d",
message.Type,
message.ProductID,
message.Price,
message.TradeID,
message.LastTradeID,
)
}
Note that I am subscribed to the BTC-USD
heartbeat
and matches
channels. I would expect that every time a new match occurs, the next heartbeat would hold the said match's trade identifier. However, I am seeing output like the following:
▶ go run .
2020/05/05 08:17:07 Type: subscriptions, Product: , Amount: , Trade ID: 0, Last Trade ID: 0
2020/05/05 08:17:07 Type: last_match, Product: BTC-USD, Amount: 8874.68, Trade ID: 90477204, Last Trade ID: 0
2020/05/05 08:17:07 Type: match, Product: BTC-USD, Amount: 8876.6, Trade ID: 90477205, Last Trade ID: 0
2020/05/05 08:17:07 Type: match, Product: BTC-USD, Amount: 8876.97, Trade ID: 90477206, Last Trade ID: 0
2020/05/05 08:17:07 Type: match, Product: BTC-USD, Amount: 8877.2, Trade ID: 90477207, Last Trade ID: 0
2020/05/05 08:17:07 Type: heartbeat, Product: BTC-USD, Amount: , Trade ID: 0, Last Trade ID: 0
2020/05/05 08:17:08 Type: match, Product: BTC-USD, Amount: 8875.71, Trade ID: 90477208, Last Trade ID: 0
2020/05/05 08:17:08 Type: match, Product: BTC-USD, Amount: 8875.62, Trade ID: 90477209, Last Trade ID: 0
2020/05/05 08:17:08 Type: match, Product: BTC-USD, Amount: 8877.2, Trade ID: 90477210, Last Trade ID: 0
2020/05/05 08:17:08 Type: heartbeat, Product: BTC-USD, Amount: , Trade ID: 0, Last Trade ID: 0
2020/05/05 08:17:09 Type: match, Product: BTC-USD, Amount: 8877.2, Trade ID: 90477211, Last Trade ID: 0
2020/05/05 08:17:09 Type: heartbeat, Product: BTC-USD, Amount: , Trade ID: 0, Last Trade ID: 0
2020/05/05 08:17:10 Type: heartbeat, Product: BTC-USD, Amount: , Trade ID: 0, Last Trade ID: 0
2020/05/05 08:17:11 Type: heartbeat, Product: BTC-USD, Amount: , Trade ID: 0, Last Trade ID: 0
2020/05/05 08:17:12 Type: heartbeat, Product: BTC-USD, Amount: , Trade ID: 0, Last Trade ID: 0
2020/05/05 08:17:13 Type: match, Product: BTC-USD, Amount: 8877.17, Trade ID: 90477212, Last Trade ID: 0
2020/05/05 08:17:13 Type: match, Product: BTC-USD, Amount: 8877.17, Trade ID: 90477213, Last Trade ID: 0
2020/05/05 08:17:13 Type: heartbeat, Product: BTC-USD, Amount: , Trade ID: 0, Last Trade ID: 0
2020/05/05 08:17:14 Type: heartbeat, Product: BTC-USD, Amount: , Trade ID: 0, Last Trade ID: 0
2020/05/05 08:17:15 Type: match, Product: BTC-USD, Amount: 8878.59, Trade ID: 90477214, Last Trade ID: 0
2020/05/05 08:17:15 Type: match, Product: BTC-USD, Amount: 8878.67, Trade ID: 90477215, Last Trade ID: 0
2020/05/05 08:17:15 Type: match, Product: BTC-USD, Amount: 8879.29, Trade ID: 90477216, Last Trade ID: 0
2020/05/05 08:17:15 Type: heartbeat, Product: BTC-USD, Amount: , Trade ID: 0, Last Trade ID: 0
2020/05/05 08:17:17 Type: heartbeat, Product: BTC-USD, Amount: , Trade ID: 0, Last Trade ID: 0
2020/05/05 08:17:17 Type: match, Product: BTC-USD, Amount: 8877.53, Trade ID: 90477217, Last Trade ID: 0
2020/05/05 08:17:17 Type: match, Product: BTC-USD, Amount: 8877.52, Trade ID: 90477218, Last Trade ID: 0
2020/05/05 08:17:17 Type: heartbeat, Product: BTC-USD, Amount: , Trade ID: 0, Last Trade ID: 0
2020/05/05 08:17:17 Type: match, Product: BTC-USD, Amount: 8877.52, Trade ID: 90477219, Last Trade ID: 0
2020/05/05 08:17:17 Type: match, Product: BTC-USD, Amount: 8877.49, Trade ID: 90477220, Last Trade ID: 0
2020/05/05 08:17:18 Type: match, Product: BTC-USD, Amount: 8879, Trade ID: 90477221, Last Trade ID: 0
2020/05/05 08:17:18 Type: heartbeat, Product: BTC-USD, Amount: , Trade ID: 0, Last Trade ID: 0
2020/05/05 08:17:19 Type: match, Product: BTC-USD, Amount: 8879, Trade ID: 90477222, Last Trade ID: 0
2020/05/05 08:17:19 Type: heartbeat, Product: BTC-USD, Amount: , Trade ID: 0, Last Trade ID: 0
2020/05/05 08:17:20 Type: heartbeat, Product: BTC-USD, Amount: , Trade ID: 0, Last Trade ID: 0
Notice that the LastTradeID
field of the heartbeat messages is always 0
. Is my understanding of the semantics of the heartbeat message wrong? Or am I possibly using it wrong? Or could this be a real bug – with either this library or with the Coinbase Pro API?
Hey @preichenberger,
you have to send the subscribe message each < 5 seconds to avoid a disconnection to the websocket.
To begin receiving feed messages, you must first send a subscribe message to the server indicating which channels and products to receive. This message is mandatory — you will be disconnected if no subscribe has been received within 5 seconds.
I think we should update the example https://github.com/preichenberger/go-gdax#websockets
I am having trouble using the library. Specifically when testing I keep getting the Invalid API Key or some related error depending on exactly how the tests are run. Can you assist?
env | grep COINBASE
TEST_COINBASE_OFFSET=+5
TEST_COINBASE_PASSPHRASE=5...e
TEST_COINBASE_SECRET=V...==
TEST_COINBASE_KEY=f...2
ivan@lenii:~/workspace-go/src/go-coinbase-exchange$ go test
--- FAIL: TestGetAccounts (0.37s)
account_test.go:12: Invalid API Key
--- FAIL: TestGetAccount (0.24s)
account_test.go:27: Invalid API Key
--- FAIL: TestListAccountLedger (0.24s)
account_test.go:47: Invalid API Key
--- FAIL: TestListHolds (0.24s)
account_test.go:72: Invalid API Key
--- FAIL: TestListFills (0.48s)
fill_test.go:15: Invalid API Key
fill_test.go:30: Invalid API Key
--- FAIL: TestCreateLimitOrders (0.24s)
order_test.go:20: Invalid API Key
order_test.go:24: No create id found
order_test.go:30: Price not equal
--- FAIL: TestCreateMarketOrders (0.24s)
order_test.go:47: Invalid API Key
order_test.go:51: No create id found
order_test.go:57: Size not equal
--- FAIL: TestCancelOrder (0.24s)
order_test.go:67: Invalid API Key
--- FAIL: TestGetOrder (0.55s)
order_test.go:92: Invalid API Key
order_test.go:97: Invalid API Key
--- FAIL: TestListOrders (0.50s)
order_test.go:112: Invalid API Key
order_test.go:125: Invalid API Key
FAIL
exit status 1
FAIL go-coinbase-exchange 6.774s
If I run an individual test I get an error like this one:
account_test.go:12: CB-ACCESS-KEY header is required
I started my own main and this seems to work but the testing is still a mystery to me.
Any plans to create and maintain an orderbook from snapshot and then level2 updates?
The Order struct should include the stop
and stop_price
fields so that stop-loss orders can be submitted.
The Stats Response return last & volume_30days. Would be nice if they are contained in the API
I opened a Pullrequest: #44
According to the documentation,
Historical rate data may be incomplete. No data is published for intervals where there are no ticks.
When I call GetHistoricRate() on a 5 minute interval, I expect 72 candles over a 6hr period (6hr * 60m = 360m / 5m = 72 intervals)
But because of the above notation, there are "holes" in the returned data. How do you handle these holes? Do you just copy the previous interval or assign all 0's to HLOC?
Would be great to see a type that could implement what's described https://docs.gdax.com/#the-code-classprettyprintfullcode-channel.
I might work on this when I get some time.
Current release, v2.0.5, has a lot of missing fields in structs, Product struct for example. I was fixing it when I've seen its already fixed on master.
Can you please tag a new release? Thanks in advance.
GDAX is being deprecated and replaced with coinbase pro. The API endpoints will need to be updated.
Hello!
Is there any work already being done to update this to the new Advanced Trade API, now that Coinbase Pro is being deprecated?
According to the Readme, it says the build is failing.
Is this software stable to use?
I'm not sure if I'm missing something but I can't make websocket work for level2. The returned structure is different than the Message one and I can't find the right one in the project. Any help would be appreciated.
Coinbase Pro advises using authenticated websockets for some extra detail in the feed.
The main doc has an example of opening an unathenticated websocket. Is there a facility
to open an authenticated one, using API Key, API Secret and API Phassphrase?
Thanks.
See this Stack Overflow answer for why not. Since all go-gdax should be doing is immediately serializing to JSON, this might not be readily noticeable but it looks like #37 may be a symptom. I'm also concerned that the use of float64
s encourages developers unfamiliar with the issues around float precision to make really horrible mistakes in their software.
In #18, decimals were proposed however, that brought up the issue of there being multiple packages implementing them in various forms. Looking into the docs, GDAX uses strings for API interactions:
Decimal numbers are returned as strings to preserve full precision across platforms. When making a request, it is recommended that you also convert your numbers to strings to avoid truncation and precision errors.
Perhaps we should follow suit and switch to strings? That would leave it to users of go-gdax to bring their own decimal library. Thoughts? @preichenberger
Hello
Philip, I received the error in the subject when I run the following code.
I found if I removed the following code in message.go it works fine.
Do you know why?
-----your source code -----------
func (e *SnapshotChange) UnmarshalJSON(data []byte) error {
var entry []string
if err := json.Unmarshal(data, &entry); err != nil {
return err
}
e.Side = entry[0]
e.Price = entry[1]
e.Size = entry[2]
return nil
}
----------my testing code -------
package main
import (
"fmt"
"log"
"encoding/json"
coinbasepro "github.com/preichenberger/go-coinbasepro"
)
func check(e error) {
if e != nil {
log.Fatal(e)
}
}
func main(){
//the messageJson is captured from the coinbase pro ws feed.
messageJson := { "type": "l2update", "product_id": "ETH-USD", "product_ids": null, "trade_id": 0, "order_id": "", "client_oid": "", "sequence": 0, "maker_order_id": "", "taker_order_id": "", "time": "2019-04-26T20:34:02.674Z", "remaining_size": "", "new_size": "", "old_size": "", "size": "", "price": "", "side": "", "reason": "", "order_type": "", "funds": "", "new_funds": "", "old_funds": "", "message": "", "changes": [ { "Side": "sell", "Price": "151.44000000", "Size": "0.11" } ], "last_size": "", "best_bid": "", "best_ask": "", "channels": null, "user_id": "", "profile_id": "", "last_trade_id": 0 }
message := coinbasepro.Message {}
err := json.Unmarshal([]byte(messageJson), &message)
check(err)
fmt.Println(message)
}
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.