Git Product home page Git Product logo

eas-sdk's People

Contributors

0xclarity avatar izziaraffaele avatar kristoferlund avatar lbeder avatar michael-spengler avatar monique-baumann avatar mrsaints avatar slavik0329 avatar web3pm avatar xrdavies 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

eas-sdk's Issues

Wagmi compatibility hooks

Hi

I started working on an alternative frontend which uses this SDK with wagmi/viem. The frontend is part of Avalanche deployment of EAS which is being led by @cryptofish7: https://github.com/avax-attestations/aas-frontend

In the docs I found a link to a gist with some hooks which wrapped wagmi/viem clients in ethers compatible signer/provider, but the code was outdated (it was targeting ethers v5) so I had to adapt it. Here's the updated code which works with ethers v6:

// useProvider.ts
import { JsonRpcProvider, FallbackProvider } from "ethers";
import { type PublicClient } from "viem";
import { useState, useEffect } from "react";
import { usePublicClient } from "wagmi";


function publicClientToProvider(publicClient: PublicClient) {
  const { chain, transport } = publicClient;
  if (!chain) {
    return;
  }

  const network = {
    chainId: chain.id,
    name: chain.name,
    ensAddress: chain.contracts?.ensRegistry?.address
  };

  if (transport.type === "fallback") {
    return new FallbackProvider(
      (transport.transports).map(
        ({ value }: any) => new JsonRpcProvider(value?.url, network)
      )
    );
  }

  return new JsonRpcProvider(transport.url, network);
}

type Provider = ReturnType<typeof publicClientToProvider>

export function useProvider() {
  const publicClient = usePublicClient();
  const [provider, setProvider] = useState<Provider | undefined>(undefined);

  useEffect(() => {
    if (publicClient) {
      setProvider(publicClientToProvider(publicClient));
    }
  }, [publicClient]);

  return provider;
}
// useSigner.ts
import { useEffect, useState } from "react";
import { useWalletClient } from "wagmi";
import { type WalletClient } from "viem";
import { BrowserProvider, JsonRpcSigner } from "ethers";

export async function walletClientToSigner(walletClient: WalletClient) {
  const { account, chain, transport } = walletClient;
  if (!chain || !account) {
    return;
  }

  const network = {
    chainId: chain.id,
    name: chain.name,
    ensAddress: chain.contracts?.ensRegistry?.address
  };

  const provider = new BrowserProvider(transport, network);
  const signer = await provider.getSigner(account.address);

  return signer;
}

export function useSigner() {
  const { data: walletClient } = useWalletClient();

  const [signer, setSigner] = useState<JsonRpcSigner | undefined>(undefined);

  useEffect(() => {
    if (walletClient) {
      walletClientToSigner(walletClient).then((signer) => {
        setSigner(signer);
      })
    }
  }, [walletClient]);

  return signer;
}

If you want, I can create a PR that adds these hooks to a new module (wagmi-compat.ts) so that this functionality is more easily available to SDK users. The module would not be referenced by other modules in this package and users would have to import it directly with something like:

import { useSigner, useProvider } from "@ethereum-attestation-service/eas-sdk/wagmi-compat"

I would also add viem, wagmi and react as peer dependencies.

[BUG] Types JsonRpcProvider and SignerOrProvider are incompatible

This simple code doesn't work with ethers v6.7.1 and typescript v5.2.2:

ethers.ts

import { JsonRpcProvider } from 'ethers'

export const provider = new JsonRpcProvider(process.env.RPC_PROVIDER)

eas.ts

import { EAS } from '@ethereum-attestation-service/eas-sdk'
import { provider } from './ethers.js'

export const eas = new EAS(process.env.EAS_CONTRACT)

eas.connect(provider)
Argument of type 'JsonRpcProvider' is not assignable to parameter of type 'SignerOrProvider'.
  Type 'JsonRpcProvider' is not assignable to type 'Provider'.
    The types returned by 'getNetwork()' are incompatible between these types.
      Type 'Promise<import("d:/Desktop/Hackathons/Newforum/EAS/node_modules/ethers/lib.esm/providers/network", { assert: { "resolution-mode": "import" } }).Network>' is not assignable to type 'Promise<import("d:/Desktop/Hackathons/Newforum/EAS/node_modules/ethers/lib.commonjs/providers/network").Network>'.
        Type 'import("d:/Desktop/Hackathons/Newforum/EAS/node_modules/ethers/lib.esm/providers/network", { assert: { "resolution-mode": "import" } }).Network' is not assignable to type 'import("d:/Desktop/Hackathons/Newforum/EAS/node_modules/ethers/lib.commonjs/providers/network").Network'.
          Property '#private' in type 'Network' refers to a different member that cannot be accessed from within type 'Network'.ts(2345)

Error "provider wasn't set" when calling eas.getOffchain before setting provider

I understand that we need to inject a provider for legacy version detection when calling eas.getOffchain but the documentation is not made clear for this which causes the "provider wasn't set" error when people try to replicate the example.

eas-sdk/README.md

Lines 157 to 159 in 939a12a

const eas = new EAS(EASContractAddress);
const offchain = await eas.getOffchain();

From my opinion, there should be a better resolution for the provider. How about splitting signer and provider?

  • If both are set, respect them both.
  • If signer is set, provider isn't, infer the value from signer to provider.
  • If provider is set, signer isn't, error when execute write operations.
  • If none is set, provider is inferred with default providers, error when execute write operations. I suggest viem's chains for the defaults: https://github.com/wevm/viem/blob/main/src/chains/definitions

private data attestation insecure

Where can I review the code for your private data attestations?

In the docs you outline how to create private data attestations.
If the data space size is low, the attestation can be easily guessed.
For example a schema of
Name, Gender, over100k, credit score

Assuming the verifier knows his customer name, he can easily iterate through the possible values and guess the merkle root as there are only
2(gender)*2(over100k)*1000 different options.

To make it resistant each data needs to be paired with a random nonce node. (can be made deterministic for example by using the hash of the signed value by the recipient private key)

Offchain attestation that requires refUID

Hi, I'm in a situation where I have to create off-chain attestation that references an on-chain attestation.

Also, my schema resolver logic requires validating the attestation provided in refUID.

Due to the fix in this PR: #54, which set the refUID to be zero bytes 32 all the time, my resolver logic fails.

// Verify the offchain attestation onchain by simulating a contract call to attest. Since onchain verification
// makes sure that any referenced attestations exist, we will set refUID to ZERO_BYTES32.
await this.eas.contract.attest.staticCall(
{ schema, data: { recipient, expirationTime, revocable, refUID: ZERO_BYTES32, data, value: 0 } },

My question: could we allow simulating resolver with refUID: params.refUID || ZERO_BYTES32 ?

How to publish off-chain attestation by EAS-SDK?

We are ready to make off-chain attestation and publish it to query after.
But the SDK is just for making, how to publish it by EAS-SDK, and then display on the EAS platform.

Or some other suggestions for me.

How do we verify the private data matching given the data input?

Hi, I would like to know how we can use the private data attestation especially when it comes to validating if the given inputs match the output proof for the verifiers.
I came across this question after reading this part of the document: https://docs.attest.sh/docs/tutorials/private-data-attestations

For example, I was able to generate the following Proof Result from parts of the private data on the attestation:

{"leaves":[{"type":"string","name":"date_of_birth","value":"1997/1/1","salt":"0x69e42ffc6776c137dc9b3f55d129cb8ade03f246e2ed9ace36e9b5a65ea6c8e4"}],"proof":["0x5642f8152e7460dfd8917be8a736e4af0cbb34fd25daa1e4c03a315eec6854df"],"proofFlags":[false]}

Link to the attestation: https://sepolia.easscan.org/attestation/view/0x9035ad04e14aecf266c9353601e1e6821ef53f3327df03afcb222c91186205b8

Let's say I give this information to someone, how can that person validate if the leaves can produce the proof exactly?
It will be good if you can share the code reference of where this can be found.

Thank you.

SDK does not expose options to control transactions

The transactional methods such as attest or register exposed by EAS SDK should accept options (ethers Override) for on-chain transactions.

We need to customize:

  • gasLimit
  • gasPrice
  • nonce (for concurrent invocations)

Built-in IPFS support?

I see on EASScan that offchain attestations are added to IPFS (and pinned presumably). Are there plans to add IPFS support in eas-sdk via an external provider, or is this out of scope?

If out of scope, an example publishing to IPFS (e.g. via a local node) might be nice to ensure the data is formatted correctly and the resulting CID is as expected.

About Off-Chain Attestations

Hi guys, we want to use EAS's off-chain attestations in the upcoming EthGlobal Istanbul hackathon, but we had a few problems when pulling attestations with the api. After making the off-chain attestation, we can see the attestation thanks to the url on easscan.org, but when we try to pull it from the GraphQL Api, nothing appears on behalf of the attestation. When we manually publish to ipfs via easscan, we can then pull the attestation from GraphQL, but we need to do this programmatically. We need some help on this issue. I actually tried to reach you on twitter but I guess none of your dm boxes were open. You can find my twitter and discord handles in my github profile, it would be good if we can chat a bit about this

creating both onchain and offchain attestations example errors

**The examples for creating both onchain and offchain attestations generates various errors:

onchain: return [4 /yield/, signerOrProvider.call(tx, blockTag)];

offchain: 'invalid hexlify value' NOTE: leads to further errors even if value ignored.

please advise. thx.**

TypeError: (0 , ethers_1.toUtf8Bytes) is not a function

I am trying to integrate eas-sdk into a Next13 repo:

I have tried both version 1.5.0, and the beta 2.0.0v yet I can't get this working.

I am using Wagmi/Viem V2s EthersSigner adapter

My hook

import  { EAS, SchemaEncoder }  from "@ethereum-attestation-service/eas-sdk";
import { TransactionSigner } from "@ethereum-attestation-service/eas-sdk";
import { useEthersSigner } from "./userEthersSigner";
import { useEffect, useState } from "react";

// EAS Schema https://optimism.easscan.org/schema/view/0x081fc803f607b291b727b885a203d53b8cbb1488f6db1242327cca81db5f17ed

const easContractAddress = "0x4200000000000000000000000000000000000021";
const schemaUID = "0x081fc803f607b291b727b885a203d53b8cbb1488f6db1242327cca81db5f17ed";
const eas = new EAS(easContractAddress); // ERROR HERE: TypeError: (0 , ethers_1.toUtf8Bytes) is not a function

export const useEAS = () => {
  const [connectedEAS, setConnectedEAS] = useState<EAS | null>(null);
  const provider = useEthersSigner({ chainId: 10 });

  useEffect(() => {
    const connectEAS = async () => {
      if (provider) {
        eas.connect(provider); // TYPE ERROR HERE Argument of type  is not assignable to parameter of type Transaction Signer

      }
      setConnectedEAS(eas);
    }
    connectEAS();
  }, [provider])

  const attest = async (message: string, context: string) => {
     // Initialize SchemaEncoder with the schema string
  const schemaEncoder = new SchemaEncoder("string message,string context");
    const encodedData = schemaEncoder.encodeData([
      { name: "message", value: message, type: "string" },
      { name: "context", value: context, type: "string" }
    ]);
    const tx = await eas.attest({
      schema: schemaUID,
      data: {
        recipient: "0x0000000000000000000000000000000000000000",
        expirationTime: 0 as unknown as bigint,
        revocable: true, // Be aware that if your schema is not revocable, this MUST be false
        data: encodedData,
      },
    });
    const newAttestationUID = await tx.wait();
    console.log("New attestation UID:", newAttestationUID);
  }

  return { connectedEAS, attest };
}

I haven't been able to move this forward, looked into the open/closed issues on Github.

Include docs for generating offline link

Hi!
I'm working on a project using EAS where I can to create offchain signatures and embed as QR codes to be verified. The QR code should point to the EAS scanner so I'm trying to figure out how to generate the attestation id used in the URL.

For example I want to create a URL like this:
https://easscan.org/offchain/url/#attestation=eNqlkDuOHDEMRO%2FSccPgR%2Fwo3J3xXMJwIIlkNHCw8AB7fGv6CmZIFF8V69cBP0iPE88Dvj%2BQwB78%2BTmI2k9affHSu4yH8h1yojjdUtyOt5h7I4Xl4eXpNoOIu8wRK21WrvTszRqADi4MHllNqLv0DgARF0R8%2BAhPnW5qSxtgbFgY4KCp0ky2XyKRKwDv044LHaYqNMZ5nORvDtRE1XWPB7LbTaZyPQaJEVLvdbcJ6sV1mU5qpUmVXZSwS5ZoTlumOkoaAYUNJpHc2TFqUK%2FFCBOxUBdfEBcBSAddhWnNWwvZmWFoeOdKzNDSCcY%2BBbJx2FaRBXiuofiG7NrVwb3tRk64Fn%2B%2FXnk99H%2Bz8XD%2BeT2fv%2F8BTKB3Mg%3D%3D

From my research I've found that the id is a gzipped base64 encoded string (with encodeURIComponent).

I have been able to successfully decode it into a valid javascript array with the following:

const pako = require("pako")

const id = decodeURIComponent("eNqlkDuO...")
// Create buffer from decoded base64
const buffer = Buffer.from(atob(id), "binary");

// Unzip using pako
const decompressed = pako.inflate(buffer, { to: "string" });

This gives the following array:

[
    "0.26",
    1,                                                                    // version
    "0xA1207F3BBa224E2c9c3c6D5aF63D0eb1582Ce587",                         // verifying contract
    "0x394260c8d8f8e87bd22395badce7bfece8e9474006a3f1d3aef45298599000dd", // sig.r
    "0x58a8ad8e6b8767c6401de87d701a2b65475587e1228600399091c180b660431b", // sig.s
    28,                                                                   // sig.v
    "0x0fb166cDdF1387C5b63fFa25721299fD7b068f3f",                         // signer address
    "0xb24f6e2fe9562195ef56eb7c766af54202d7a3255e06a1dfa29fc310b11f16c3", // uid
    "0x85500e806cf1e74844d51a20a6d893fe1ed6f6b0738b50e43d774827d08eca61", // schema
    "0",                                                                  // ?
    1680884900,                                                           // message.time
    0,                                                                    // ?
    "0",                                                                  // ?
    true,                                                                 // message.revocable
    "0x0000000000000000000000000000000000000000000000000000000000000001", // message.data
    0,                                                                    // ?
    null                                                                  // ?
  ];

I should then be able to compress it into the original ID:

const compressed = pako.deflate(JSON.stringify(decompressed), { to: "string" });
encodeURIComponent(Buffer.from(compressed).toString("base64"));

I haven't been able to get the same ID as in the URL. This one starts with:
eJylkTlOA0AMRe%...t8AP0qn6m

Here's the code:
https://replit.com/@CarlBarrdahl/PakoTest#index.js

Questions:

  • How to properly encode the compressed data?
  • What are the variables in the array marked with ?

Grateful for any help!

Provide browser integration instructions (e.g. with React)

Hey guys!

Just thinking out loud here, but how cool would it be to have a little section in the docs about using the SDK in the frontend? ๐Ÿค” Especially after #46.

Oh, and speaking of making things easier, I made this little React package to help devs with the integration with React. Would be super cool if you could check it out and let me know what you think. ๐Ÿš€๐ŸŽธ

Repo: react-eas on Github
npm: react-eas on npm

BTW thanks for the amazing work you're dong at EAS! ๐Ÿ’ช๐Ÿ”ฅโญ

When sdk for private data proofs

  • sdk for creating private data attestations using merkle trees
  • sdk for creating proofs
  • smart contract code for validating proofs

Offchain Attestation Gives Error

so what happens is that,
as soon as the application reaches at the line

const offchain = await eas.getOffchain();

It gives the following error
Uncaught (in promise) TypeError: this.contract.getAddress is not a function

I am not using typescript, just simple javascript with react.

Got "missing r" error when using EAS + Metamask + etherjs

Issue detail

In our dApp https://app.fairsharing.xyz/, when we make an onchain attestaion call, metamask returned the error as below snapshot,

We use EAS + Metamask + etherjs. When we change wallet app to like OKX, it works well.

image

Who should fix this issue and how?

I found a relative issue ethers-io/ethers.js#3926, seems we have to wait for etherjs to fix?
Or metamask should get this fixed?

Or we have to replace etherjs?

Please help look into this issue, it is blocking many users using our dApp now.

@brycealan @slavik0329

Offchain attestation fails without refUID

This might just be a docs issue, however, the offchain example is failing for me because of refUID missing in the call to signOffchainAttestation as ethers runs into an issue when hashing:

/eas-sdk-test/node_modules/@ethersproject/bytes/lib/index.js:9
    return !!(value.toHexString);
                    ^

TypeError: Cannot read properties of undefined (reading 'toHexString')
    at isHexable (/eas-sdk-test/node_modules/@ethersproject/bytes/lib/index.js:9:21)
    at arrayify (/eas-sdk-test/node_modules/@ethersproject/bytes/lib/index.js:69:9)
    at _pack (/eas-sdk-test/node_modules/@ethersproject/solidity/lib/index.js:53:34)
    at /eas-sdk-test/node_modules/@ethersproject/solidity/lib/index.js:83:20
    at Array.forEach (<anonymous>)
    at pack (/eas-sdk-test/node_modules/@ethersproject/solidity/lib/index.js:82:11)
    at keccak256 (/eas-sdk-test/node_modules/@ethersproject/solidity/lib/index.js:89:39)
    at getOffchainUID (/eas-sdk-test/node_modules/@ethereum-attestation-service/eas-sdk/dist/utils.js:14:94)
    at Offchain.getOffchainUID (/eas-sdk-test/node_modules/@ethereum-attestation-service/eas-sdk/dist/offchain/offchain.js:59:43)
    at Offchain.signOffchainAttestation (/eas-sdk-test/node_modules/@ethereum-attestation-service/eas-sdk/dist/offchain/offchain.js:40:30)

Node.js v19.8.1

Setting refUID: '0x0000000000000000000000000000000000000000000000000000000000000000', solves this:

const newAttestationUID = await offchain.signOffchainAttestation({
  recipient: '0xFD50b031E778fAb33DfD2Fc3Ca66a1EeF0652165',
  // Unix timestamp of when attestation expires. (0 for no expiration)
  expirationTime: 0,
  // Unix timestamp of current time
  revocable: 0,
  time: 1671219636,
  nonce: 0,
  schema: "0xb16fa048b0d597f5a821747eba64efa4762ee5143e9a80600d0005386edfc995",
  refUID: '0x0000000000000000000000000000000000000000000000000000000000000000',
  data: encodedData,
}, signer);

Adding the revocable param has no influence, but worth noting if this is just a doc cleanup.

Error: use sdk to create on-chain attestation

i use sepolia testnet, code look like this:

import { EAS, SchemaEncoder } from "@ethereum-attestation-service/eas-sdk";

const eas = new EAS(EASContractAddress);
eas.connect(signer);

// Initialize SchemaEncoder with the schema string
const schemaEncoder = new SchemaEncoder("uint256 eventId, uint8 voteIndex");
const encodedData = schemaEncoder.encodeData([
  { name: "eventId", value: 1, type: "uint256" },
  { name: "voteIndex", value: 1, type: "uint8" },
]);

const schemaUID = "0xb16fa048b0d597f5a821747eba64efa4762ee5143e9a80600d0005386edfc995";

const tx = await eas.attest({
  schema: schemaUID,
  data: {
    recipient: "0xFD50b031E778fAb33DfD2Fc3Ca66a1EeF0652165",
    expirationTime: 0,
    revocable: true,
    data: encodedData,
  },
});

const newAttestationUID = await tx.wait();

console.log("New attestation UID:", newAttestationUID);

error:

Error: cannot estimate gas; transaction may fail or may require manual gas limit [ See: https://links.ethers.org/v5-errors-UNPREDICTABLE_GAS_LIMIT ] (error={"reason":"execution reverted","code":"UNPREDICTABLE_GAS_LIMIT","method":"estimateGas","transaction":{"from":"0xE65a34b090daF08C6C1eE4fDd35FCc5Ff794239C","maxPriorityFeePerGas":{"type":"BigNumber","hex":"0x59682f00"},"maxFeePerGas":{"type":"BigNumber","hex":"0x59682f12"},"to":"0xC2679fBD37d54388Ce493F1DB75320D236e1815e","data":"0xf17325e70000000000000000000000000000000000000000000000000000000000000020b1f077940c6b2d07d05412d11ef2c5bfd8fc9aadfc89ae87ec649640fc191e860000000000000000000000000000000000000000000000000000000000000040000000000000000000000000e65a34b090daf08c6c1ee4fdd35fcc5ff794239c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000562616a6965000000000000000000000000000000000000000000000000000000","type":2,"accessList":null}}, tx={"data":"0xf17325e70000000000000000000000000000000000000000000000000000000000000020b1f077940c6b2d07d05412d11ef2c5bfd8fc9aadfc89ae87ec649640fc191e860000000000000000000000000000000000000000000000000000000000000040000000000000000000000000e65a34b090daf08c6c1ee4fdd35fcc5ff794239c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000562616a6965000000000000000000000000000000000000000000000000000000","to":{},"from":"0xE65a34b090daF08C6C1eE4fDd35FCc5Ff794239C","type":2,"maxFeePerGas":{"type":"BigNumber","hex":"0x59682f12"},"maxPriorityFeePerGas":{"type":"BigNumber","hex":"0x59682f00"},"nonce":{},"gasLimit":{},"chainId":{}}, code=UNPREDICTABLE_GAS_LIMIT, version=abstract-signer/5.7.0)

    at Logger.Object.<anonymous>.Logger.makeError (/Users/weiguangchao/binglian/eas-demo/node_modules/@ethersproject/logger/src.ts/index.ts:269:28)
    at Logger.Object.<anonymous>.Logger.throwError (/Users/weiguangchao/binglian/eas-demo/node_modules/@ethersproject/logger/src.ts/index.ts:281:20)
    at /Users/weiguangchao/binglian/eas-demo/node_modules/@ethersproject/abstract-signer/src.ts/index.ts:301:31
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async Promise.all (index 7)

and i also meet some error when use web app, link is https://sepolia.easscan.org/attestation/attestWithSchema/0xb1f077940c6b2d07d05412d11ef2c5bfd8fc9aadfc89ae87ec649640fc191e86

image

thanks.

Please add some examples for delegated attestation and delegated proxy attestation

Hi @slavik0329 , I see we only have on-chain/off-chain attestation examples.

Please add some examples about delegated on-chain attestation, as well as some delegated proxy on-chain attestation.

Thanks. โค๏ธ

Currently I am using the code from the tests. I use signDelegatedProxyAttestation on server side, then use attestByDelegationProxy on the client side, to achieve this feature: "you have a single entity like a KYC provider attesting to many users while wanting the users to pay for the gas" . I haven't get it work correctly.

Why make off-chain didn't pass the resolver contract?

I create the scheme with the resolver contract.
But when I make the off-chain attestation, it seems that just sign the data without passing the resolver contract.
Is this reasonable? Would you consider improving it in the future?

ps: I read the docs about Resolver Contracts, which didn't indicate about off-chain.

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.