Giter VIP home page Giter VIP logo

extension's Introduction

Taho Extension

The community owned & operated wallet.

Taho is a community owned and operated Web3 wallet, built as a browser extension.

Why not MetaMask?

Today's Web3 landscape is dominated by a single wallet and a single infrastructure provider, both owned by a single conglomerate. These facts undermine the censorship resistance of Ethereum today... and they're also against Web3's spirit of community ownership.

We can do better.

Taho will be

  • Fairly launched βš–οΈ
  • Sustainably aligned with users 🀲
  • Wholly owned by the community πŸ‘ͺ

Quickstart

Try this.

$ nvm use
$ nvm install
$ npm install -g yarn # if you don't have yarn globally installed
$ yarn install # install all dependencies; rerun with --ignore-scripts if
               # scrypt node-gyp failures prevent the install from completing
$ yarn start # start a continuous webpack build that will auto-update with changes

Once the build is running, you can install the extension in your browser of choice:

Extension bundles for each browser are in dist/<browser>.

By default, the yarn start command rebuilds the extension for each browser on save. You can target a particular browser by specifying it in the command, e.g. to only rebuild the Firefox extension on change:

# On change, rebuild the firefox extension but not others.
$ yarn start --config-name firefox
# On change, rebuild the firefox and brave extensions but not others.
$ yarn start --config-name firefox --config-name brave
# On change, rebuild the chrome
$ yarn start --config-name chrome

Note for some Linux distributions

In some Linux distributions such as Ubuntu 20.04, you need to explicitly tell npm where your python3 executable is located before running the above commands successfully:

$ npm config set python /usr/bin/python3

Package Structure, Build Structure, and Threat Model

The extension is built as two packages, background and ui. background contains the bulk of the extension's background script, while ui contains the code powering extension popups.

These are separate packages in order to emphasize the difference in attack surface and clearly separate the threat models of each. In particular, ui is considered untrusted code, while background is considered trusted code. Only background should interact with key material regularly, while ui should only interact with key material via a carefully maintained API.

The background package is also intended to minimize external dependencies where possible, reducing the surface exposed to a supply chain attack. Dependencies are generally version-pinned, and yarn is used to ensure the integrity of builds.

Building and Developing

Builds are designed to be run from the top level of the repository.

Development Setup

If you’re on macOS, install Homebrew and run scripts/macos-setup.sh. Note that if you don’t have Homebrew or you’re not on macOS, the below information details what you’ll need. The script additionally sets up pre-commit hooks.

$ ./scripts/macos-setup.sh

Validators

If you need to create or update a validation function then:

  • You need to write the schema in the .ts file to have correct typing.
  • Add the new schema with the validator function name to the generate-validators.ts file
  • You need to update the jtd-validators.d.ts or json-validators.d.ts files with the typing definition
  • run yarn run generate:validators
  • import it in your code and happy validating :)

This setup is necessary so we don't need to include unsafe-eval in the CSP policy.

Required Software

If you can't use the macOS setup script, here is the software you'll need to install:

Installing pre-commit hooks

Before committing code to this repository or a fork/branch that you intend to submit for inclusion, please make sure you've installed the pre-commit hooks by running pre-commit install. The macOS setup script does this for you.

Local mainnet fork setup for development

For more detailed description see ./dev-utils/local-chain/README.md

Quick Start:

$ cd dev-utils/local-chain
$ yarn install
$ yarn start

Commit signing

Commits on the Taho repository are all required to be signed. No PR will be merged if it has unsigned commits. See the GitHub documentation on commit signing to get it set up.

Releasing a version

This repository uses yarn version to create new versions. Typical usage:

$ yarn version --patch # bump patch version, e.g. 0.0.5->0.0.6
$ yarn version --minor # bump minor version, e.g. 0.1.5->0.2.0

Major releases generally require more discussion than this automation allows, but can be managed the same way.

Bumping a version in this way will do a few things:

  • Ensure the commit is running on the correct branch (release-<new-version>) for review. If you are on a different branch, the script attempts to switch to a new branch based on the latest origin/main. Releases should generally only add version bumps to the main branch.
  • Synchronize the extension manifest version to the updated package version.
  • Commit, tag, and push the new version and branch.

Once the branch is pushed, you should open a pull request. This will do any further processing, including potentially managing automated submission of the new version to extension directories (as relevant).

Additional Scripts

$ yarn build # create a production build of the extension

The build script will generate a ZIP file for each browser bundle under the dist/ directory.

$ yarn lint # lint all sources in all projects
$ yarn lint-fix # auto-fix any auto-fixable lint issues
$ yarn test # run all tests in all projects

A note on git blame

Because lint configurations can occasionally evolve in a way that hits many files in the repository at once and obscures the functional blame readout for files, this repository has a .git-blame-ignore-revs file. This file can be used to run git blame while skipping over the revisions it lists, as described in the Pro Git book reference and this Moxio blog post.

To make use of this, you can do one of the following:

  • Run git config --global blame.ignoreRevsFile .git-blame-ignore-revs to configure git to globally look for such a file. The filename is relatively standard across projects, so this should save time for other projects that use a similar setup.
  • Run git config blame.ignoreRevsFile .git-blame-ignore-revs to configure your local checkout to always ignore these files.
  • Add --ignore-revs-file .git-blame-ignore-revs to your git blame invocation to ignore the file one time.

The GitHub UI does not yet ignore these commits, though there is a community thread requesting the feature. In the meantime, the GitHub blame UI does allow you to zoom to the previous round of changes on a given line, which relieves much of the annoyance; see the GitHub blame docs for more.

Architecture

Here is a light architecture diagram describing the relationship between services (in the API package) and the interface and browser notifications:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                                                                                                     β”‚
β”‚   ____                  _                                                                           β”‚
β”‚  / ___|  ___ _ ____   _(_) ___ ___  ___                                                             β”‚
β”‚  \___ \ / _ \ '__\ \ / / |/ __/ _ \/ __|                                       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”
β”‚   ___) |  __/ |   \ V /| | (_|  __/\__ \                                       β”‚                    β”‚  β”‚
β”‚  |____/ \___|_|    \_/ |_|\___\___||___/                                       β”‚                    β”‚  β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                                                                     Chain                           β”‚  β”‚   β”‚External Servicesβ”‚
β”‚                                                                     - Blocks      ━━━━━━━━━━━━┓     β”‚  β”‚   β”‚                 β”‚
β”‚                 β”Œβ”€β”€β”€β”€subscribe (incoming or outgoing tx status)───▢ - Transactions            ┃     β”‚  β”‚   β”‚  Local node     β”‚
β”‚                 β”‚                                                                             ┃     β”‚  β”‚   β”‚                 β”‚
β”‚                 β”‚                                                                             ┃     β”‚  β”‚   β”‚  Alchemy        β”‚
β”‚                 β”‚                                                                             ┃     β”‚  β”œβ”€β”€β”€β–Ά                 β”‚
β”‚                 β”‚                                                    Indexing                 ┃     β”‚  β”‚   β”‚  BlockNative    β”‚
β”‚                 β”‚                                                    - Accounts               ┃     β”‚  β”‚   β”‚                 β”‚
β”‚                 β”‚                                                    - ERC-20 balances    β”β”β”β”β•‹β”€β”€β”€β”€β”€β”Όβ”€β”€β”˜   β”‚  CoinGecko      β”‚
β”‚                 β”œβ”€β”€β”€subscribe (eg balance changes), get balances───▢ - ERC-721 ownership      ┃     β”‚      β”‚                 β”‚
β”‚                 β”‚                                                    - Governance proposals   ┃     β”‚      β”‚                 β”‚
β”‚                 β”‚                                                    - On-chain prices        ┃     β”‚      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚                 β”‚                                                                             ┃     β”‚
β”‚                 β”‚                                                                             ┃     β”‚      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                 β”‚                                                   Internal Signer           ┃     β”‚      β”‚                β”‚
β”‚                 β”œβ”€β”€β”€β”€β”€β”€list accounts, sign tx, sign message───────▢ - Native  ────────────────╋─────┼──────▢   Extension    β”‚
β”‚                 β”‚                                                   - Remote                  ┃     β”‚      β”‚  Storage API   β”‚
β”‚      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                                                  ┃     β”‚      β”‚                β”‚
β”‚      β”‚                     β”‚                                                                  ┃     β”‚      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚      β”‚                     β”‚                                                                  ┃     β”‚
β”‚      β”‚     Wallet API      │──────┐                                 Preferences  ━━━━━━━━━━━━━┫     β”‚
β”‚      β”‚                     β”‚      β”‚                                                           ┃     β”‚      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚      β”‚                     β”‚      β”‚                                                           ┃     β”‚      β”‚                β”‚
β”‚      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–²β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β”‚                                 Notifications             ┃     β”‚      β”‚                β”‚
β”‚                 β”‚                 β”‚                                 - Ephemeral               ┣━━━━━╋━━━━━━▢   IndexedDB    β”‚
β”‚                 β”‚                 └──────pull and subscribe───────▢ - Application      ━━━━━━━┛     β”‚      β”‚                β”‚
β”‚                 β”‚                                                   - Security-critical             β”‚      β”‚                β”‚
β”‚             subscribe                                                          β”‚                    β”‚      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚              and get                                                           β”‚                    β”‚
β”‚                 β”‚                                                              β”‚                    β”‚
β”‚                 β”‚                                                            push                   β”‚
β”‚                 β”‚                                                              β”‚                    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                             β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                                  β”‚                             β”‚                               β”‚
β”‚                                  β”‚                             β”‚                               β”‚
β”‚         Wallet interface         β”‚                             β”‚     Browser notifications     β”‚
β”‚                                  β”‚                             β”‚                               β”‚
β”‚                                  β”‚                             β”‚                               β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                             β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                   β”‚               β”‚
                   β”‚ Internal dApp β”‚
                   β”‚               β”‚
                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”Œβ”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”
                   β”‚ Earn β”‚ β”‚ Swap β”‚
                   β””β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”˜

File Structure

Extension content lives directly under the root directory alongside project-level configuration and utilities, including GitHub-specific functionality in .github. Extension content should be minimal, and largely simply glue together UI and wallet code. Manifest information is managed in the manifest/ subdirectory as described below.

Here is a light guide to the directory structure:

.github/ # GitHub-specific tooling

package.json      # private extension package
webpack.config.js # Webpack build for extension

src/ # extension source files
  background.js # entry file for the background extension script; should be
                # minimal and call in to @tallyho/tally-wallet
  ui.js         # entry file for the frontend UI; should be minimal and bind
                # the functionality in @tallyho/tally-ui

dist/ # output directory for builds
  brave/   # browser-specific
  chrome/  # build
  edge/    # directories
  firefox/
  brave.zip  # browser-specific
  chrome.zip # production
  edge.zip   # bundles
  firefox.zip

build-utils/ # build-related helpers, used in webpack.config.js
  *.js
dev-utils/          # dev-mode helpers for the extension
  extension-reload.js # LiveReload support for the extension.
manifest/         # extension manifest data
  manifest.json             # common manifest data for all browsers
  manifest.chrome.json      # manifest adjustments for Chrome
  manifest.dev.json         # manifest adjustments for dev environment
  manifest.firefox.dev.json # manifest adjustments for Firefox in dev

background/ # @tallyho/tally-background package with trusted wallet core
  package.json

ui/ # @tallyho/tally-ui package
  package.json

Firefox store build

Firefox requires to upload source code if minifier is used and to be able to compile identical output to the uploaded package. Our builds are environment dependent at the moment because of the minification and source map process. Long term solution will be to upgrade our build process to be able to produce identical file assets, but until then we use Docker.

  1. Install and setup container manger, like at nerdctl,podman or docker
  2. Clone git repository
git clone https://github.com:tallycash/extension.git tallyho-firefox
  1. Change the directory
cd tallyho-firefox
git checkout tags/latest_release-tag
  1. Fill the production keys .env.prod file

  2. Run build script

./firefox-build.sh
  1. Archive it
zip -r tallyho-firefox.zip dist/firefox
  1. You can delete everything if you want except for the archive

Localization

Taho currently only supports English as the default language. We distill english strings to _locales to prepare for localization.

For other languages, we will use language code defined in Support locales. We will use weblate for crowd translation, and will commit back to the github periodically after these translations are QA'ed.

Translation status

extension's People

Contributors

0xdaedalus avatar 7alip avatar ahsan-javaiid avatar alleycat0001 avatar andreachapman avatar cairomassimo avatar dills122 avatar dmtrbrl avatar eladrof avatar frankiebee avatar gasolin avatar gaudren avatar henryboldi avatar hyphenized avatar idange avatar ioay avatar itsrachelfish avatar jagodarybacka avatar mhluongo avatar michalinacienciala avatar mr-michael avatar ngrinkevich avatar omahs avatar rootial avatar shadowfiend avatar thejarx avatar weblate avatar wojciech-turek avatar xpaczka avatar zuuring 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

extension's Issues

[aggregate] Project setup

Build system dev:

  • build for chrome
  • live reload

Build system production:

  • safari
  • chrome
  • firefox

Docs:

  • have a loose chart of expected flows and communications
  • doc project layout

Testing:

  • setup testing
  • e2e in browser (work with FED)
  • unit
  • component testing (work with FED)

github actions:

  • prepare prod builds on release branches?

In-page JS

What interface do dApps see when a user has Tally installed?

We need to

  • Include a Web3 provider
  • Support account unlocking
  • Consider not showing the in-page JS unless a user has decided to connect to a wallet (preventing the easy Ethereum user tracking MetaMask et al currently enable)

This might have to happen via the usual inpage.js, or via content scripts for manifest v3 forward compatibility.

Relates to #4

Linting & Github Actions

Two actions to be had here:

  • Linting (using run-p?).
    • eslint for JS, using eslint-config-prettier, airbnb linting rules, and TypeScript extensions to those rules.
    • prettier for config and docs (yaml, json, toml though we don't really have any, and markdown)
    • fix all linting errors
  • Basic smoke test extension build. The goal here isn't to pump out artifacts yet necessarily, but to have something that will fail if we break the build somehow.

Push notifications on tx status

We want browser push notifications on

  • Tx submission
  • Tx mempool drop
  • Tx confirmation
  • Payment receipt

To avoid running a centralized backend, we want to use a provider that supports WebSockets.

https://docs.blocknative.com/websocket

We also need to fall back gracefully, first to a regular data provider or local node, then to skipping the functionality.

Optimism support

  • Include Optimism in the default network selection dropdown
  • Include Optimism on Kovan
  • Support Uniswap, Saddle, and Synthetix on Optimism mainnet
  • Include a "send to Optimism" on Ethereum mainnet and Kovan

Bitcoin support

This is a big one.

A UTXO model breaks many assumptions in wallet land, including the idea of watching accounts for updates. There are a few major requirements

  • A web3-style API for Bitcoin
  • PSBT support, allowing more complex tx construction
  • Message signing support
  • More flexible chain data models to allow tracking single addresses (boo) or x/y/zpubs (yay)

Toggle Web3 hijacking

Tally can hijack MetaMask connections and act as the primary wallet, similar to NiftyWallet.

Some users might prefer that behavior, for others it's an inconvenience. Making it a configurable default is πŸ‘Œ

Arbitrum support

  • Include Arbitrum in the default network selection dropdown
    • Refactor ChainService to work with Alchemy + Arbitrum
    • Refactor IndexingService to work with Alchemy + Arbitrum
    • Include Arbitrum on Kovan
  • Include Arbitrum-specific token lists
  • Recognize Arbitrum bridge transactions in wallet activities
  • Recognize Arbitrum bridge transactions when signing
  • Support 0x on Arbitrum mainnet and Kovan
  • Include a "send to Arbitrum" on Ethereum mainnet and Kovan that uses the Arbitrum bridge

Rebuild past history for imported accounts

An empty account history sucks, and it makes migrating wallets or even browsers pretty inconvenient.

A combination of the Alchemy Transfers and Token APIs should do the trick.

  • Pull data in the backend (#126)
  • Reconstruct the account history for the API
  • Display past transactions + any token balances

Onboarding flow

  • - New Account/Wallet
  • - Import Metamask
  • - Hardware Wallet

  • - Revise design based on User Testing

Build system

Create Build System

needs:

  • build system should create a directory at the root of the project called dist
  • dist should contain the different build directories per browser platform
  • each one containing a manifest extended from _base.json with the particular platform specific manifest
  • each one should have this tree: (chrome reload should only be in dev mode. Exclude it from prod)
chrome
   β”œβ”€β”€ background.js
   β”œβ”€β”€ chromereload.js
   β”œβ”€β”€ content-script.js
   β”œβ”€β”€ inpage.js
   β”œβ”€β”€ manifest.json
   β”œβ”€β”€ public
   β”‚Β Β  └── popup.html
   └── ui.js

popup could be moved to the dir root, manifest:_base would need to be changed to reflect this public is all static files images etc.

DEV MODE:

  • yarn start should do dev mode
  • dev mode should allow for global process.env.NODE_ENV which should be 'development' or 'production' or 'test' (for now lets not worry to much on test mode extension test can get complicated and might require a special build process)
  • live reload yasss including chromereload

PROD:

  • exclude chromereload.js from manifest
  • zip each browser directory for publish

Up for negotiation:

  • separate dependencies into their own script from ui.js and background.js so scripts can be loaded faster this seen in mekamittens as bg-libs and ui-libs

currently the branch build has this functionality but needs to be cleaned up sense it was literally taken from mekamittens and paths were changed and some unnecessary code was deleted

Safari support

Safari now support Web Extensions! Unfortunately, hardware wallet support will require some additional, perhaps native, work.

  • Get the extension building for Safari
  • Publish a dev build Safari users can install manually
  • Package up a Safari extension for the app store (confirm licensing will work)

Investigate performance + extension size impact of bundling + minification

Since extensions are loaded locally rather than requiring network round-trips and bandwidth, I haven't been able to find strong evidence either way on whether bundling and minification provide a significant runtime impact. The downloaded extension itself is gzipped, so a lot of the file size improvement of minification most likely already comes from that compression process.

The goal here is to understand:

  • What the loading performance impact is of unminified code.
  • What the loading performance impact is of unbundled code.
  • What the loading performance impact is of bundled source maps, and whether browsers pick these up easily.
  • What the extension size impact is of unminified code.
  • What the extension size impact is of unbundled code.
  • What the extension size impact is of bundled source maps.

These can then be synthesized with any other concerns to make a decision about the best way to move forward on minification and bundling.

But Why?

One of the most developer-hostile things modern web technology does is obfuscate code. Source maps help, but require additional work and are often not included in production bundles. Tally being an open source project, we should encourage exploration and tinkering with the underlying source---the easiest way to do that is to give users and developers an already-usable code base with the shipped extension.

Earn

  • Farming
  • Single Farm
  • Pools
  • Single Pool
  • Withdraw farm + pool
  • Deposit farm + pool

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.