Coder Social home page Coder Social logo

symbol / catapult-rest Goto Github PK

View Code? Open in Web Editor NEW
43.0 29.0 32.0 3.62 MB

Catapult REST combines HTTP and WebSockets to perform read and write actions on the blockchain

Home Page: https://docs.symbolplatform.com/api.html

JavaScript 99.31% Python 0.16% HTML 0.50% Shell 0.01% Dockerfile 0.03%
symbol rest api

catapult-rest's Introduction

catapult-rest's People

Contributors

anthonylaw avatar dependabot[bot] avatar dgarcia360 avatar fboucquez avatar gimer avatar gimre-xymcity avatar jaguar0625 avatar jontey avatar martinayora avatar rg911 avatar segfaultxavi avatar vektrat avatar yilmazbahadir 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

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

catapult-rest's Issues

Add route/module for p2p endpoint(s)

I am facing an issue that currently I don't seem to be able to find out peer neighborhood and peer lists from a connection through catapult-rest.

I have come to know that catapult-server comes with a P2P API on port 8000, but our SDK currently doesn't provide with an integration of that gateway.

Two possibilities arrise here as we may implement this in the SDK connecting through port 8000 (not optimal.) or catapult-rest could provide with following proposed endpoint:

  • /peers: Get the list of neighbours for a node

This can, of course, be named differently if you have better suggestions.

Need clarification about mosaics

Hi,

I don't understand why the mosaics of the nemesis accounts have different ids from the mosaics received in the first transaction.

Account has mosaics with ids [3555157025, 1492784701] and [3375658510, 1046278526]

c_mosaics_2

Transaction has mosaics [3294802500, 2243684972] and [3084986652, 2484246962]

c_mosaics_1

Could you clarify ?

Thanks

[cleanup] codec registration

(1) should be able to disable warning

    /* eslint-disable-next-line no-unused-vars */
    registerCodecs: codecBuilder => {}

=>

    registerCodecs: () => {}

(2) rest accountLink plugin is unneeded (use empty instead).

MetadataTransaction & MosaicRestrictionTransaction payload in wrong format

Noticed that defined schemas are not picked up when there are multiple transaction types (schemas) defined in one class, even though all fields modelType are correct.

  • metadata
  • mosaicRestriction

example payload below:

"transaction": {
    "signer": "9F784BF20318AE3CA6246C0EC2207FE095FFF7A84B6787E7E3C2CE4C3B92A2EA",
    "version": 36865,
    "type": 16708,
    "targetPublicKey": "n3hL8gMYrjymJGwOwiB/4JX/96hLZ4fn48LOTDuSouo=",
    "scopedMetadataKey": "1000",
    "valueSizeDelta": 10,
    "valueSize": 10,
    "value": "AAAAAAAAAAAAAA=="
}

"transaction": {
    "signer": "9F784BF20318AE3CA6246C0EC2207FE095FFF7A84B6787E7E3C2CE4C3B92A2EA",
    "version": 36865,
    "type": 16964,
    "targetPublicKey": "n3hL8gMYrjymJGwOwiB/4JX/96hLZ4fn48LOTDuSouo=",
    "scopedMetadataKey": "1000",
    "targetMosaicId": "5263764235315548820",
    "valueSizeDelta": 10,
    "valueSize": 10,
    "value": "AAAAAAAAAAAAAA=="
}

"transaction": {
    "signer": "9F784BF20318AE3CA6246C0EC2207FE095FFF7A84B6787E7E3C2CE4C3B92A2EA",
    "version": 36865,
    "type": 17220,
    "targetPublicKey": "n3hL8gMYrjymJGwOwiB/4JX/96hLZ4fn48LOTDuSouo=",
    "scopedMetadataKey": "1000",
    "targetNamespaceId": "-681912933029472786",
    "valueSizeDelta": 10,
    "valueSize": 10,
    "value": "AAAAAAAAAAAAAA=="
}

please refactor key or address parameter parsing

const getParams = req => {
  if (req.params.publicKeys && req.params.addresses)
    throw errors.createInvalidArgumentError('publicKeys and addresses cannot both be provided');

  const idOptions = Array.isArray(req.params.publicKeys)
    ? { keyName: 'publicKeys', parserName: 'publicKey', type: AccountType.publicKey }
    : { keyName: 'addresses', parserName: 'address', type: AccountType.address };

  const accountIds = routeUtils.parseArgumentAsArray(req.params, idOptions.keyName, idOptions.parserName);

Fetch transactions by Address

In the endpoints, it should be possible using the address as well.

Motivation

Often, you don't know the public key, just the address. Go to the address info, get the public key and then fetch the transactions can be done, but it's not as direct as being able to fetch directly using the Address.

How to config the CORS

I am using the javascript SDK to announce transaction to the network. However, I am getting the error on the browse
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

I am just wondering how to set the Access Control Allow Origin for the rest server.

Thanks

Refactor project structure

plugins
   \- mosaic
       \- routes
       \- db
   \- namespace
       \- routes
       \- db
  • keep processor files within their plugins
  • consider doing this for the SDK as well plugin_name/schema.js

Duration format in MosaicDefinitionTransaction is not correct

Duration value format in the MosaicDefinitionTransaction payload should be number array rather than string.

{
    "meta": {
        "height": [
            10847,
            0
        ],
        "hash": "F35AEB1E375A267655E600EF3765397E38C26DF1BB7738DFA315F90BA8488093",
        "merkleComponentHash": "F35AEB1E375A267655E600EF3765397E38C26DF1BB7738DFA315F90BA8488093",
        "index": 0,
        "id": "5D4C046D706E7200012971F7"
    },
    "transaction": {
        "signature": "9DA67B584F6F77E7D73599C6384CA4133394AE6D36C85E91A2A9CE5EB3ACEF4555F25ED98F12DD0E387300BDF53B21B9E3B2D4E98848EBBB42FEF0DAD5315E01",
        "signer": "9F784BF20318AE3CA6246C0EC2207FE095FFF7A84B6787E7E3C2CE4C3B92A2EA",
        "version": 36865,
        "type": 16705,
        "maxFee": [
            0,
            0
        ],
        "deadline": [
            2722133455,
            24
        ],
        "cosignatures": [],
        "transactions": [
            {
                "meta": {
                    "height": [
                        10847,
                        0
                    ],
                    "aggregateHash": "F35AEB1E375A267655E600EF3765397E38C26DF1BB7738DFA315F90BA8488093",
                    "aggregateId": "5D4C046D706E7200012971F7",
                    "index": 0,
                    "id": "5D4C046D706E7200012971F8"
                },
                "transaction": {
                    "signer": "9F784BF20318AE3CA6246C0EC2207FE095FFF7A84B6787E7E3C2CE4C3B92A2EA",
                    "version": 36865,
                    "type": 16717,
                    "nonce": -2054142337,
                    "id": "8010629975985322872",
                    "flags": 7,
                    "divisibility": 3,
                    "duration": "0"
                }
            }
        ]
    }
}

message property on a transfer transaction is undefined and other stuff.

The first transaction has the message property but the second doesn't. It let's into a SDK error since it expects that property to be set.

Setup:

  • latest catapult-service-boostrap
  • nem2-sdk-ts: 0.11.3
[{
  "meta": {
    "height": [128, 0],
    "hash": "B6FC3A5DADEE2F3969E48B56F25BCDE0C9FACE4530B7204C95F6E8A4C7DD5DC8",
    "merkleComponentHash": "B6FC3A5DADEE2F3969E48B56F25BCDE0C9FACE4530B7204C95F6E8A4C7DD5DC8",
    "index": 0,
    "id": "5CB1CCD7E5CE8C0001443474"
  },
  "transaction": {
    "signature": "F89E2809ADFC552DE46E633817F1E40B993733314A64E17C66C749AAE27A6387C2D229D9ABAD386EDFBE9D8812A1FB273CE486240327E78E9EBD20E47BE5CC05",
    "signer": "64371CA35D48FCD86E595338561B5663936A9F6A72650366D582A46FF87E6C39",
    "version": 36867,
    "type": 16724,
    "maxFee": [0, 0],
    "deadline": [1205290169, 22],
    "recipient": "90E4D933EA51957D8F23DFC90B4D247D82190ABCCE874663EC",
    "message": {
      "type": 0,
      "payload": ""
    },
    "mosaics": []
  }
}, {
  "meta": {
    "height": [1, 0],
    "hash": "B079B040D6CA64F2B5EA4077E591F0A02F1D7EFA2A39FEBA1FB2783520AB49BB",
    "merkleComponentHash": "B079B040D6CA64F2B5EA4077E591F0A02F1D7EFA2A39FEBA1FB2783520AB49BB",
    "index": 12,
    "id": "5CB1C59CE5CE8C0001443360"
  },
  "transaction": {
    "signature": "0D21346C33920D61540E6CCA40F244C1735765F2256A7190ADF0004B4A3D0AF7D09A4DDDCC8E2E184D6006B19236743D1D534EB768F578164708B99A9B781103",
    "signer": "ED0BFF623BCB7C7B454BE035BA575CE941762476F866F3086082ACB74A9F1887",
    "version": 36867,
    "type": 16724,
    "maxFee": [0, 0],
    "deadline": [1, 0],
    "recipient": "90E4D933EA51957D8F23DFC90B4D247D82190ABCCE874663EC",
    "mosaics": [{
      "id": [3294802500, 2243684972],
      "amount": [3863990592, 95248]
    }, {
      "id": [3084986652, 2484246962],
      "amount": [2000000, 0]
    }]
  }
}]

If there is no outgoing transaction, should the public key of AccountDTO return null

When get account (that is no outgoing transaction) info by Catapult rest api /account/:accountId , public key return 0000000000000000000000000000000000000000000000000000000000000000
Using this PublicKey will be the address 'SAXQUTQQNS6JEJG7PLC6FRVJ2USS44GLMXG4DOF2' when MIJIN_TEST.

I think there is a concern that you get the public key from the address in the API and accidentally create an aggregate transaction using this public key.

So, I think that should return null like NIS1 when returning the public key of an account with no outgoing transaction in the API.

Monitoring changes to multisig account information

Given the following scenario:

  1. There are two regular accounts A and B, one multisg account M, cosigned by account A.
  2. Announce a multisigModify transaction that removes A as a cosigner of M and adds B as a cosigner of M.

In NIS 1, it is possible to listen for the confirmation of the transaction by listening to:

  • Confirmed transactions of A
  • Confirmed transactions of B
  • Confirmed transactions of M

However in catapult, the way to check if the transaction has gone through is by listening to:

  • confirmedAdded of A
  • confirmedAdded of M

It seems that because it doesn't involve the signature of B, and the receiver is M, B never gets notified that it is added as a cosigner of another account.

Looking at the documentation in https://nemtech.github.io/api/websockets.html, I think account B should be notified of the transaction as it is "related to the address"

Take over building of catapult rest images

Migrated from maniphest tasks.

Npm packages could probably be built and published automatically using travis.

Additionally for release, docker images are needed.

Release docker images should be pushed to TB docker repository.

(some older scripts provided to the team P216 P217)

Account restriction endpoints error

When calling account/{key}/restrictions internal error returned:

InternalError: Cannot read property \'restrictionType\' of undefined\n    at Object.toRestError (/node_modules/catapult-api-rest/_build/server/errors.js:31:5)\n    at toRestError (/node_modules/catapult-api-rest/_build/server/bootstrapper.js:33:27)\n    at result.catch.err (/node_modules/catapult-api-rest/_build/server/bootstrapper.js:130:13)\n    at process._tickCallback (internal/process/next_tick.js:68:7)

Fix/update spammer subproject

The spammer is currently out of date when creating transactions, since they have changed, update it so that the tests pass again

Relatively low prio

MosaicDefinitionTransaction mosaicNonce vs nonce

According to the Open API 3 spec,

https://github.com/nemtech/nem2-openapi/blob/master/spec/openapi3.yaml

the nonce property of MosaicDefinitionTransactionDTO is "mosaicNonce" but the server is returning "nonce" as the JSON below.

The Java SDK heavily relies on the generate clients and DTOs from the Open API spec. If there is an inconsistency like this the DTO won't be parsed correctly. The solution would be to either change the open API spec or change or the catapult-rest model object. What do you think @dgarcia360?

{  
   "transaction":{  
      "signature":"7EAEA998D0FA78F96E9CF8FE3AFF3CE39F6FDC67CD38EFEC1670F7BE7C6A3C7AAAAA2BE108126AA855C5548F5BD109B9D4227A9156DC31CF243F501D9E33F10C",
      "signer":"69970C5FB7A72662A6457504851DC11B10B19EB8A7D8C5E22301F1DC7492F292",
      "version":36865,
      "type":16717,
      "maxFee":[  
         0,
         0
      ],
      "deadline":[  
         4002752628,
         24
      ],
      "nonce":1493805961,
      "mosaicId":[  
         319533547,
         672276418
      ],
      "properties":[  
         {  
            "key":0,
            "value":[  
               3,
               0
            ]
         },
         {  
            "key":1,
            "value":[  
               4,
               0
            ]
         },
         {  
            "key":2,
            "value":[  
               100,
               0
            ]
         }
      ]
   },
   "meta":{  
      "hash":"92C12CFC091788B7FF10ACE45DB6B6C37F299152E09DB889C2716118C5FFFF67",
      "merkleComponentHash":"92C12CFC091788B7FF10ACE45DB6B6C37F299152E09DB889C2716118C5FFFF67",
      "height":[  
         11749,
         0
      ],
      "channelName":"confirmedAdded"
   }
}

Get mosaic information by namespaceId

Discussion about the possibility to get the mosaic information by NamespaceId.

⚠️ This enhancement is not planned to be implemented at the moment, requiring further discussion.

Motivation

To get the mosaic information using the linked NamespaceId, we need to:

  1. Call /namespace/{:namespaceId} and get the aliased mosaicId.
  2. Call /mosaic/{:mosaicId} and get the mosaic information.

From the developer point of view, it will be easier to get the mosaic info using the NamespaceId directly. It will also reduce parsing in the client-side code the MSB to determine if the id belongs to a mosaic or namespace.

Specification

Option A

Change /mosaic/{:mosaicId} to /mosaic/{:mosaicId|:namespaceId}

Issues

Looking at the current architecture seems not correct to merge MosaicIds and NamespaceIds in a route that belongs to the mosaic plugin.

Alias - under namespace plugin - links namespaces with mosaics. To enable this behavior, it should be under "namespace" plugin, so it cannot be named /mosaic/:namespaceId since it will conflict with /mosaic/:mosaicId.

Option B

To be discussed.

Merkle tree endpoint not working (error 500)

Reported by @evias, quoting:

with latest catapult service + rest, when I call /block/1/transaction/83975B0DDD702E03B5B712985A502B8F86C3F69ECAB01C48D2BEBE501A053C24/merkle
I get {"code":"Internal","message":"Cannot read property 'queryDocument' of undefined"}

Peer discovery API call

it would be nice to have an api for fetching the neighboring nodes

this is critical for a private chain for building a monitoring system where we can uncover the network by crawling all the nodes then monitor each of them for anomalies.

Allow in the endpoint of receive transactions given an account to be sorted by height ASC and DESC.

In the endpoints

should be a query param to ask the transactions ordered by block height ascendant or descendant.

Motivation

The library nonfungible-asset will benefit due to be able to read the transactions in batches instead of loading all transactions in memory and then reverse the order.

Travis builds failing

Travis is failing with the follwing when computing coverage:

----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |        0 |        0 |        0 |        0 |                   |
----------|----------|----------|----------|----------|-------------------|
[error] "2019-06-27T13:37:41.474Z"  'error from lcovParse: ' 'Failed to parse string'
[error] "2019-06-27T13:37:41.476Z"  'input: ' ''
[error] "2019-06-27T13:37:41.476Z"  'error from convertLcovToCoveralls'
/home/travis/build/nemtech/catapult-rest/catapult-sdk/node_modules/coveralls/bin/coveralls.js:18
        throw err;
        ^
Failed to parse string
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
The command "cd ${SUBPROJECT} && yarn run test:travis" exited with 1.

The issue here is that thenyc report is empty, thus coveralls input is malformed and ends up failing when being parsed.

There error started appearing between the following builds, and is not due to dev updates

response payload mismatch between websocket monitor response payload

Symptom

Rest response payload mismatch between websocket monitor response payload e.g. transaction confirmed and Rest endpoint response payload account/{publicKey}/transactions.

Example (AccountPropertyAddress Transaction):
  • Monitor response is using modificationType inside modifications array
    modifications: 
    [ { modificationType: 1,
        value: '903EFA58C54681F5FBA106055676178960E4510944EA06ACBB' } ]
    
  • Rest endpoint (transaction list) e.g. account/{publicKey}/transactions uses type
  modifications: 
  [ { type: 1,
      value: '903EFA58C54681F5FBA106055676178960E4510944EA06ACBB' } ]

Affect:

  • Account Property Transactions (all 3) : modificationType -> type
  • Account Link Transaction: actionType -> type
  • Address Alias Transaction: actionType -> type
  • Mosaic Alias Transaction: actionType -> type

NamespceId in transaction payload is in wrong format

Expecting id in number[] format but got long

example payload:

{
    "meta": {
        "height": [
            80925,
            0
        ],
        "hash": "63ADB80976843F676FEA71F4519130B327CF92D7B1C06CBF3FE6FDAEBFB7882E",
        "merkleComponentHash": "63ADB80976843F676FEA71F4519130B327CF92D7B1C06CBF3FE6FDAEBFB7882E",
        "index": 0,
        "id": "5D5C128C706E7200012CA0AB"
    },
    "transaction": {
        "signature": "264AB8715FDBCB66D34E91DFCD715A13AF23E16374091FCB979280E6E6F86E8452759B8C9EF5C8EBFA45164CDD86B2A045C3647E7448E5DF8CC7FBEE3B59F904",
        "signer": "9F784BF20318AE3CA6246C0EC2207FE095FFF7A84B6787E7E3C2CE4C3B92A2EA",
        "version": 36865,
        "type": 16718,
        "maxFee": [
            0,
            0
        ],
        "deadline": [
            3774321935,
            24
        ],
        "registrationType": 0,
        "duration": [
            1000,
            0
        ],
        "id": "-681912933029472786",
        "name": "root-test-namespace-9562"
    }
}

Choose different prefix for secret lock/proof and lock funds status errors

The status errors related to secret lock/proof and locks funds transactions share the same prefix Failure_Lock_.

The current naming makes challenging to know what failed rapidly since they are separate entities, but the error prefix is shared.

List of affected errors:

    case 0x804C0001: return 'Failure_Lock_Invalid_Hash_Algorithm';
    case 0x804C0002: return 'Failure_Lock_Invalid_Mosaic_Id';
    case 0x804C0003: return 'Failure_Lock_Invalid_Mosaic_Amount';
    case 0x804C0004: return 'Failure_Lock_Hash_Exists';
    case 0x804C0005: return 'Failure_Lock_Hash_Does_Not_Exist';
    case 0x804C0006: return 'Failure_Lock_Missing_Secret_Padding';
    case 0x804C0007: return 'Failure_Lock_Hash_Not_Implemented';
    case 0x804C0008: return 'Failure_Lock_Proof_Size_Out_Of_Bounds';
    case 0x804C0009: return 'Failure_Lock_Secret_Mismatch';
    case 0x804C000A: return 'Failure_Lock_Unknown_Secret';
    case 0x804C000B: return 'Failure_Lock_Inactive_Hash';
    case 0x804C000C: return 'Failure_Lock_Inactive_Secret';
    case 0x804C000D: return 'Failure_Lock_Hash_Algorithm_Mismatch';
    case 0x804C000E: return 'Failure_Lock_Hash_Already_Used';
    case 0x804C000F: return 'Failure_Lock_Secret_Already_Used';
    case 0x804C0010: return 'Failure_Lock_Invalid_Duration';

/mosaics endpoint not working (error 500)

error 500 InternalError: value.getLowBitsUnsigned is not a function

the /mosaics endpoint is currently failing due to a change in how properties are represented at the database level, mosaic properties should be an object including id and value

Add endpoints for retrieval of network (node) configuration

With multiple catapult networks available, it may be useful to be able to retrieve network configuration from network nodes through catapult-rest endpoints.

The config-network.properties file contains several settings that are needed in client integrations.

Important for Multi-Network Compatibility:

  • blockGenerationTargetTime = 15s: Used for date displays and date estimations.
  • namespaceGracePeriodDuration = 2m: Used for notifications about namespace expiration
  • currencyMosaicId = ..: Used to identify the currency mosaic on the network
  • harvestMosaicId = ..: Used to identify the harvest mosaic on the network
  • epochAdjustment = ..: Used to adjust timestamp of nemesis block

Important for Fee estimations:

  • minFeeMultiplier = 100: Used for fee estimations. (node specific)
  • rootNamespaceRentalFeePerBlock = 1'000'000: Used for fee estimations.
  • childNamespaceRentalFee = 100'000'000: Used for fee estimations.
  • mosaicRentalFee = 500'000'000: Used for fee estimations.

Important for User Experience:

  • maxRollbackBlocks = 40: Useful for transaction persistence.
  • maxTransactionsPerAggregate = 1'000: Useful for form validation.
  • maxCosignaturesPerAggregate = 15: Useful for form validation.
  • lockedFundsPerAggregate = 10'000'000: Useful for feature compatibility.
  • maxHashLockDuration = 2d: Useful for notifications or general UX.
  • maxSecretLockDuration = 30d: Useful for notifications or general UX.
  • minProofSize = 1: Useful for form validation.
  • maxProofSize = 1000: Useful for form validation.
  • maxMosaicDuration = 3650d: Useful for form validation.
  • maxMosaicDivisibility = 6: Useful for form validation.
  • minNamespaceDuration = 1m: Useful for form validation.
  • maxNamespaceDuration = 365d: Useful for form validation.
  • reservedRootNamespaceNames = xem, nem, user, account, org, com, biz, net, edu, mil, gov, info: Useful for form validation.
  • maxAccountRestrictionValues = 512: Useful for notifications or general UX.
  • maxMosaicRestrictionValues = 20: Useful for notifications or general UX.
  • maxMessageSize = 1024: Useful for form validation.
  • maxNameSize = 64: Useful for form validation.
  • maxChildNamespaces = 500: Useful for notifications or general UX.
  • maxNamespaceDepth = 3: Useful for form validation.
  • maxMultisigDepth = 3: Useful for form validation.
  • maxCosignersPerAccount = 10: Useful for notifications of general UX.
  • maxCosignedAccountsPerAccount = 5: Useful for form validation.

If some of those fields seem to be less important to retrieve (mostly "form validation"), they do allow much smoother multi-network capabilities for out client integrations (wallets / explorers / cli / sdk).

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.