txnlab / use-wallet Goto Github PK
View Code? Open in Web Editor NEWA framework agnostic wallet integration library for Algorand dApps
Home Page: https://txnlab.gitbook.io/use-wallet
License: MIT License
A framework agnostic wallet integration library for Algorand dApps
Home Page: https://txnlab.gitbook.io/use-wallet
License: MIT License
Upon installation of the package, if user wants to only use N out of M total supported providers (for example only pera, defly), use-wallet fails to load on the error below if other peer wallet providers aren't installed:
All wallet connections work, and connections can return a balance amount with provider Id.
The getClient function returns client not found error when signTransactions is called
Error happens with: const signedTransactions = await signTransactions([encodedTransaction]);
the is a way to reinitialize the providers? without recompiling the project for switching networks on the fly like testnet mainet, I was trying to do it but I guess "useInitializeProviders" don't support this behavior thanks!
In v3, if a wallet client requires an SDK/lib to function, its dependency is dynamically imported when the connect
method is called. This reduces the overall bundle size of the library, and only loads the (sometimes very large) dependencies if/when they are needed.
Hot module replacement in local development will sometimes reset the active wallet client to its initial state (depending on the HMR implementation). When you try to sign after a hot reload, a "client is not initialized" error is thrown.
The straightforward solution is to re-initialize if the SDK is not detected instead of throwing the error. But I'd also like to investigate why this happens, as I would expect HMR to preserve state between reloads.
This link is broken. Can you update the polyfills instruction?
If someone wants to use the default configuration for localnet it should work by simply setting network: NetworkId.LOCALNET
and not requiring a custom algod
configuration.
Related to #152 which fixed this for the wallet clients' public methods
I have tried to do npm install
but it has failed with errors
Could not resolve dependency:
npm ERR! peer algosdk@"^1.23.2" from @blockshake/[email protected]
Then i upgraded defly connect, and got
Could not resolve dependency:
npm ERR! peer algosdk@"^1.23.2" from @perawallet/[email protected]
.. many other packages are not updated in the packages.json, so i did ```npm i --legacy-peer-deps`` but audit shows
23 vulnerabilities (22 high, 1 critical)
i am not able to run npm update --save
because of
Could not resolve dependency:
npm ERR! peer rollup@"^2.28.2" from [email protected]
Then i did yarn install
and it has passed, but yarn audit
shows
Severity: 63 High | 14 Critical
Just had a case recently when using this inside a vue project could have been extremely helpful but since the main way to interact with the library is via useWallet and its all react hooks based - how hard would it be to make it generic to be able to work with other frameworks?
At the end of the day - walletconnect, algosigner, peraconnect, myalgo and etc are all stack agnostic and aren't locked to react only.
@gabrielkuettel @pbennett what do you guys think about potentially morphing the repo into more generalist utility that can work with vue composition api, other frameworks and generally not be tied to use via react hooks only.
Vite is pretty fast and performant tool that lots of project prefer over things like webpack these days. They seem to have this ideological preference to avoid using node specific packages in frontend projects. Because of that walletconnect has tons of issues with it out of the box. Just as a minor suggestion - might make sense to validate whether there are no out of the box issue with vite if any react based projects using that would like to use use-wallet hooks.
I was encountering these errors:
Someone else posted on Discord:
Source: https://discord.com/channels/925410112368156732/1039592016704721019/1051855605003984938
AlgoSigner:
Exodus:
use-wallet/src/clients/exodus/client.ts
Line 61 in 71d6908
It's not really an error, someone does not have an extension installed, first thing that comes to mind:
console.warn("AlgoSigner not initialised. Reason: no extension installed.")
Something that would explain what is happening rather than sea of red in the console.
Similar to its algod client, the WalletManager can create an indexer client that is optionally configurable and updates when the active network changes.
Add a new client to support the KMD wallet interface
I am seeing the following error when attempting to disconnect a Pera client:
Unhandled Runtime Error
TypeError: Cannot read private member #client from an object whose class did not declare it
Call Stack
Object.disconnect [as callback]
node_modules/@txnlab/use-wallet/dist/esm/index.js (1127:0)
eval
node_modules/@walletconnect/core/dist/esm/events.js (41:0)
Array.forEach
<anonymous>
EventManager.trigger
node_modules/@walletconnect/core/dist/esm/events.js (35:0)
WalletConnect._handleSessionDisconnect
node_modules/@walletconnect/core/dist/esm/index.js (633:0)
WalletConnect.killSession
node_modules/@walletconnect/core/dist/esm/index.js (418:0)
The error only appears to happen when the webpage is reloaded after the client is set as active.
authAddr
is required for a rekeyed account.
Here is their spec:
https://github.com/PureStake/algosigner/blob/develop/docs/dApp-integration.md#transaction-requirements
Next.js (React) and Nuxt (Vue) examples demonstrate using the library's framework adapters in SSR apps with client side hydration. Now that the SolidJS adapter has been added, it would be helpful to include a SolidStart example app as well.
Hello,
I am trying to send a transaction and got the following error:
RangeError: offset is outside the bounds of the DataView
readU8 Decoder.ts:550
readHeadByte Decoder.ts:430
doDecodeSync Decoder.ts:210
doDecodeSingleSync Decoder.ts:124
decode Decoder.ts:120
V decode.ts:58
decode encoding.ts:66
decodeSignedTransaction transaction.ts:1360
sendRawTransactions index.js:147
sendTransactions index.js:3831
startTxn Transactions.tsx:107
handleShippingSubmit Store.tsx:136
React 29
The line causing the issue is:
await sendTransactions(stxn, waitRoundsToConfirm);
And stxn is a UintArray:
preSignedTxn
Uint8Array(321) [ 131, 164, 115, 103, 110, 114, 196, 32, 130, 195, … ]
[0…99]
[100…199]
[200…299]
[300…320]
buffer: ArrayBuffer { byteLength: 321 }
byteLength: 321
byteOffset: 0
length: 321
: Uint8Array.prototype { … }
Transactions.tsx:106
Is there anything I am missing here? Is the length wrong?
The common issue for React Native projects to adapt React libraries is that some of the libraries have some other React dependencies and react-native doesn't have a corresponding peer.
For example, js Algo SDK has a dependency which I think is crypto and the react-native project cannot directly use the one provided for React.
Hope we can have a react native version (expo preferred)
I am using walletConnect to connect another blockchain via (rainbowKit with wallet-conenct option) while enabling walletConnect in use-Wallet for algorand as well,
This cause an error of Failed to execute 'define' on 'CustomElementRegistry': the name "wcm-button" has already been used with this registry
, seems like its caused by the @walletconnect/modal-sign-html
when initializing the wallet-connect registering something twice..
Any idea how can i solve this?
The order of the array of providers
passed to useInitializeProviders
should determine the order of providers
returned by the useEffect
hook in-app.
🎁 hiii
i do believe the following function works nice for groups with a single signer or with multiple consecutive, liike:
or
is returned as-is
but in case of non-consecutive, it returns duplicated txns and while duplicating misses the txn on each replaced index, liike:
is returned as:
(note utxn2 is lost and replaced by a duplicated stxn1)
(note² in the examples, signerA will sign a txn, and signerB already signed it so will not sign nothing on this request)
use-wallet/src/clients/pera/client.ts
Lines 204 to 213 in 380bd15
thank you for your awesome work'¡
There are cases when there is a need to perform rekeying back to original addresses, in such cases signer is the current address to which it was rekeyed. However txn fields such as sender, receiver and rekeyTo are all set to original address.
Defly and Pera have an ability to pass authAddress to SignersAccount on their respective signTransactions function. In use-wallet though behaviour is rather implicit and varies depending on wallet provider.
Would be great to have an ability to select which txns in txn group has to be signed by a different signer and cover that in documentation.
Apps that have installed https://github.com/TxnLab/use-wallet/releases/tag/v2.6.0 or https://github.com/TxnLab/use-wallet/releases/tag/v2.6.1 will encounter build failures if @magic-ext/algorand
is not installed, even if they are not configured to support the Magic.link provider.
Although the Magic SDK is passed to the useInitializeProviders
configuration object via the clientStatic
or getDynamicClient
properties, the Algorand extension is directly imported by the Magic provider client, making it a required dependency.
It must also be passed to the configuration object:
const getDynamicMagicSdk = async () => {
const Magic = (await import('magic-sdk')).Magic
return Magic
}
const getDynamicAlgoExtension = async () => {
const AlgorandExtension = (await import('@magic-ext/algorand')).AlgorandExtension
return AlgorandExtension
}
const providers = useInitializeProviders({
providers: [
{
id: PROVIDER_ID.MAGIC,
getDynamicClient: getDynamicMagicSdk,
getDynamicExtension: getDynamicAlgoExtension,
clientOptions: { apiKey: '<API_KEY>' }
},
// ... other provider configurations
],
})
The library should not import any SDKs/dependencies for wallet providers (besides type imports). This should be handled by the consuming application on an opt-in basis, depending on which wallets it supports.
Apps that support the Magic.link provider are unaffected, since they must install its dependencies for it to work.
Just a suggestion, but for performance purposes (reducing bundle size) would be great if package had a lower footprint. Showing 206k 👍
Thanks for releasing this package! I'm new to the Algo eco, and although the tooling/documentation appears to be thorough, I was getting concerned that I wasn't able to find an existing JS package that abstracts connecting & transacting via the various wallet softwares behind a common interface.
The js-sdk defines a TransactionSigner
interface to be passed to TransactionWithSigner and ATC method calls, it'd make a great addition to this package
Definition here:
https://github.com/algorand/js-algorand-sdk/blob/develop/src/signer.ts#L15-L18
One implementation here:
https://github.com/algorand-devrel/beaker-ts/blob/master/src/web/session_wallet.ts#L130-L144
Here it is set by default to false
:
use-wallet/src/clients/pera/client.ts
Line 63 in 1bca5ab
Originally the default is set to true
:
https://github.com/perawallet/connect#options
Previously I had a single line of code and I was happy:
const walletProviders = initializeProviders();
Then I've realised that Pera doesn't trigger the popup and I need to manually initialise it.
BUT
Passing an empty array as the first argument enables all of the default providers.
Configuring Pera caused other wallets to disappear and as a consequence I need to add all other wallets manually.
import { PROVIDER_ID, pera, myalgo, kmd, algosigner, defly, exodus, walletconnect } from "@txnlab/use-wallet";
const walletProviders = {
[PROVIDER_ID.PERA]: pera.init({
clientOptions: {
shouldShowSignTxnToast: true,
}
}),
[PROVIDER_ID.MYALGO]: myalgo.init({}),
[PROVIDER_ID.DEFLY]: defly.init({}),
[PROVIDER_ID.KMD]: kmd.init({}),
[PROVIDER_ID.ALGOSIGNER]: algosigner.init({}),
[PROVIDER_ID.EXODUS]: exodus.init({}),
[PROVIDER_ID.WALLETCONNECT]: walletconnect.init({})
};
(passing empty clientOptions
to use defaults)
Ideally there should be an option to keep the defaults + configure individual wallet.
This was a change I made in #187, specifically here: 486c892
In retrospect it was a heavy-handed solution to address certain wallets simply not working after changing networks.
After discussing with @acfunk I think the library should take a hands-off approach to this issue, and let the consuming app worry about it.
A warning can be added to the documentation for setActiveNetwork
that some wallets simply do not support this, and signing requests will fail until the wallet is disconnected and reconnected on the new network.
There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.
Error type: Cannot find preset's package (on the 2nd day of the month)
Algosdk depedency is pinned to a specific version, when the dependency cannot be deduplicated it will cause errors with any Transactions. This is something that has come up before as well: algorand/js-algorand-sdk/issues/740
A transaction is trying to be created twice in the instantiateTxnIfNeeded
call even though it is a valid instance of a Transaction. This is due to the algosdk
being included twice in a project that depends on a different version than the currently pinned version.
Error: address seems to be malformed
at decodeAddress (address.ts:49:11)
at new Transaction (transaction.ts:264:24)
at instantiateTxnIfNeeded (transaction.ts:1378:7)
at Kmd.signTransaction (kmd.ts:264:20)
at kmd.ts:236:38
at Array.map (<anonymous>)
at _a5.signTransactions (kmd.ts:236:18)
at async _a5.transactionSigner (base.ts:67:28)
at async Promise.all (:5173/index 0)
at async _AtomicTransactionComposer.gatherSignatures (composer.ts:541:25)
Easiest solution would be adding algosdk
to the peerDependencies
and allowing ^2.7.0
.
Allow SupportedLedger
or string name for network during connect
call to pass to the wallet
https://github.com/TxnLab/use-wallet/blob/main/src/clients/algosigner.ts#L93
Following the steps in the readme, i've added wallet providers to app:
const providers = useInitializeProviders({
providers: [
{ id: PROVIDER_ID.DEFLY, clientStatic: DeflyWalletConnect },
{ id: PROVIDER_ID.PERA, clientStatic: PeraWalletConnect },
{ id: PROVIDER_ID.DAFFI, clientStatic: DaffiWalletConnect },
{ id: PROVIDER_ID.EXODUS }
],
nodeConfig: {
network: 'testnet',
nodeServer: 'https://testnet-api.algonode.cloud/',
nodeToken: '',
nodePort: '443'
}
})
...
return (
<WalletProvider value={providers}>
<RouterProvider router={router} />
</WalletProvider>
)
Then, on a page i have:
import { useWallet,
DEFAULT_NODE_BASEURL,
DEFAULT_NODE_TOKEN,
DEFAULT_NODE_PORT } from '@txnlab/use-wallet'
const algodClient = new algosdk.Algodv2(DEFAULT_NODE_TOKEN, DEFAULT_NODE_BASEURL, DEFAULT_NODE_PORT)
...
const { activeAccount, activeAddress, signTransactions, sendTransactions } = useWallet()
const suggestedParams = await algodClient.getTransactionParams().do();
const ptxn = algosdk.makePaymentTxnWithSuggestedParamsFromObject({
from: activeAddress,
suggestedParams,
to: constants.receiveWallet,
amount: algosdk.algosToMicroalgos(total/algoInUsd/1000),
note: new Uint8Array(Buffer.from(noteKey)),
});
try {
const encodedTransaction = algosdk.encodeUnsignedTransaction(ptxn)
const signedTransactions = await signTransactions([encodedTransaction])
const waitRoundsToConfirm = 4
const { id } = await sendTransactions(signedTransactions, waitRoundsToConfirm)
console.log('Successfully sent transaction. Transaction ID: ', id)
} catch (error) {
console.log("Couldn't sign txn", error);
}
Testing with Pera connected using Pera Web, and when signing that tx i'm sent to Pera which shows TESTNET
since i have the node set to testnet, i get:
Network mismatch
Your wallet is connected to a different network to this dApp. Update your wallet to the correct network (MainNet or TestNet) to continue.
Is there something i'm missing or overlooked? I have connected to Pera using essentially the demo code (with ui formatting), with testnet set, and restarted the app a few times but i cannot gewt it to connect to testnet.
Any help is much appreciated.
The library uses ES6 classes with private methods, which Safari started supporting in v15. Older versions of Safari will throw:
SyntaxError: Unexpected private name #<method name>. Cannot parse class method with private name.
Using @rollup/plugin-babel older browsers can be targeted with polyfills.
This is a holdover from the original MyAlgo implementation (pre ARC-0001) that only supported signatures by a single account per group.
NFDomains requires signatures from two accounts to verify a linked address, so our solution was to return the entire group (not just the signed transactions) so a second signing request could be initiated.
This is no longer necessary, and adds unnecessary complexity to the library's signing logic. It also breaks with the ARC-0001 SignTxnsFunction
type signature by returning unsigned transactions.
My use case involves leveraging a hot wallet to sign some transactions in a group. The sender needs to sign some other transactions, but the group cannot be signed when using the WalletConnect client. Note - it does work when using the Pera client.
Just a suggestion for cases when it's not possible to fully e2e test things like perawallet or myalgo, a simple in-browser mnemonic account is useful for e2e tests in tools like cypress, selenium, playwright because it's easier to automate input of a mnemonic phrase rather than automation real providers.
Can function similar to the existing KMD provider - on select it asks for a passphrase of an account and that's it. Related documentation or warnings can be supplied that it's only recommended in testing/dev environments.
Let me know if more examples of how this provider can be useful for ui testing just let me know. Also if you'd agree that this is useful i can try the initial pr draft myself - i believe it should be relatively easy to implement.
The code I used that had setup for connecting Defly wallet previously worked, but suddenly it's not executing the correct behavior. I cannot connect my app to a Defly wallet anymore.
Let me know if there are any fixes in the works.
First Off I wanted to thank for at least attempting to build out this library - It's something the Algorand ecosystem desperately needs.
However currently while using remix.run the plugin in unusable with many errors - remix uses Esbuild.
I kept getting build errors that I needed to install dependencies which are marked as peer dependencies in your app
algorand-walletconnect-qrcode-modal and @blockshake/defly-connect even when I install those
I keep getting process is undefined when importing anything from your package in the browser leaving my application unusable.
const NODE_SERVER = process.env.NODE_SERVER ||
line 14
I tried to set the environment variable but to no avail it breaks no matter what
Also I cloned your repo and in order to run the storybooks - I needed to install webpack as well
Let me know if I can help out in anyway - I think it's a great project to have and hope it becomes the "raindbowkit or web3modla" of algorand.
I propose the addition of returning the value 'isReconnecting' from the useWallet
hook.
There are various use cases where this might be useful, but the most glaring one that comes to mind is the following:
however, suppose that:
In this scenario, as soon as the user lands on the page, a check will be made to see if the address with which the user is connected is authorised.
But since the reconnection takes an arbitrary amount of time, most likely at the time the check takes place, the reconnection has not yet taken place and so the redirect is made to another page.
In such a circumstance, a variable such as 'isReconnecting' is required to have control.
I can't seem to use useWallet in safari browser, it only works in latest version of safari. i keep getting these errors "SyntaxError: Unexpected private name #composeTransactions. Cannot parse class method with private name."
I would love an alternative approach or solution to this issue thanks.
The wallet provider clients for Lute Wallet, Kibisis, Exodus and WalletConnect use the Node.js Buffer
API to convert byte arrays to/from base 64 strings in their signing methods.
To use Buffer
in a browser environment, a polyfill like the buffer
NPM package is needed. While Next.js applications support this out-of-the-box, other frameworks (like Vite + React) do not. Without the polyfill, attempting to sign transactions with these wallet providers will fail.
Instead of requiring consuming applications to install the polyfill, wallet provider clients should instead use the native JavaScript methods atob
and btoa
, which are available in the browser.
See the equivalent fix in v3: #153
v3 with pera fails to connect with message
ReferenceError: global is not defined
Add shim to index.html
but it may be better to update the pera library
<head>
<script>
// Suggest that Pera to use globalThis instead of global | window
globalThis.global = globalThis
</script>
</head>
Hey. I had trouble getting the signer
method to work.
https://github.com/TxnLab/use-wallet/blob/main/src/hooks/useWallet.ts#L191-L201
Should this method be filtering the transactions before signing using indexesToSign
, rather than after? e.g
const signedTxns = await Promise.resolve(
signTransactions(blobs.filter((_, idx) => indexesToSign.includes(idx)))
);
I am not sure what the implications are of signing all transactions rather than those specified by indexesToSign
.
Hi, I noticed that on mobile, some users get double transactions, therefore get an overspend error sometimes, and it throws an error. How can I get some logs about that ?
This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.
These updates have all been created already. Click a checkbox below to force a retry/rebase of any.
@magic-ext/algorand
, @magic-sdk/provider
, @perawallet/connect-beta
, @solidjs/testing-library
, @tanstack/react-store
, @tanstack/solid-store
, @tanstack/store
, @tanstack/vue-store
, @testing-library/jest-dom
, @testing-library/react
, @types/node
, @types/react
, @vitejs/plugin-react
, @vitejs/plugin-vue
, @vue/test-utils
, @walletconnect/sign-client
, @walletconnect/types
, eslint-plugin-prettier
, jsdom
, magic-sdk
, prettier
, react
, react-dom
, solid-js
, tsup
, typescript
, vite
, vitest
, vue
, vue-demi
)@typescript-eslint/eslint-plugin
, @typescript-eslint/parser
)These are blocked by an existing closed PR and will not be recreated unless you click a checkbox below.
.github/workflows/ci.yml
actions/checkout v4
actions/setup-node v4
pnpm/action-setup v4
actions/cache v4
.github/workflows/github-releases-to-discord.yml
actions/checkout v4
SethCohen/github-releases-to-discord v1.15.0
package.json
@testing-library/jest-dom 6.4.2
@testing-library/react 14.2.2
@typescript-eslint/eslint-plugin 6.21.0
@typescript-eslint/parser 6.21.0
@vitejs/plugin-react 4.2.1
@vitejs/plugin-vue 5.0.4
@vitejs/plugin-vue-jsx 3.1.0
@vue/test-utils 2.4.5
eslint 8.57.0
eslint-config-prettier 9.1.0
eslint-plugin-prettier 5.1.3
prettier 3.2.5
vite 5.2.6
vite-plugin-solid 2.10.2
vitest 1.4.0
vue-demi 0.14.7
pnpm 9.2.0
packages/use-wallet-react/package.json
@tanstack/react-store 0.4.1
@types/react 18.2.70
algosdk 2.8.0
jsdom 24.0.0
react 18.2.0
react-dom 18.2.0
tsup 8.0.2
typescript 5.4.3
@blockshake/defly-connect ^1.1.6
@magic-ext/algorand ^23.0.2
@perawallet/connect-beta ^2.0.11
@walletconnect/modal ^2.6.2
@perawallet/connect ^1.3.4
@walletconnect/sign-client ^2.10.2
algosdk ^2.7.0
lute-connect ^1.3.0
magic-sdk ^28.0.3
react ^17.0.0 || ^18.0.0
react-dom ^17.0.0 || ^18.0.0
packages/use-wallet-solid/package.json
@tanstack/solid-store 0.4.1
@solidjs/testing-library 0.8.7
algosdk 2.8.0
solid-js 1.8.16
tsup 8.0.2
tsup-preset-solid 2.2.0
typescript 5.4.3
@blockshake/defly-connect ^1.1.6
@magic-ext/algorand ^23.0.2
@perawallet/connect ^1.3.4
@perawallet/connect-beta ^2.0.11
@walletconnect/modal ^2.6.2
@walletconnect/sign-client ^2.10.2
algosdk ^2.7.0
lute-connect ^1.3.0
magic-sdk ^28.0.3
packages/use-wallet-vue/package.json
@tanstack/vue-store 0.4.1
algosdk 2.8.0
tsup 8.0.2
typescript 5.4.3
vue 3.4.21
@blockshake/defly-connect ^1.1.6
@magic-ext/algorand ^23.0.2
@perawallet/connect ^1.3.4
@perawallet/connect-beta ^2.0.11
@walletconnect/modal ^2.6.2
@walletconnect/sign-client ^2.10.2
algosdk ^2.7.0
lute-connect ^1.3.0
magic-sdk ^28.0.3
vue ^3.0.0
packages/use-wallet/package.json
@tanstack/store 0.4.1
@agoralabs-sh/avm-web-provider 1.6.2
@blockshake/defly-connect 1.1.6
@magic-ext/algorand 23.0.2
@magic-sdk/provider 28.0.2
@perawallet/connect 1.3.4
@perawallet/connect-beta 2.0.11
@types/node 20.11.30
@walletconnect/modal 2.6.2
@walletconnect/modal-core 2.6.2
@walletconnect/sign-client 2.11.3
@walletconnect/types 2.11.3
algosdk 2.8.0
lute-connect 1.3.0
magic-sdk 28.0.3
tsup 8.0.2
typescript 5.4.3
@agoralabs-sh/avm-web-provider ^1.6.2
@blockshake/defly-connect ^1.1.6
@perawallet/connect ^1.3.4
@perawallet/connect-beta ^2.0.11
@walletconnect/modal ^2.6.2
@walletconnect/sign-client ^2.10.2
algosdk ^2.7.0
lute-connect ^1.3.0
Using Exodus and AlgoSigner wallets in the same Chrome browser causes a conflict
Connecting AlgoSigner should not be picking up the account from Exodus wallet; it should return the account that AlgoSigner has.
The Exodus account will appear under AlgoSigner instead of the account from AlgoSigner
If the Chrome extensions are disabled so that only one is active at a time, they will work fine on their own.
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.