Code Monkey home page Code Monkey logo

node-binance-api's People

Contributors

afsharsafavi avatar bkrypt avatar bmino avatar boyhagemann avatar charlesdarkwind avatar davewang avatar dbvcode avatar dependabot[bot] avatar dmitriz avatar dmzoneill avatar ejfrancis avatar eluvade avatar gemmell avatar gmalca avatar gunar avatar gusgold avatar itnok avatar jaggedsoft avatar joaquinnunez avatar kirosc avatar lht147 avatar maddeveloper avatar maxah avatar meetmangukiya avatar nimanr avatar robaleman avatar sethyx avatar taboca avatar waterdrop01 avatar wostafa avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

node-binance-api's Issues

Issue with marketBuy method

I'm attempting to use the marketBuy method but get a response of "{ code: -1013, msg: 'Invalid price.' }". I am not passing in a price as it is a marketBuy. Code looks like:

binance.marketBuy("ADAETH", 50, function(response) {
console.log(response)
})

Version on NPM is outdated

I spent 2 hours scratching my head trying to figure out why my options for the candlesticks endpoint wasn't working. And then I dug deeper into the code and realized that the README reflected a version of the package that hasn't been published yet.

binance.depth error

When i call binance.depth i sometime get an error:
Uncaught TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined

how can i handle such situation and check the cause of error?

Example call:

  binance.depth("REQETH", function(depth) {
  	console.log("market depth", depth);
  });

Stop Loss Order Not Working

When calling stop loss order, I use the following code to test stop loss order:

binance.sell(exchangePair, quantity, price, { stopPrice: price }, function (response) {...}

I got the following error:
{ code: -1106,
msg: 'Parameter 'stopPrice' sent when not required.' }

messageQueue[symbol] undefined

Parse error: Cannot read property 'push' of undefined

depthCache: function depthCacheFunction(symbols, callback, limit = 500) {
				if ( typeof symbols === 'string' ) symbols = [symbols]; // accept both strings and arrays
				for ( let symbol of symbols ) {
					if ( typeof info[symbol] === 'undefined' ) info[symbol] = {};
					info[symbol].firstUpdateId = 0;
					depthCache[symbol] = {bids: {}, asks: {}};
					messageQueue[symbol] = [];
					let reconnect = function() {
						if ( options.reconnect ) depthCacheFunction([symbol], callback);
					};
					subscribe(symbol.toLowerCase()+'@depth', function(depth) {
						if ( !info[symbol].firstUpdateId ) {
							console.log(messageQueue[symbol])  **// UNDEFINED**
							messageQueue[symbol].push(depth);  // BUG IS HERE
							return;
						}

CORS issue

I am getting:
Failed to load https://api.binance.com/api/v1/ticker/allPrices: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8100' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

When trying to use the API withing angular2 service.

this.binance.binance.prices(function(ticker){
console.log("prices()", ticker);
console.log("Price of BNB: ", ticker.BNBBTC);
});

Please suggest. Thanks

Binance is down

Tried stream over webscoket, keys are provided using this

binance.websockets.trades(['BNBBTC', 'ETHBTC'], function(trades) {
let {e:eventType, E:eventTime, s:symbol, p:price, q:quantity, m:maker, a:tradeId} = trades;
console.log(symbol+" trade update. price: "+price+", quantity: "+quantity+", maker: "+maker);
});

no output

tried getting an http call done

binance.trades("SNMBTC", function(trades, symbol) {
console.log(symbol+" trade history", trades);
});

output was

SNMBTC trade history { code: -1021,
msg: 'Timestamp for this request was 1000ms ahead of the server's time.' }

great lib

LOT_SIZE error

All of my limit and market orders are giving this response:
{ code: -1013, msg: 'Filter failure: LOT_SIZE' }

I am making calls with ticker, quantity and price (If applicable.) I have made successful market information requests, but cannot execute orders.

Thanks,
-Izaac

RSV2 and RSV3 must be clear

I'm streaming data from the websocket, but always get this error after 4-5 minutes of running it:
This is the ws method I'm using:

    binance.websockets.prevDay(false, function(response) {
    });
Parse error: Unexpected token ║ in JSON at position 51198
error: uncaughtException: RSV2 and RSV3 must be clear
    at Receiver.getInfo (\node_modules\ws\lib\Receiver.js:184:18)
    at Receiver.startLoop (\node_modules\ws\lib\Receiver.js:153:16)
    at Receiver.add (\node_modules\ws\lib\Receiver.js:139:10)
    at TLSSocket._ultron.on (\node_modules\ws\lib\WebSocket.js:138:22)
    at emitOne (events.js:116:13)
    at TLSSocket.emit (events.js:211:7)
    at addChunk (_stream_readable.js:263:12)
    at readableAddChunk (_stream_readable.js:250:11)
    at TLSSocket.Readable.push (_stream_readable.js:208:10)
    at TLSWrap.onread (net.js:594:20)

Any idea what might be causing it?

Error when attempting a Stop Loss Limit order

Attempted Code:

let type = "STOP_LOSS_LIMIT";
let quantity = round(lastETH,5);
let price = round(buyPrice * (1.0 - sLimit),2) - 0.01; // 1310.99
let stopPrice = round(buyPrice * (1.0 - sLimit),2);  //1311
binance.sell("ETHUSDT", quantity, price, {stopPrice: stopPrice, type: type});

Console Result:
SELL(ETHUSDT,4.77109,1310.99) { code: -1102, msg: 'Mandatory parameter \'timeInForce\' was not sent, was empty/null, or malformed.' }

callback not callbac

depthCache: function depthCacheFunction(symbols, callbac, limit = 100)

depthCache: function depthCacheFunction(symbols, callback, limit = 100)

calling balance generates this error

binance.balance(function(balances) {
});

node-binance-api/node-binance-api.js:220
for ( let obj of data.balances ) {
^

TypeError: data.balances is not iterable
at balanceData (node-binance-api/node-binance-api.js:220:25)

market orders aren't working

Hi, the example code to place a market order doesn't work—I'm not sure why, but it seems to be sending price information, which the api isn't expecting. Limit orders work fine.

Here's the error code I receive:

BUY(BNBBTC,1,0) { code: -1104,
msg: 'Not all sent parameters were not read; read '9' parameter(s) but was sent '10'.' }

0.4.0: TypeError: Cannot read property 'msg' of null

Version 0.4.0

L.146

node_modules\node-binance-api\node-binance-api.js:146
                        if ( typeof response.msg !== 'undefined' && response.msg === 'Filter failure: MIN_NOTIONAL' ) {
                                             ^

TypeError: Cannot read property 'msg' of null
    at node_modules\node-binance-api\node-binance-api.js:146:25
    at Request._callback (S:\Projects\prophet\node_modules\node-binance-api\node-binance-api.js:111:12)
    at Request.self.callback (S:\Projects\prophet\node_modules\request\request.js:186:22)
    at emitTwo (events.js:126:13)
    at Request.emit (events.js:214:7)
    at Request.<anonymous> (S:\Projects\prophet\node_modules\request\request.js:1163:10)
    at emitOne (events.js:116:13)
    at Request.emit (events.js:211:7)
    at IncomingMessage.<anonymous> (S:\Projects\prophet\node_modules\request\request.js:1085:12)
    at Object.onceWrapper (events.js:313:30)

I believe the problem is at L.108
https://github.com/jaggedsoft/node-binance-api/blob/master/node-binance-api.js#L108

you're sending null as response, L.149 probably needs to implement the new pattern of (error, response) instead of (response)

Document the entire websocket data objects

Hey, I'm currently trying to handle the outboundAccountInfo and executionReport websocket responses and I'm finding it impossible to figure out some of the fields.

Any chance you could detail what each of the properties in these objects are?

Thanks.

Additional options for fetching trades

Sorry to bug again.

The trades method doesn't allow any parameters. Would something like this make sense:

trades: function(symbol, callback, options) {
	signedRequest(base+"v3/myTrades", {symbol:symbol, ...options}, function(data) {
		if ( callback ) return callback.call(this, data, symbol);
	});
},

TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined

HI,

I have tried to figure out why this happens but for some reason everything I try doesn't work. This error does not always occur but a lot of the time does.

Any help would be appreciated!

/home/sites/pndbot.com/public/v1/node_modules/node-binance-api/node-binance-api.js:220
	for ( let obj of data.balances ) {
		                   ^

TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined
    at balanceData (/home/sites/pndbot.com/public/v1/node_modules/node-binance-api/node-binance-api.js:220:22)
    at /home/sites/pndbot.com/public/v1/node_modules/node-binance-api/node-binance-api.js:485:30
    at Request._callback (/home/sites/pndbot.com/public/v1/node_modules/node-binance-api/node-binance-api.js:85:20)
    at Request.self.callback (/home/sites/pndbot.com/public/v1/node_modules/request/request.js:186:22)
    at emitTwo (events.js:106:13)
    at Request.emit (events.js:191:7)
    at Request.<anonymous> (/home/sites/pndbot.com/public/v1/node_modules/request/request.js:1163:10)
    at emitOne (events.js:96:13)
    at Request.emit (events.js:188:7)
    at IncomingMessage.<anonymous> (/home/sites/pndbot.com/public/v1/node_modules/request/request.js:1085:12)

Better way to get the current price / volume for each coin?

I want to be able to get the current price & volume for each coin, once per minute. I'm using the binance.prices(function(ticker) { to get back the current prices. I can then feed that into something like binance.websockets.candlesticks(['IOTABTC'], "1d", function(candlesticks) {, and I'll get back all of the information I need (note that I pass all of the BTC/ETH pairs into that websocket). I then terminate the websocket once I have the information.

It would be better if there was a non-websocket API to get the price/volume, but I don't see it. Because right now, it takes forever to wait for the websocket to get back all the information for each coin , when you pass in 100+ coins into it.

CORS issue on request

Helloes,
I'm getting CORS errors on all my calls:

Failed to load https://api.binance.com/api/v1/ticker/allPrices: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Is there a spesific option I'm missing while initiating?

Detect a server side disconnect and handle it

Hi,

Is there a way I can detect if the Binance socket goes down and call a function if so? I see there is the reconnect:true optional flag, but I would like to know that it went down before the reconnect is attempted (and whether the reconnect worked).
can I do anything like:

binance.websockets.on("disconnected"...)

or something?

Issue when getting restful depth (order book)

Hi, Running the example works fine for everything except:

binance.depth("SNMBTC", function(json) {
 console.log("market depth",json);
});

which throws:

/[PROJECT]/node_modules/node-binance-api/node-binance-api.js:265
		for ( obj of data.bids ) {
		                 ^

TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined

any idea why?

Thanks

Websocket Reconnection/Heartbeat

I can't see anything in the implementation for heartbeat checks (although this could be done by someone using the library).

Also, is there any chance we could get automatic re-connections to the socket if the network connection drops?

quick syntax error

node-binance-api.js:431
marketSell: function(symbol, quantity, flags = {type: 'MARKET'} callback = false) {
^^^^^^^^

the comma is missing

SyntaxError: Unexpected identifier

marketSell: function(symbol, quantity, flags = {type: 'MARKET'}, callback = false) {
order('SELL', symbol, quantity, 0, flags, callback);
},

disconnect websockets

once you use binance.websockets.prevDay websockets or any websockets, is it possible to disconnect if you no longer need it?

thanks

weird issue with depth

binance.websockets.depthCache([pair], (symbol, depth) => {
		if (typeof depth === 'object') {
			console.log(depth)
		}
		else {
			console.log(symbol + " --> ERROR <-- ")
		}
	});

I sometimes get this error:

for ( obj of data.bids ) {
                                  ^
TypeError: data.bids is not iterable
at depthData (C:\Users\herve\xxx\node_modules\node-binance-api\node-binance-api.js:265:21)
...

Timestamp for this request is not valid for openOrders

Hit the following error when trying to pull open Orders:

openOrders() { code: -1021, msg: 'Timestamp for this request is not valid.' }

I guess that the server side tried to compare the data.timestamp with server's time and rejected all the requests with all obsolete timestamps (time bypassed too long).

The problem here is that this API is trying to pass the client's local time. Need to consider the scenario where the client and the server are in different time zones.

Error: ETIMEDOUT

I am getting those errors lately any idea why?

/app/node-binance-api.js:42
2018-01-10T18:12:43.896798+00:00 app[web.1]: 			if ( !response || !body ) throw 'publicRequest error: '+error;
2018-01-10T18:12:43.896799+00:00 app[web.1]: 			                          ^
2018-01-10T18:12:43.896825+00:00 app[web.1]: publicRequest error: Error: ETIMEDOUT

Need a callback function for the buy API

I think it will be better we have sort of callback function to save the order IDs for the BUY API.

There is no way to get the order ID for the BUY API. It is a bit scary that we have no way to know whether the BUY action succeeded or not.

Converting depth object to array gives garbled orders

I'm using the latest version of the library.

If I am tracking a symbol, doesn't matter which, sometimes the depth cache gives orders that look like this:

0.000001, 100000

Orders that couldn't possibly be the highest bid or lowest ask.

I am using this structure to convert the depth cache object into an array

let bids = Object.entries(binance.sortBids(depth.bids)).sort((a, b) => a - b)
let asks = Object.entries(binance.sortAsks(depth.asks)).sort((a, b) => b - a)

How do I check response codes?

Hi,

Nice library. Just wondering how I go about checking API response codes? Binance's API rules specify that hitting them after they throttle use could result in permanent blocking, so I'd like to check response codes when an error occurs.

Cheers,

Depth cache doesn't update increases in price properly

I've been noticing some weird errors in my programs, and after lots of testing I've found that the depthCache does not update pricing reliably. If the price increases on the bids (I assume this affects the asks as well) it will not update.

e.g.,

You run this program and the price is 0.00063, then the price drops to 0.00062. It will show that. If someone now puts a bid for 0.000625 making that the highest bid, it will not show that as the highest bid and will instead spit out 0.00062 still.

Even this minimal example fails to update the changes on the orderbook that is being tracked.

I am running the latest version of the library.

const Binance = require('node-binance-api')

Binance.websockets.depthCache(['BNBBTC'], (market, depth) => {
  console.log(Binance.array(depth.bids)[0][0])
})

info on candles

I tried everywhere but can't seem to find what this means on the candle. can someone help me?

what do these represent in a candle:

assetVolume, trades, buyBaseVolume, buyAssetVolume, ignored

thanks

Problems with Depth Cache

I've been running Depth Cache for a while now. And the code broke two times, these are the errors:

 node-binance-api.js:280
 
                 for ( obj of depth.b ) { //bids
                                    ^
 TypeError: depth.b is not iterable
node-binance-api.js:603
                 for ( let depth of messageQueue[symbol] ) {
                                                ^

TypeError: messageQueue[symbol] is not iterable

I think Depth Cache has some issues at the moment. Or is it my fault? This is the code I'm using

binance.websockets.depthCache(socketArray, function(symbol, depth) {
	let bids = binance.sortBids(depth.bids);
	let asks = binance.sortAsks(depth.asks);
	let bid = binance.first(bids);
	let ask = binance.first(asks);
	prices[symbol] = prices[symbol] || {}
	prices[symbol].ask = parseFloat(bid),
	prices[symbol].bid = parseFloat(ask)
});

Documentation cleanup

  1. Is the default cb console.log because when calling binance.buy from the console without a callback it seems to log things (or is it sync which seems unlikely)

var quantity = 5, price = 0.00402030;
binance.buy("BNBETH", quantity, price, {}, function(response) {
	console.log("Limit Buy response", response);
	console.log("order id: " + response.orderId);
});

What is that {}? We jump straight from 3 to 5 parameters without specifying that.

// When the stop is reached, a stop order becomes a market order
let quantity = 1;
let price = 0.069;
let stopPrice = 0.068;
binance.sell("ETHBTC", quantity, price, {stopPrice: stopPrice});

Does it become a market order or does it sell at the price specified? If it does sell at the price specified, how can I make it a market order? Leave null for the price?

Get market depth for a symbol

binance.depth("BNBBTC", function(depth, symbol) {
	console.log(symbol+" market depth", depth);
});

The response shown is actually console.log("mark depth "+symbol, depth);. I know, a bit picky, but consistency is important for someone who doesn't know the library.

depthData error for new listed pair

Trying to run:

binance.websockets.depthCache([data.symbols[i].symbol], (symbol, depth) => {
				lasttimestamp = Date.now()
				let bids = binance.sortBids(depth.bids, max);
				let asks = binance.sortAsks(depth.asks, max);

For APPCBTC and I get this error:

APPCBTC
2018-01-06T21:34:10.102657+00:00 app[web.1]: /app/node_modules/node-binance-api/node-binance-api.js:265
2018-01-06T21:34:10.102667+00:00 app[web.1]: 		for ( obj of data.bids ) {
2018-01-06T21:34:10.102668+00:00 app[web.1]: 		                  ^
2018-01-06T21:34:10.102670+00:00 app[web.1]: 
2018-01-06T21:34:10.102671+00:00 app[web.1]: TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined
2018-01-06T21:34:10.102673+00:00 app[web.1]:     at depthData (/app/node_modules/node-binance-api/node-binance-api.js:265:21)
2018-01-06T21:34:10.102674+00:00 app[web.1]:     at /app/node_modules/node-binance-api/node-binance-api.js:598:28
2018-01-06T21:34:10.102675+00:00 app[web.1]:     at Request._callback (/app/node_modules/node-binance-api/node-binance-api.js:41:20)
2018-01-06T21:34:10.102676+00:00 app[web.1]:     at Request.self.callback (/app/node_modules/request/request.js:186:22)
2018-01-06T21:34:10.102677+00:00 app[web.1]:     at emitTwo (events.js:126:13)
2018-01-06T21:34:10.102678+00:00 app[web.1]:     at Request.emit (events.js:214:7)
2018-01-06T21:34:10.102679+00:00 app[web.1]:     at Request.<anonymous> (/app/node_modules/request/request.js:1163:10)
2018-01-06T21:34:10.102680+00:00 app[web.1]:     at emitOne (events.js:116:13)
2018-01-06T21:34:10.102681+00:00 app[web.1]:     at Request.emit (events.js:211:7)
2018-01-06T21:34:10.102682+00:00 app[web.1]:     at IncomingMessage.<anonymous> (/app/node_modules/request/request.js:1085:12)

data.balances is not iterable

I am trying to return my account balances using the provided code:

binance.balance(function(balances) {
console.log("balances()", balances);
});

I am getting the below error:

TypeError: data.balances is not iterable

depthCache limit question

the following code:

binance.websockets.depthCache([pair], (symbol, depth) => {
			var bids = binance.sortBids(depth.bids)
			var asks = binance.sortAsks(depth.asks)
console.log(symbol + " " + _.values(asks).length + " / " + _.values(bids).length )
		}, 10);

produces

ETHBTC 63 / 61
NEOBTC 45 / 66
WTCBTC 41 / 59
LTCBTC 53 / 57
BCCBTC 32 / 31
MCOBTC 27 / 18

the size of bids and asks keeps increasing over time. is it intended? should bids and asks size auto resized to the input limit?

unable to run any method

I'm just trying to get this up and running, but done of the example works.

i get the following:


const publicRequest = function(url, data, callback, method = "GET") {
	                                                           ^

SyntaxError: Unexpected token =
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:387:25)
    at Object.Module._extensions..js (module.js:422:10)
    at Module.load (module.js:357:32)
    at Function.Module._load (module.js:314:12)
    at Module.require (module.js:367:17)
    at require (internal/module.js:16:19)
    at Object.<anonymous> (/Users/chungtinhlakho/Desktop/thaison/ct/app.js:4:17)
    at Module._compile (module.js:413:34)
    at Object.Module._extensions..js (module.js:422:10)

Depth cache out of sync

Depth cache occasionally goes out of sync. This started happening today (1/5/2018). Binance did some upgrades last night and it seems that websocket is no longer reliable.

Any clues what is happening?

I just wanted to report the problem. Feel free to close the issue if you feel it's not related to the library.

throwing whenever the statusCode != 200 causes issues

There is no way (AFAIK) to embed your API in Promises, when you simply throw the response on L.89.

try catch, or Promise rejection won't get it, and it will just throw and fail.

Recommend you remove L.89 or use Promises instead of a callback.

if ( response && response.statusCode !== 200 ) throw response;

Syntax Error in NPM version of the API

/Users/slavko/Desktop/Code/NodeJS/CryptoHub/node_modules/node-binance-api/node-binance-api.js:431
		marketSell: function(symbol, quantity, flags = {type: 'MARKET'} callback = false) {
		                                                                ^^^^^^^^

SyntaxError: Unexpected identifier
    at createScript (vm.js:74:10)
    at Object.runInThisContext (vm.js:116:10)
    at Module._compile (module.js:537:28)
    at Object.Module._extensions..js (module.js:584:10)
    at Module.load (module.js:507:32)
    at tryModuleLoad (module.js:470:12)
    at Function.Module._load (module.js:462:3)
    at Module.require (module.js:517:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/Users/slavko/Desktop/Code/NodeJS/CryptoHub/routes/index.js:2:15)

In the NPM version on line 431 there's a missing comma, which seems to be present in the most recent GitHub commit but isn't present in the latest NPM version.

Just letting ya know :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.