bitcoinjs / bip32 Goto Github PK
View Code? Open in Web Editor NEWA BIP32 compatible library.
License: MIT License
A BIP32 compatible library.
License: MIT License
Hi there,
I have been going through the code and I came across the fromSeed()
function, which I assume is the one that generates the wallet master keys from the given seed, but it doesn't seem to be taking a user defined optional passphrase nor does it prefix it with mnemonic
as defined in the BIP39 standard.
Am I getting something wrong or is this an intended behaviour? If so, are there any security related reasons for ditching the standard? And if not could this function be changed to comply with the standard?
Hi there,
I was wondering how I could extract the Extended public & private keys (zPub & zPrv) from the HD Root, does this package come with such a method?
This is my code for reference:
const addressGenerator = async (passphrase = "") => {
// Generate a random mnemonic (uses crypto.randomBytes under the hood), defaults to 128-bits of entropy
const mnemonic = bip39.generateMnemonic(256);
console.log(mnemonic);
// Generate a root seed from the mnemonic and the passphrase
const seed = bip39.mnemonicToSeedSync(mnemonic, passphrase);
// Generate a master wallet key from the root seed
const hdRoot = bip32.fromSeed(seed);
// Path of child node (84' is SegWit v0 path)
const path = "m/84'/0'/0'/0/0"; // 1st key of the receiving addresses (external addresses) of the 1st account
// Derive the child node from the path
const childNode = hdRoot.derivePath(path);
// Extract the child node public key
const pubkey = childNode.publicKey;
// Encode the public key with Bech32 standard to derive P2WPKH the address
const { address } = bitcoin.payments.p2wpkh({ pubkey, network: TESTNET });
console.log(address);
};
Hello:
I want to port some old code to new code. I am trying to create some QTUM wallet, which has the derivePath of "m/88'/0'/0'".
The Wallet definition for QTUM looks like this:
export class Wallet {
public address: string
private insight: Insight
constructor(public keyPair: bip32.BIP32Interface,
public network: INetworkInfo)
{
this.address = this.keyPair.toBase58();
this.insight = Insight.forNetwork(this.network)
}
I want to use the following TS code:
import * as ecc from 'tiny-secp256k1';
import { BIP32Factory } from 'bip32';
export class Network {
constructor(public info: INetworkInfo) {}
/**
*/
public fromMnemonic(mnemonic: string, password?: string): Wallet {
const hdNode = ethers.HDNodeWallet.fromMnemonic(mnemonic, password);
const accountNode = hdNode.derivePath("m/88'/0'/0'");
const privateKey = accountNode.privateKey;
const bip32 = BIP32Factory(ecc);
const chainCode = accountNode.chainCode;
const node = bip32.fromPrivateKey(Buffer.from(privateKey), Buffer.from(chainCode));
const keyPair = KeyPair.fromPrivateKey(Buffer.from(privateKey));
return new Wallet(keyPair, this.info);
}
But the keyPair is not correct. I think keyPair is only one data type for private_key and public_key, right?
However, I don’t know how to get a public key from the private key.
Please let me know how can I make the code to work?
PS: I am using Node.js version 20.2 on Windows 10 (22H2)
Thanks,
version: electron^4.0.6
const crypto = require('crypto')
console.log(crypto.getHashes())
// ["md4", "md5", "ripemd160", "sha1", "sha224", "sha256", "sha384", "sha512"]
use bip32@^2.0.6, Compile error
Uncaught ReferenceError: Buffer is not defined
at Object../node_modules/tiny-secp256k1/rfc6979.js (rfc6979.js:3:1)
at Object.options.factory (react refresh:6:1)
at __webpack_require__ (bootstrap:24:1)
at fn (hot module replacement:62:1)
at Object../node_modules/tiny-secp256k1/js.js (js.js:4:1)
at Object.options.factory (react refresh:6:1)
at __webpack_require__ (bootstrap:24:1)
at fn (hot module replacement:62:1)
at Object../node_modules/bip32/src/bip32.js (bip32.js:5:1)
at Object.options.factory (react refresh:6:1)
import { networks, initEccLib, payments } from 'bitcoinjs-lib';
import * as bip39 from 'bip39';
import * as BIP32Factory from 'bip32';
import ecc from '@bitcoinerlab/secp256k1';
initEccLib(ecc);
const bip32 = BIP32Factory.default(ecc);
const network = networks.bitcoin;
mnemonic = bip39.generateMnemonic();
const seedBuffer = bip39.mnemonicToSeedSync(mnemonic);
const derivationPath = `m/48'/0'/0'/0`;
const root = bip32.fromSeed(seedBuffer, network);
const child = root.derivePath(derivationPath);
const message = crypto.createHash('sha256').update('foo bar baz').digest('hex');
const signature = child.sign(message);
I get Expected Scalar
What I'm doing wrong?
The Bitcoin backend I use only stores the WIF. I would like to be able to show the user their mnemonic by calculating it from the WIF.
If one tries to use this library with a zpub
or ypub
like:
const zpub = 'zpub6rJ2iP3x8vJGTf2H8i2RK8KfwpRwyiKmbRYPtvC3zUGK9DHFQYCx5sPhH9TV7ekGgU5bR8fmqNadhRYG9LtWV6gw2UG3UA2BmNNQ2Dp5dJf'
const node = bip32.fromBase58(xpub, networks.bitcoin)
This will fail, because the networks.bitcoin
has only 0488b21e
& 0488ade4
defined as public and private extended key prefixes.
Is there any interest to add support for zpub
& ypub
as well? And if so, how to approach this? as these constants are not even defined here but in bitcoinjs-lib as I can see here.
I'm getting an error when running this library on testnet. Specifically I'm getting the TypeError TypeError('Invalid network version')
. I'm trying to understand this better but I'm having trouble wrapping my head around it.
From the BIP32 wiki, the version is supposed to be the first 4 bytes of a pub/priv key. e.g.
testnet: 0x043587CF public, 0x04358394 private
However, in this bip32 repo, the Type error throws on (here) :
const version = buffer.readUInt32BE(0)
if (version !== network.bip32.private && version !== network.bip32.public)
throw new TypeError('Invalid network version');
I'm struggling to understand how can this statement ever be true? Given:
network.bip32.private = 0x04358394 //testnet
network.bip32.public = 0x043587CF //testnet
then isn't it basically asking if version
is equal to both public and private versions?
Furthermore, a few lines later, the statement (here):
if (version === network.bip32.private) { ...
Given the previous equality condition, wouldn't this line always be true?
It has the same problem as bitcoinjs/bitcoinjs-lib#1512
The commit that tiny-secp256k1 pulls in on master is currently 3 years old, any reason not to update this to a more recent version? For example npmjs.com/package/secp256k1 has a much newer version and fallbacks for the brower as well
Hi There,
I am trying to run the below code:
//Import dependencies
const bip32 = require('bip32')
const bip39 = require('bip39')
const bitcoin = require('bitcoinjs-lib')
//Define the network
const network = bitcoin.networks.bitcoin //use networks.testnet for testnet
// Derivation path
const path = `m/49'/0'/0'/0` // Use m/49'/1'/0'/0 for testnet
let mnemonic = bip39.generateMnemonic()
const seed = bip39.mnemonicToSeedSync(mnemonic)
let root = bip32.fromSeed(seed, network)
let account = root.derivePath(path)
let node = account.derive(0).derive(0)
let btcAddress = bitcoin.payments.p2pkh({
pubkey: node.publicKey,
network: network,
}).address
console.log(`
Wallet generated:
- Address : ${btcAddress},
- Key : ${node.toWIF()},
- Mnemonic : ${mnemonic}
`)
Node version 16.13.2
NPM version 8.6.0
I am running the above .js file like this:
But getting the TypeError: bip32.fromSeed is not a function
any idea what could be causing this?
Thank you.
I'm building a project with angular
, using angular-cli
for building. I'm also using crypto-browserify
, this warning probably comes from it.
Since 2.0.1 this warning appears (ng serve or ng build):
WARNING in ./node_modules/asn1.js/lib/asn1/api.js
Module not found: Error: Can't resolve 'vm' in './node_modules/asn1.js/lib/asn1'
I don't know explicitly what ng runs internally, but I guess this warning comes from browserify or maybe webpack... not sure.
Downgrading to 2.0.0 the warning disappears.
@angular/cli: 7.3.7
@angular/core: 7.2.0
crypto-browserify: 3.12.0
Edit 2 (from junderw): I made an Electrum seed library: Here is the github and it can be installed with npm install electrum-mnemonic
Edit (from junderw): See my reply below for an example of segwit wallet as well
After wasting half a day and reading Electrum docs & sources, here's an example how to work with electrum seed format:
const crypto = require('crypto');
const bitcoin = require('bitcoinjs-lib');
function mnemonic2seed(mnemonic, passphrase = '', iterations = 2048) {
return crypto.pbkdf2Sync(mnemonic, 'electrum' + passphrase, iterations, 64, 'sha512');
}
const root = bitcoin.bip32.fromSeed(mnemonic2seed("<SEED HERE>"));
let xpub = root.toBase58();
const index = 1;
const node = bitcoin.bip32.fromBase58(xpub);
const externalAddress = bitcoin.payments.p2pkh({
pubkey: node.derive(0).derive(index).publicKey,
}).address;
A non-hardened child key should not have private key components -- as in:
var node = bip32js.bip32.fromBase58('<some_private_key');
var child = node.derive(0);
alert("Child: " + child.toBase58());
Interestingly, the child starts with xprv
-- which should have been the case if 0'
were used for derivation. Am I missing something? Is this the expected behavior?
As a possible solution, var child = node.derive(0).neutered();
prevents the child from being able to derive further private keys. Is this the suggested solution?
please update tiny-secp256k1 to resolve this problem.
next.js 14.1
Uncaught TypeError: Cannot read properties of undefined (reading 'call')
at Hash.CipherBase (index.js:7:15)
at new Hash (browser.js:8:10)
at createHash (browser.js:23:12)
at sha256x2 (index.js:6:15)
at Object.encode (base.js:7:24)
at Object.encode (index.js:38:55)
at BIP32.toWIF (bip32.js:151:24)
at generateBTCAddress (addr.ts:90:35)
at generateAddress (BTCAddress.tsx:11:36)
As this module is implemented now, It is possible to derive paths such as this one:
xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483648
or
xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483648
(note the unhardened 2147483648)
This module will handle 2147483648 as if it was a derivation to 0'
(zero hardened).
I understand the reasoning behind this. The problem is Bitcoin Core assumes these paths are wrong.
See for example this fixture here which is expected to fail:
I was considering a PR to fix derivePath
(the function that accepts a string path). But the thing is a PR to fix this "issue" may break other projects that rely on this behaviour...
I'll wait to see what you guys thing about it.
Is there aby abbility ti nit use tiny-bs58check ?!
info cli using local version of lerna
lerna notice cli v3.4.3
lerna info versioning independent
lerna info bootstrap root only
yarn install v1.10.1
[1/4] Resolving packages...
[2/4] Fetching packages...
info [email protected]: The platform "win32" is incompatible with this module.
info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
[4/4] Building fresh packages...
error D:\nodejs\lerna-ark\node_modules\tiny-secp256k1: Command failed.
Exit code: 1
Command: node-gyp rebuild
Arguments:
Directory: D:\nodejs\lerna-ark\node_modules\tiny-secp256k1
Output:
gyp info it worked if it ends with ok
gyp info using [email protected]
gyp info using [email protected] | win32 | x64
gyp info spawn C:\Users\RIK.windows-build-tools\python27\python.exe
gyp info spawn args [ 'D:\nodejs\lerna-ark\node_modules\node-gyp\gyp\gyp_main.py',
gyp info spawn args 'binding.gyp',
gyp info spawn args '-f',
gyp info spawn args 'msvs',
gyp info spawn args '-G',
gyp info spawn args 'msvs_version=2015',
gyp info spawn args '-I',
gyp info spawn args 'D:\nodejs\lerna-ark\node_modules\tiny-secp256k1\build\config.gypi',
gyp info spawn args '-I',
gyp info spawn args 'D:\nodejs\lerna-ark\node_modules\node-gyp\addon.gypi',
gyp info spawn args '-I',
gyp info spawn args 'C:\Users\RIK.node-gyp\8.11.4\include\node\common.gypi',
gyp info spawn args '-Dlibrary=shared_library',
gyp info spawn args '-Dvisibility=default',
gyp info spawn args '-Dnode_root_dir=C:\Users\RIK.node-gyp\8.11.4',
gyp info spawn args '-Dnode_gyp_dir=D:\nodejs\lerna-ark\node_modules\node-gyp',
gyp info spawn args '-Dnode_lib_file=C:\Users\RIK.node-gyp\8.11.4<(target_arch)\node.lib',
gyp info spawn args '-Dmodule_root_dir=D:\nodejs\lerna-ark\node_modules\tiny-secp256k1',
gyp info spawn args '-Dnode_engine=v8',
gyp info spawn args '--depth=.',
gyp info spawn args '--no-parallel',
gyp info spawn args '--generator-output',
gyp info spawn args 'D:\nodejs\lerna-ark\node_modules\tiny-secp256k1\build',
gyp info spawn args '-Goutput_dir=.' ]
gyp info spawn msbuild
gyp info spawn args [ 'build/binding.sln',
gyp info spawn args '/clp:Verbosity=minimal',
gyp info spawn args '/nologo',
gyp info spawn args '/p:Configuration=Release;Platform=x64' ]
���ઠ ��⮢ � �⮬ �襭�� �� ������. �⮡� ������� ��ࠫ������ ᡮ��, ������� ��ࠬ��� "/m".
C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V140\Microsoft.Cpp.Platform.targets(57,5): error MSB8020: The build tools for v141 (Platform Toolset = 'v141') cannot be found. To build using the v141 build tools, please install v141 build tools. Alternatively, you may upgrade to the current Visual Studio tools by selecting the Project menu or right-click the solution, and then selecting "Retarget solution". [D:\nodejs\lerna-ark\node_modules\tiny-secp256k1\build\secp256k1.vcxproj]
gyp ERR! build error
gyp ERR! stack Error: msbuild failed with exit code: 1
gyp ERR! stack at ChildProcess.onExit (D:\nodejs\lerna-ark\node_modules\node-gyp\lib\build.js:262:23)
gyp ERR! stack at emitTwo (events.js:126:13)
gyp ERR! stack at ChildProcess.emit (events.js:214:7)
gyp ERR! stack at Process.ChildProcess._handle.onexit (internal/child_process.js:198:12)
gyp ERR! System Windows_NT 6.1.7601
gyp ERR! command "C:\Program Files\nodejs\node.exe" "D:\nodejs\lerna-ark\node_modules\node-gyp\bin\node-gyp.js" "rebuild"
gyp ERR! cwd D:\nodejs\lerna-ark\node_modules\tiny-secp256k1
gyp ERR! node -v v8.11.4
gyp ERR! node-gyp -v v3.8.0
gyp ERR! not ok
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.
lerna ERR! yarn install --mutex network:42424 --non-interactive exited 1 in 'root'
lerna ERR! yarn install --mutex network:42424 --non-interactive exited 1 in 'root'
So far I am able to derive the Bip32 object from the extended pub key but how to generate a specific receiving address or shareable format address using your module.
Does this library implement BIP44 -- a path naming convention? From the code, it seem it doesn't but just wanted to confirm.
When I'm installing locally I get this node-gyp error from tiny-secp256k1
:
../native/addon.cpp:89:23: error: no matching member function for call to 'BooleanValue'
return info[index]->BooleanValue() ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED;
Hi!
I am 99% sure I am doing something wrong but I am getting the "Invalid network version" error when executing this code:
export async function getSystemKeys(derivationKeyIndex): Promise<{publicKey: string; privateKey: string; address: string}> {
const seed = await bip39.mnemonicToSeed('item lamp erase right project fan awake day crater where dance aspect')
const root = bip32.fromSeed(seed)
const path = `m/49'/1'/0'/0/${derivationKeyIndex}`;
const derived = root.derivePath(path)
const address = getAddress(derived.publicKey);
const publicKey = derived.publicKey.toString('hex');
const privateKey = derived.toWIF();
return {publicKey, privateKey, address};
}
async function test() {
const psbt = bitcoin.Psbt.fromHex(...);
const {privateKey} = await getSystemKeys(10);
console.log(privateKey);
try {
console.log(ECPair.fromWIF(privateKey, config.network));
} catch (e) {
console.log(e);
}
}
test()
in this case, the private key I am getting is L17wmnZK14fDZJHpo4W4VGQRHSCSkD8jUdSoUWMphBaupMFwkCgk
, the network is the testnet
and, if I go putting logs into where the error is happening (https://github.com/bitcoinjs/ecpair/blob/d122cbf63a8ef820427086dd61353a64d6823c9a/src/ecpair.js#L35) I get this logs:
version 128
network {
messagePrefix: '\x18Bitcoin Signed Message:\n',
bech32: 'tb',
bip32: { public: 70617039, private: 70615956 },
pubKeyHash: 111,
scriptHash: 196,
wif: 239
}
network.wif 239
looking at the logs, the network I am passing to the method is the correct one, but the network of the generated wif is the mainnet.
What am I doing wrong?
Thanks in advance!
The library tiny-secp256k1
breaks builds both in vite/rollup, as well as, some webpack configurations. This library's dependency on tiny-secp256k1
makes it unusable. Can you suggests alternatives to tiny-secp256k1
? Thank you 🙏🏾
@axic created useful package for checking derivation path, we can use it here
ref: https://www.npmjs.com/package/bip32-path
Hello, we have found that the library has breaking changes with node v17.
The reason why is explained in this webiste, but a tinny extract from the website says:
This error is because node.js 17 uses OpenSSL3, which has changed code for initialization context of md family (including md4), and this is a breaking change.
Please let us know if more information is needed or if we can help on a different way
I used to have this code in bitcoinjs v3:
function _nodeToBech32SegwitAddress(hdNode) {
const pubkeyBuf = hdNode.publicKey;
var scriptPubKey = bitcoin.script.witnessPubKeyHash.output.encode(bitcoin.crypto.hash160(pubkeyBuf));
var address = bitcoin.address.fromOutputScript(scriptPubKey);
return address;
}
which doesnt work after upgrade.
Thanks!
Trying to get bech32 address from mnemonic words and im getting this error:
const root = bip32.fromSeed(seed)
^
TypeError: bip32.fromSeed is not a function
this is the code im running:
var randomBytes = crypto.randomBytes(16)
var mnemonic = bip39.entropyToMnemonic(randomBytes.toString('hex'))
const seed = bip39.mnemonicToSeedSync(mnemonic);
const root = bip32.fromSeed(seed);
thanks for any helps since im new in the bitcoinjs and crypto programming in general
I am trying to derive grandchildren of a master key and this can be done by using the path m/0/0
-- which requires the master key. To derive the grandchildren from children, I have tried the following:
var node = bip32js.bip32.fromBase58('<some_private_key>')
var child = node.derivePath('m/0')
alert("Child: " + JSON.stringify(child));
var grandChild = child.derivePath('m/0'); // +1 depth from the child (i.e., grandchild)
alert("Grandchild: " + JSON.stringify(grandChild));
But this gives an Expected master, got child
error. I also tried child.derivePath('0/0')
which uses the same notation of m/0
by adding 1 more depth to the key in use but the final depth is 3 instead of 2.
Is the correct path for deriving grandchildren from children 0
in this case (i.e., child.derivePath('0')
)?
(I am not sure whether opening an issue is the correct thing to do for these questions. I looked for a channel to ask but couldn't find one. Stackoverflow did not seem too interested in these questions since it is specific to a library. If there is a better way to ask these, I'd appreciate it if you could share.)
I am using a documented moethod of using this library, yet Node.js throws an error when I try to use the BIP32Factory.
import BIP32Factory from 'bip32'
import * as ecc from 'tiny-secp256k1'
const bip32 = BIP32Factory(ecc)
results in error:
TypeError: BIP32Factory is not a function
My project is running Node.js v14.17.5 and is configured to use ES modules. Same error happened when I tried importing tiny-secp256k1
asynchronously.
I've also tried importing the module directly as import BIP32Factory from 'bip32/src/bip32.js'
but it resulted in the same error.
I' ve looked into the source files (in node_modules) and haven't found what could be wrong.
Hi All,
`const ecc = require('tiny-secp256k1');
console.log(ecc.isPoint)
const { BIP32Factory } = require('bip32');
// You must wrap a tiny-secp256k1 compatible implementation
const bip32 = BIP32Factory(ecc);
const bip39 = require('bip39');
const bitcoin = require('bitcoinjs-lib');
export function generateBitcoinTestAddress(mnemonic) {
//const bip32 = BIP32Factory.default(ecc);
const seed = bip39.mnemonicToSeedSync(mnemonic);
const root = bip32.fromSeed(seed);
const path = "m/49'/1'/0'/0/0";
const child = root.derivePath(path);
const { address } = bitcoin.payments.p2sh({
redeem: bitcoin.payments.p2wpkh({
pubkey: child.publicKey,
network: bitcoin.networks.testnet,
}),
network: bitcoin.networks.testnet,
});
console.log(address, "address");
}
export function generateBitcoinMainAddress(mnemonic) {
//const bip32 = BIP32Factory.default(ecc);
const seed = bip39.mnemonicToSeedSync(mnemonic);
const root = bip32.fromSeed(seed);
const path = "m/49'/0'/0'/0";
const child = root.derivePath(path);
const { address } = bitcoin.payments.p2sh({
redeem: bitcoin.payments.p2wpkh({
pubkey: child.publicKey,
network: bitcoin.networks.bitcoin,
}),
network: bitcoin.networks.bitcoin,
});
} `
I could not able to bip32 throws following error
Unhandled Runtime Error
TypeError: ecc.isPoint is not a function
Source
Object.testEcc
node_modules\bip32\src\testecc.js (5:0)
BIP32Factory
node_modules\bip32\src\bip32.js (9:0)
`
pages\api\Utilities.js (5:14) @ BIP32Factory
3 | const { BIP32Factory } = require('bip32');
4 | // You must wrap a tiny-secp256k1 compatible implementation
5 | const bip32 = BIP32Factory(ecc);
`
discussion in bitcoinjs-lib: bitcoinjs/bitcoinjs-lib#508
I extracted some code from bitcoinjs-lib, repository -- https://github.com/fanatid/bip32
It's far from ideal, but at least we can start not from scratch.
In hw-app-eth
, to export a key, you're given the following interface:
(path: string): Promise<{publicKey: string, address: string, chainCode?: string}>
This is awkward to deal with because you're given the publicKey and not the extended public key (which is what is needed by libraries like this one). One way people tackle this is by rewriting the logic to calculate the extended key which is not ideal either.
There shouldn't be a need for users to have to copy-paste logic to recalculate the fingerprint needed for the extended public key because this library already knows how to do this. However, this library doesn't make public the right constructor to able able to inject the proper values for depth, index and parent fingerprint and instead only providers these constructors.
The solution, I believe, is to do the following:
When I call bip32.fromSeed() got this error [RangeError: Range consisting of offset and length are out of bounds].
on React Native
Waiting on
.isMaster()
)I asked this on StackOverflow but got no response.
How can one export the derived public keys in a non-binary format? For instance,
var node = bip32js.bip32.fromBase58('<some private key>');
var child = node.derivePath('m/0/0');
var publicKey = child.publicKey(); // This gets the public key for the child
console.log(btoa(publicKey)) // This gives an error since the returned public key is not a string
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.